Android WebView 使用JS扩选的问题:我的需求是当用户选择webview的文本内容的时候,首次的长按的时候帮助用户选择整段,后续用户扩选的时候,自动帮用户选择整句。
我的思路是当原生这边创建系统菜单的时候(也就是用户开始选择之后),调用js,通过js的Selection API去做一个扩选。比如使用了下面的代码:
function modify() { function forwardWord(selection) { var focusNode = selection.focusNode; var range = selection.getRangeAt(0); range.setEnd(range.endContainer, focusNode.textContent.length); selection.addRange(range); } let selection = window.getSelection(); selection.modify("extend", "backward", "paragraphboundary"); forwardWord(selection); console.log("selection.toString()", selection.toString()); return selection.toString();}
调用了该Js之后,发现是能扩选成功的,但是系统的菜单就不再出现了,光标也不展示了。
其中,系统菜单是在长按的时候出现的那些例如:复制,全选,分享之类的系统自带的。
我是通过重写WebView的startActionMode(ActionMode.Callback callback)
和startActionMode(ActionMode.Callback callback, int type)
方法,创建自己的Callback代理,例如:
fun proxyWebMenuCallback(callback: ActionMode.Callback, noticeH5: () -> Unit): ActionMode.Callback { return if (SdkVersion.maxThanM()) { WebViewMenuCallback2(callback, noticeH5) } else { WebViewMenuCallback(callback, noticeH5) }}@SuppressLint("NewApi")class WebViewMenuCallback2( private val callback: ActionMode.Callback, private val noticeH5: () -> Unit) : ActionMode.Callback2() { override fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean { return callback.onCreateActionMode(mode, menu).also { LogUtil.d("WebViewMenuCallback2", "onCreateActionMode:$it") } } override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?): Boolean { noticeH5() return callback.onPrepareActionMode(mode, menu).also { LogUtil.d("WebViewMenuCallback2", "onPrepareActionMode:$it") } } override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?): Boolean { return callback.onActionItemClicked(mode, item).also { LogUtil.d("WebViewMenuCallback2", "onActionItemClicked:$it") } } override fun onDestroyActionMode(mode: ActionMode?) { callback.onDestroyActionMode(mode).also { LogUtil.d("WebViewMenuCallback2", "onDestroyActionMode:$it") } } override fun onGetContentRect(mode: ActionMode?, view: View?, outRect: Rect?) { if (callback is ActionMode.Callback2) { callback.onGetContentRect(mode, view, outRect) } else { super.onGetContentRect(mode, view, outRect) } }}class WebViewMenuCallback( private val callback: ActionMode.Callback, private val noticeH5: () -> Unit) : ActionMode.Callback { override fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean { return callback.onCreateActionMode(mode, menu) } override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?): Boolean { noticeH5() return callback.onPrepareActionMode(mode, menu) } override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?): Boolean { return callback.onActionItemClicked(mode, item) } override fun onDestroyActionMode(mode: ActionMode?) { callback.onDestroyActionMode(mode) }}
我的想法是在创建菜单的监听中去执行JS代码进行扩选,但是无论我把noticeH5
回调放在onPrepareActionMode
还是onCreateActionMode
中调用,还是noticeH5
的实现是会通过postDelay
去调用JS,结果都是扩选成功,但是菜单却被隐藏了,光标不见了。
然后我尝试在执行JS完成之后,例如:
evaluateJavascript("javascript:" + js, value -> { postDelay(1000){ //performLongClick(); //showContextMenu(); } } );
都不起效,无论是否一起调用。
后面我尝试在自定义菜单也不可以。
还尝试了自定义菜单,然后在执行完成JS之后,调用startActionMode
方法,发现是会出现菜单的,但是菜单的位置出现不正确,而且光标也不见了,同时该方法还只能去设置执行一次,否则会陷入死循环,因为调用该方法之后,Callback里面的方法又开始执行了。
最后尝试了全部逻辑交由JS实现,结果就是js的菜单位置,扩选啥的都能直接做到,但是却不能自由选择了,光标没有了。
我的想法是这是否是Chrome的Bug,即在JS扩展选区的时候不能同步到原生端?因为扩选选区之后是会回调Callback的onGetContentRect
方法的,我还在给官方提了bug,但是暂时也没有回应。When JavaScript expand the selection,WebView ContextMenu aoto dimiss
请问应该如何实现JS扩展选区,扩选之后菜单能保持在正确的位置。
PS: 小米浏览器有一个扩选的功能,而且扩选之后是可以正常展示菜单和光标的。或者有知道小米的是如何实现的吗?
最终是修改了方案实现,用户可以自由复制,端上通过自定义Callback实现全自定义菜单。通过开源方案选择完整句子get-selection-more,对开源的方案进行了优化,增加了换行补充。
本文向大家介绍iOS中长按调出菜单组件UIMenuController的使用实例,包括了iOS中长按调出菜单组件UIMenuController的使用实例的使用技巧和注意事项,需要的朋友参考一下 UIMenuController的使用 UIMenuController的展现需要基于一个View视图,其交互则需要基于其所在View视图的Responder。举例来说,如果一个UIMenuCont
本文向大家介绍Android 实现长按弹出PopupMenu 菜单栏,包括了Android 实现长按弹出PopupMenu 菜单栏的使用技巧和注意事项,需要的朋友参考一下 在Android中的SDK3.0版本以后加入了一个特殊的菜单效果,它可以在任何的View上显示,根据View的位置显示菜单效果。 res/menu/menu.xml MainActivity.java 总结 以上所述是小编给大家
js 文本划选 第一次划取执行的时候没有问题,获取的起始位置是相对于div标签的。 执行之后会向html中添加span标签 第二次划取span标签后的文字的时候,获取的起始位置却是相对于span标签的 有没有方法每次获取的起始位置都是相对于div的?
问题内容: 我想禁用长按(触摸并按住)Web应用程序中的图像后出现的上下文菜单。我见过关于如何做到这一点的不同想法,但似乎没有一个对我有用。 有没有办法通过HTML / CSS / Javascript在Android上执行此操作? 问题答案: 这应该适用于1.6或更高版本(如果我没记错的话)。我不认为有1.5或更早版本的解决方法。
我想在单击导航抽屉时更改其文本颜色。 我怎么能做到呢? 这是我的清单:
使用任何按钮都可以触发一个弹出菜单,只需要把它放置在一个.btn-group中,并提供适当的弹出菜单标记。 插件依赖 按钮弹出菜单需要你的Bootstrap中调用了弹出菜单插件。 内容 单按钮弹出菜单 通过一些基本的标记变化,将一个按钮变成一个弹出菜单。 <!-- Single button --> <div class="btn-group"> <button type="button"