From 698f79d5830b5e4270cb42b877db9ca3e35d0b20 Mon Sep 17 00:00:00 2001 From: HapeLee <1321903405@qq.com> Date: Tue, 28 Oct 2025 19:45:15 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=BAWebView=E5=A2=9E=E5=8A=A0=E8=AF=8D?= =?UTF-8?q?=E5=85=B8=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../legado/app/ui/rss/read/VisibleWebView.kt | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/app/src/main/java/io/legado/app/ui/rss/read/VisibleWebView.kt b/app/src/main/java/io/legado/app/ui/rss/read/VisibleWebView.kt index 0e6e1b40b..d9a790406 100644 --- a/app/src/main/java/io/legado/app/ui/rss/read/VisibleWebView.kt +++ b/app/src/main/java/io/legado/app/ui/rss/read/VisibleWebView.kt @@ -1,17 +1,112 @@ package io.legado.app.ui.rss.read +import android.annotation.SuppressLint import android.content.Context import android.util.AttributeSet +import android.view.ActionMode +import android.view.Menu +import android.view.MenuItem import android.view.View import android.webkit.WebView +import androidx.appcompat.app.AppCompatActivity +import io.legado.app.R +import io.legado.app.ui.dict.DictDialog +@SuppressLint("SetJavaScriptEnabled") class VisibleWebView( context: Context, attrs: AttributeSet? = null ) : WebView(context, attrs) { + init { + settings.javaScriptEnabled = true + settings.domStorageEnabled = true + } + override fun onWindowVisibilityChanged(visibility: Int) { super.onWindowVisibilityChanged(View.VISIBLE) } + override fun startActionMode(callback: ActionMode.Callback?): ActionMode { + val wrappedCallback = createWrappedCallback(callback) + return super.startActionMode(wrappedCallback) + } + + override fun startActionMode(callback: ActionMode.Callback?, type: Int): ActionMode { + val wrappedCallback = createWrappedCallback(callback) + return super.startActionMode(wrappedCallback, type) + } + + private fun createWrappedCallback(original: ActionMode.Callback?): ActionMode.Callback { + return object : ActionMode.Callback { + override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean { + val result = original?.onCreateActionMode(mode, menu) ?: false + menu.add(Menu.NONE, MENU_ID_DICT, 0, R.string.dict) + getSelectedText { /* 触发缓存*/ } + return result + } + + override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean { + updateDictMenuItem(menu) + return original?.onPrepareActionMode(mode, menu) ?: false + } + + override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean { + when (item.itemId) { + MENU_ID_DICT -> { + getSelectedText { selectedText -> + if (selectedText.isNotBlank()) { + showDictDialog(selectedText) + } + } + mode.finish() + return true + } + else -> { + return original?.onActionItemClicked(mode, item) ?: false + } + } + } + + override fun onDestroyActionMode(mode: ActionMode) { + original?.onDestroyActionMode(mode) + } + } + } + + private fun updateDictMenuItem(menu: Menu) { + val dictItem = menu.findItem(MENU_ID_DICT) + dictItem?.let { item -> + getSelectedText { selectedText -> + item.isEnabled = selectedText.isNotBlank() + } + } + } + + private fun getSelectedText(callback: (String) -> Unit) { + evaluateJavascript("(function(){return window.getSelection().toString();})()") { result -> + val selectedText = result + ?.removeSurrounding("\"") + ?.replace("\\n", "\n") + ?.replace("\\t", "\t") + ?.replace("\\\"", "\"") + ?: "" + callback(selectedText) + } + } + + private fun showDictDialog(selectedText: String) { + val activity = context as? AppCompatActivity + activity?.let { + val dialog = DictDialog(selectedText) + it.supportFragmentManager.beginTransaction() + .add(dialog, "DictDialog") + .commitAllowingStateLoss() + } + } + + companion object { + private const val MENU_ID_DICT = 1001 + } + } \ No newline at end of file