WebView实现长按保存图片 长按识别二维码

先来简单说一下本文所要实现的功能:用户在浏览网页的时候,长按某一区域,识别若是是图片,则弹出弹框,出现保存图片的功能。同时识别图片是不是二维码,若是是则在弹框中追加识别二维码功能。git

细节上:保存图片的弹框要显示在手指长按的位置;选择图片保存后,可让用户直接去相册查看;选择识别二维码,判断是是否是网址,是的话可让用户选择复制或访问,不然可让用户选择复制或搜索。github

而后再来看一下效果图:缓存

保存图片

识别包含普通文字的二维码:

识别包含网址的二维码:

上述功能所用到的类和库:

  • 得到长按内容:WebView.HitTestResult
  • 弹框列表:DialogFragment
  • 图片下载:Glide
  • 二维码识别:Zxing

实现要点

记录长按位置

继承WebView记录触摸位置:bash

@Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        touchX = (int) event.getRawX();
        touchY = (int) event.getRawY();
        return super.onInterceptTouchEvent(event);
    }
复制代码

弹框我选择DialogFragment而不是poupwindow的缘由是poupwindow的显示一般须要依托另外一个View,并且在7.0以上有兼容问题。 判断长按位置的内容类型是不是图片:网络

获取图片信息

setOnLongClickListener(new View.OnLongClickListener() {

            public boolean onLongClick(View v) {
                WebView.HitTestResult result = getHitTestResult();
                if (null == result)
                    return false;
                int type = result.getType();
                switch (type) {
                    case WebView.HitTestResult.EDIT_TEXT_TYPE: // 选中的文字类型
                        break;
                    case WebView.HitTestResult.PHONE_TYPE: // 处理拨号
                        break;
                    case WebView.HitTestResult.EMAIL_TYPE: // 处理Email
                        break;
                    case WebView.HitTestResult.GEO_TYPE: //  地图类型
                        break;
                    case WebView.HitTestResult.SRC_ANCHOR_TYPE: // 超连接
                        break;
                    case WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE: // 带有连接的图片类型
                    case WebView.HitTestResult.IMAGE_TYPE: // 处理长按图片的菜单项
                        String url = result.getExtra();
                        if (mOnSelectItemListener != null && url != null && URLUtil.isValidUrl(url)) {
                            mOnSelectItemListener.onSelected(touchX, touchY, result.getType(), url);
                        }
                        return true;
                    case WebView.HitTestResult.UNKNOWN_TYPE: //未知
                        break;
                }
                return false;
            }
        });
复制代码

在手指长按位置处弹出弹框

HitTestResult是一个实体类,只记录两个信息:当选选择内容的类型和内容的具体值。能够看到经过WebView.HitTestResult,咱们能够得到除了图片外的不少内容类型。固然这里咱们只须要判断是不是图片就行了,而后将长按位置和url一块儿回调给外层。在手指长按处显示弹框,主要就是DialogFragment显示位置的设定了:app

public void onStart() {
        super.onStart();
        Dialog dialog = getDialog();
        if (dialog != null) {
            Window window = dialog.getWindow();
            if (window != null) {
                WindowManager.LayoutParams lp = window.getAttributes();
                window.setGravity(Gravity.LEFT | Gravity.TOP);
                lp.x = LocationX;//横坐标位置
                lp.y = LocationY;//纵坐标位置
                lp.width = UIHelper.dip2px(100);
                lp.dimAmount = 0.0f;//外层背景透明,默认变暗
                lp.width = ViewGroup.LayoutParams.WRAP_CONTENT;
                lp.height = ViewGroup.LayoutParams.WRAP_CONTENT;
                window.setAttributes(lp);
                window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));//内部背景透明
            }
        }
    }
复制代码

保存到相册

利用Glide下载图片,Glide自带预加载和图片缓存功能,不须要每次都从网络中下载:ide

GlideApp.with(appContext).asFile().load(url).submit().get();
复制代码

能够在长按识别出图片的时候就行预加载:优化

GlideApp.with(appContext).asBitmap().load(url).preload();
复制代码

将图片保存在相册:ui

public static void displayToGallery(Context context, File photoFile) {
        if (photoFile == null || !photoFile.exists()) {
            return;
        }
        String photoPath = photoFile.getAbsolutePath();
        String photoName = photoFile.getName();
        // 把文件插入到系统图库
        try {
            ContentResolver contentResolver = context.getContentResolver();
            MediaStore.Images.Media.insertImage(contentResolver, photoPath, photoName, null);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        // 最后通知图库更新
        context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + photoPath)));
    }
复制代码

识别图片中的二维码

显示弹框的同时还要判断图片是否包含二维码,这部分就是Zxing自带的功能,因此代码就不贴了。注意不该该等是Zxing判断是否是二维码后再显示弹框,由于这部分操做耗时可能比较长(见图二)。应当在识别二维码内容后再去更新弹框列表的内容。url

总结

整体来讲这个功能实现注意的地方仍是挺多的,好在都不复杂。固然本例还存在待优化的地方,以及实现更高级的功能,好比以图搜图,查看大图功能,也能够利用WebView.HitTestResult对获取到其余类型的内容进行处理,限于篇幅就再也不展开了。 最后贴下本项目Github地址,对WebView感兴趣的能够了解下:

Github

相关文章
相关标签/搜索