时间:2022-10-03 11:31:53 | 栏目:Android代码 | 点击:次
附GitHub源码:WebViewExplore
先看图:
在WebView页面长按时会弹出一个复制框,但如果里面的item不是我们想要的或者想自定义,那么可以通过覆盖WebView的 startActionMode 方法来实现:
/** * 长按弹出ActionMode菜单样式 * @param callback * @param type * @return */ @Override public ActionMode startActionMode(Callback callback, int type) { Logger.d(TAG, "startActionMode--callback:" + callback + " type:" + type); ActionMode actionMode = super.startActionMode(callback, type); return resolveActionMode(actionMode); }
private ActionMode resolveActionMode(ActionMode actionMode) { if (actionMode != null) { final Menu menu = actionMode.getMenu(); mActionMode = actionMode; //清除系统自定item选项 menu.clear(); /** * 为菜单item重新赋值 */ for (int i = 0; i < mActionList.size(); i++) { menu.add(mActionList.get(i)); //可以为每个item添加icon //menu.getItem(i).setIcon(R.drawable.ic_launcher); } for (int i = 0; i < menu.size(); i++) { MenuItem menuItem = menu.getItem(i); /** * 新添item的点击事件【可根据不同个item点击事件,来进行相关的业务处理】 */ menuItem.setOnMenuItemClickListener(new OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { Logger.d(TAG, item.getTitle().toString()); getSelectedData((String) item.getTitle()); releaseAction(); return true; } }); } } mActionMode = actionMode; return actionMode; }
上面的mActionList是早已经在该控件的构造方法调用时添加了所需的item:
private void initData() { mActionList = new ArrayList<>(); //扩选 mActionList.add(GlobalConstant.ENLARGE); //复制 mActionList.add(GlobalConstant.COPY); //分享 mActionList.add(GlobalConstant.SHARE); }
这里拿"复制"事件举例,通过如下native调用该Js的代码的方式可以获取当前所文本框所选中的文本:
/** * Android调用JS的代码方式有2种: * 1、通过WebView的loadUrl() * 2、通过WebView的evaluateJavaScript() * <p> * 点击的时候,获取网页中选择的文本,回掉到原生中的js接口 * * @param title 传入点击的item文本,一起通过js返回给原生接口 */ private void getSelectedData(String title) { String js = "(function getSelectedText() {" + "var txt;" + "var title = \"" + title + "\";" + "if (window.getSelection) {" + "txt = window.getSelection().toString();" + "} else if (window.document.getSelection) {" + "txt = window.document.getSelection().toString();" + "} else if (window.document.selection) {" + "txt = window.document.selection.createRange().text;" + "}" + "JSInterface.callback(txt,title);" + "})()"; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { evaluateJavascript("javascript:" + js, new ValueCallback<String>() { @Override public void onReceiveValue(String value) { //此处为js返回结果 Logger.d(TAG, "value:" + value); } }); } else { loadUrl("javascript:" + js); } }
点击复制按钮就可以将我们选中的文本赋值到上述js脚本中的 'txt' 变量中,但是如何传递到native呢,这就用到了 WebView与Native的交互 章节介绍的JS调用Native的方法1,这里再说明一下:
在该控件的构造方法中早已映射了原生方法接口:
private void linkJSInterface() { //Js调用native的方式一 addJavascriptInterface(new ActionSelectInterface(this), "JSInterface"); }
JSInterface 对应的映射接口 ActionSelectInterface 实现如下:
/** * JS调用android原生方法1: * 通过WebView的addJavascriptInterface()进行对象映射 */ public class ActionSelectInterface { private ActionWebView mActionWebView; public ActionSelectInterface(ActionWebView actionWebView) { mActionWebView = actionWebView; } @JavascriptInterface public void callback(final String value, final String title) { Logger.d(TAG, "currentThread:" + Thread.currentThread()); post(new Runnable() { @Override public void run() { if (mActionSelectListener != null) { mActionSelectListener.onClick(title, value); } } }); } }
所以最终就可以根据上述js脚本中的 'JSInterface.callback(txt,title);‘方法的调用,来最终响应 至native类ActionSelectInterface中callback中,会收到title及复制文本value的值。
这样根据之前的监听,便可进行后续的一系列业务操作。