前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >WebView自定义长按选择,实现收藏/分享选中文本。

WebView自定义长按选择,实现收藏/分享选中文本。

作者头像
GSYTech
发布2018-08-22 11:33:48
2.3K0
发布2018-08-22 11:33:48
举报
文章被收录于专栏:移动开发之家

Hello,大家吼,吾就是那个挖坑不止的郭小喵,不管有没有想我(˶‾᷄ ⁻̫ ‾᷅˵)的,这次就分享快速实现一个自定义WebView的小控件吧,效果如下图,废话不多说,我们直接开撸吧。**

(PS : ╮(╯▽╰)╭如果你翻一翻我过去的文章,你会发现90%的开场白,前几个问候语都是一样的。)

效果图(1.3M)

一、前言

**** 戳这里可以去DEMO,来吧 ** **

相信刚接触android不久的同志们,在面对产品提出的 :

代码语言:javascript
复制
“自定义WebView页面中,长按文本的弹出选项、点击选择后,分享、转发、收藏选择文本” 

这样的需求时,第一反应大部分是:这是系统行为,如果实现需要在web端实现。

但是web端实现的局限性太大,曾经也有过监听系统粘贴板,在用户点击复制的时候实现其他的逻辑,但是这样用户体验不好,所以自定义WebView中长按的弹出菜单,并在点击时返回选中文本的小控件闪亮登场┏ (ω)=。

二、自定义长按弹出菜单

这一步实现其实很简单,首先创建一个CustomActionWebView继承系统WebView,然后重写下面两个方法。

这两个方法会在用户长按选择web文本时,在弹出菜单前被调用。它们之间的区别在于,第一个方法的菜单弹出方式,指定了默认的type。我们并不关心弹出的item类型是什么,我们只需要拦截下来ActionMode,然后返回我们自己的自定义ActionMode即可。

代码语言:javascript
复制
@Override
public ActionMode startActionMode(ActionMode.Callback callback) {
    ActionMode actionMode = super.startActionMode(callback);
    return resolveActionMode(actionMode);
}

@Override
public ActionMode startActionMode(ActionMode.Callback callback, int type) 
    ActionMode actionMode =  super.startActionMode(callback, type);
    return resolveActionMode(actionMode);
}

这里我们所做的事是:

  • 1、把原本的actionMode对象保存到mActionMode中。
  • 2、清空原本actionMode中的MenuItem。
  • 3、添加我们自定义的item到actionMode中。
  • 4、重定义每个menuItem的点击事件。
  • 5、在点击事件中通过执行js,获取选中文本。
  • 6、通过上面保存的** mActionMode**,释放弹出菜单(不释放会内存泄漏)。
  • 7、返回新填充的actionMode给系统。
代码语言:javascript
复制
/**
 * 处理item,处理点击
 * @param actionMode
 */
private ActionMode resolveActionMode(ActionMode actionMode) {
    if (actionMode != null) {
        final Menu menu = actionMode.getMenu();
        mActionMode = actionMode;
        menu.clear();
        for (int i = 0; i < mActionList.size(); i++) {
            menu.add(mActionList.get(i));
        }
        for (int i = 0; i < menu.size(); i++) {
            MenuItem menuItem = menu.getItem(i);
            menuItem.setOnMenuItemClickListener(new Item.OnMenuItemClickListener() {
                @Override
                public boolean onMenuItemClick(MenuItem item) {
                    getSelectedData((String) item.getTitle());
                    releaseAction();
                    return true;
                }
            });
        }
    }
    mActionMode = actionMode;
    return actionMode;
}

实现效果

三、获取选中文本

光自定义菜单,拿不到选中文本也没意义,那么如何获取选中文本呢?这里如果不转个弯,还真会在南墙在撞死( ̄^ ̄)ゞ,所以,我们伟大的js就出现了。

首先,我们自定义一个接口,用于监听js方法,其中@JavascriptInterface是关键的所在,** 在callback中获取js端返回的数据**。

然后将这个接口,在CustomActionWebView中add进去(一般是在初始化和页面加载完成时都add一次),并指定js端调用的接口名称为“ JSInterface”。(ps:别忘了开始webview的js允许哦。)

代码语言:javascript
复制
public void linkJSInterface() {
   addJavascriptInterface(new ActionSelectInterface(this), "JSInterface");
}

···

/**
 * js选中的回调接口
 */
private class ActionSelectInterface {

    CustomActionWebView mContext;

    ActionSelectInterface(CustomActionWebView c) {
        mContext = c;
    }

    @JavascriptInterface
    public void callback(final String value, final String title) {
        if(mActionSelectListener != null) {
            mActionSelectListener.onClick(title, value);
        }
    }
}

最后在点击时,通过执行js来获取web中选中的文本。在上面自定义菜单中第5项,点击menu时,执行下方js代码,便可以把选中的item和文本,回调到上面的接口中的callback。

熟悉js的小伙伴已经看出来吧:

  • 其实就是定义了一个js的function,然后在webview中执行这个方法。
  • 定义的这个名为function getSelectedText()的js方法,有两个变量:txt和title。
  • title是从原生中传入的item名字,txt是通过window去获取web中选中的文本。
  • 最后回到上面我们注册的js方法名JSInterface,通过它的callback方法,将文本和name返回到原生代码callback中。
  • 根据版本不同,执行js方法的接口也不一样。
代码语言:javascript
复制
/**
 * 点击的时候,获取网页中选择的文本,回掉到原生中的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, null);
    } else {
        loadUrl("javascript:" + js);
    }
}

四、最后

既然自定义item实现了,点击和选择文本返回也实现了,在callback中,你就可以愉悦的收藏,或者分享你所选中的文本啦(◐‿◑),操作一气呵成,有没有被惊艳到呢?

如果感兴趣的,可以下载demo看下,同时CustomActionWebView也封装好了远程依赖,欢迎使用。

https://github.com/CarGuo/CustomActionWebView

写文章也是个累活

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017.06.19 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、前言
    • **** 戳这里可以去DEMO,来吧 ** **
    • 二、自定义长按弹出菜单
    • 三、获取选中文本
    • 四、最后
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档