欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android实现在webview中长按图片弹出菜单保存图片

程序员文章站 2022-06-10 16:14:37
...

Android实现在webview中长按图片弹出菜单保存图片

在项目中遇到一个保存webview中二维码图片的问题,做个笔记。
效果如图: Android实现在webview中长按图片弹出菜单保存图片
用到webview的三个方法:

  • getHitTestResult()——Gets a HitTestResult based on the current cursor node
  • getType()——Gets the type of the hit test result(获取所选中目标的类型,可以是图片,超链接,邮件,电话等等)
  • getExtra()——Gets additional type-dependant information about the result(获取额外的信息,例如图片的地址)

1. 第一步:给webview添加长按监听

_mWebview.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                }
            });

2. 第二步:通过webview的getHitTestResult()方法获取HitTestResult 对象

(1)通过getType()获取类型,通过类型判断是否是图片

WebView.HitTestResult result = ((WebView) v).getHitTestResult();
int type = result.getType();
  • 1
  • 2

type有这几种类型

WebView.HitTestResult.UNKNOWN_TYPE    未知类型
WebView.HitTestResult.PHONE_TYPE    电话类型
WebView.HitTestResult.EMAIL_TYPE    电子邮件类型
WebView.HitTestResult.GEO_TYPE    地图类型
WebView.HitTestResult.SRC_ANCHOR_TYPE    超链接类型
WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE    带有链接的图片类型
WebView.HitTestResult.IMAGE_TYPE    单纯的图片类型
WebView.HitTestResult.EDIT_TEXT_TYPE    选中的文字类型

(2)通过getExtra()获取额外信息,图片这里就是图片地址

String imgurl = result.getExtra();
  •  

通过判断类型来做不同的显示效果,在这里我只对图片处理,长按图片弹出一个PopWindow,效果自己写。

3. 第三步:通过获取的图片地址下载图片

最后把所有代码整理一下:

自定义PopWindow——ItemLongClickedPopWindow.java

public class ItemLongClickedPopWindow extends PopupWindow {
    /**
     * 书签条目弹出菜单 * @value * {@value} *
     */
    public static final int FAVORITES_ITEM_POPUPWINDOW = 0;
    /**
     * 书签页面弹出菜单 * @value * {@value} *
     */
    public static final int FAVORITES_VIEW_POPUPWINDOW = 1;
    /**
     * 历史条目弹出菜单 * @value * {@value} *
     */
    public static final int HISTORY_ITEM_POPUPWINDOW = 3;
    /**
     * 历史页面弹出菜单 * @value * {@value} *
     */
    public static final int HISTORY_VIEW_POPUPWINDOW = 4;
    /**
     * 图片项目弹出菜单 * @value * {@value} *
     */
    public static final int IMAGE_VIEW_POPUPWINDOW = 5;
    /**
     * 超链接项目弹出菜单 * @value * {@value} *
     */
    public static final int ACHOR_VIEW_POPUPWINDOW = 6;
    private LayoutInflater itemLongClickedPopWindowInflater;
    private View itemLongClickedPopWindowView;
    private Context context;
    private int type;

    /**
     * 构造函数 * @param context 上下文 * @param width 宽度 * @param height 高度 *
     */
    public ItemLongClickedPopWindow(Context context, int type, int width, int height) {
        super(context);
        this.context = context;
        this.type = type;
        //创建
        this.initTab();
        //设置默认选项
        setWidth(width);
        setHeight(height);
        setContentView(this.itemLongClickedPopWindowView);
        setOutsideTouchable(true);
        setFocusable(true);
    }

    //实例化
    private void initTab() {
        this.itemLongClickedPopWindowInflater = LayoutInflater.from(this.context);
        switch (type) {
//            case FAVORITES_ITEM_POPUPWINDOW:
//                this.itemLongClickedPopWindowView = this.itemLongClickedPopWindowInflater.inflate(R.layout.list_item_longclicked_favorites, null);
//                break;
//            case FAVORITES_VIEW_POPUPWINDOW: //对于书签内容弹出菜单,未作处理
//                break;
//            case HISTORY_ITEM_POPUPWINDOW:
//                this.itemLongClickedPopWindowView = this.itemLongClickedPopWindowInflater.inflate(R.layout.list_item_longclicked_history, null);
//                break;
//            case HISTORY_VIEW_POPUPWINDOW: //对于历史内容弹出菜单,未作处理
//                break;
//            case ACHOR_VIEW_POPUPWINDOW: //超链接
//               break;
            case IMAGE_VIEW_POPUPWINDOW: //图片
                this.itemLongClickedPopWindowView = this.itemLongClickedPopWindowInflater.inflate(R.layout.list_item_longclicked_img, null);
                break;
        }
    }

    public View getView(int id) {
        return this.itemLongClickedPopWindowView.findViewById(id);
    }
}

PopWindow的布局文件——list_item_longclicked_img.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="5dp"
    android:orientation="vertical">

    <TextView
        android:id="@+id/item_longclicked_viewImage"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:gravity="center"
        android:text="查看图片"
        android:textColor="@android:color/white"
        android:textSize="16sp" />

    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="@color/gray_9F" />

    <TextView
        android:id="@+id/item_longclicked_saveImage"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:gravity="center"
        android:text="保存图片"
        android:textColor="@android:color/white"
        android:textSize="16sp" />

</LinearLayout>

通过GestureDetector获取按下的位置,来定位PopWindow显示的位置

private GestureDetector gestureDetector;
private int downX, downY;


    gestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
            @Override
            public void onLongPress(MotionEvent e) {
                downX = (int) e.getX();
                downY = (int) e.getY();
            }
        });

在Activity中对webview的监听

_mWebview.setOnLongClickListener(new View.OnLongClickListener() {
     @Override
     public boolean onLongClick(View v) {
        WebView.HitTestResult result = ((WebView)v).getHitTestResult();
        if (null == result) 
            return false;
        int type = result.getType();
        if (type == WebView.HitTestResult.UNKNOWN_TYPE) 
            return false;
        if (type == WebView.HitTestResult.EDIT_TEXT_TYPE) {
          //let TextViewhandles context menu return true;
         }
final ItemLongClickedPopWindow itemLongClickedPopWindow = new ItemLongClickedPopWindow(HtmlActivity.this,ItemLongClickedPopWindow.IMAGE_VIEW_POPUPWINDOW, UIUtils.dip2px(120), UIUtils.dip2px(90));
    // Setup custom handlingdepending on the type
   switch (type) {
       case WebView.HitTestResult.PHONE_TYPE: // 处理拨号
           break;
       case WebView.HitTestResult.EMAIL_TYPE: // 处理Email
           break;
       case WebView.HitTestResult.GEO_TYPE: // TODO
           break;
       case WebView.HitTestResult.SRC_ANCHOR_TYPE: // 超链接
           // Log.d(DEG_TAG, "超链接");
           break;
       case WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE:
           break;
       case WebView.HitTestResult.IMAGE_TYPE: // 处理长按图片的菜单项
           imgurl = result.getExtra();
           //通过GestureDetector获取按下的位置,来定位PopWindow显示的位置
           itemLongClickedPopWindow.showAtLocation(v,        Gravity.TOP|Gravity.LEFT, downX, downY + 10);
           break;
       default:
           break;
    }

itemLongClickedPopWindow.getView(R.id.item_longclicked_viewImage)
    .setOnClickListener(new View.OnClickListener() {
           @Override
           public void onClick(View v) {
               itemLongClickedPopWindow.dismiss();
           }
     });
                                                                          itemLongClickedPopWindow.getView(R.id.item_longclicked_saveImage)
    .setOnClickListener(new View.OnClickListener() {
           @Override
           public void onClick(View v) {
               itemLongClickedPopWindow.dismiss();
               new SaveImage().execute(); // Android 4.0以后要使用线程来访问网络
           }
    });
    return true;
  }
});

最后下载图片

private String imgurl = "";

    /***
     * 功能:用线程保存图片
     *
     * @author wangyp
     */
    private class SaveImage extends AsyncTask<String, Void, String> {
        @Override
        protected String doInBackground(String... params) {
            String result = "";
            try {
                String sdcard = Environment.getExternalStorageDirectory().toString();
                File file = new File(sdcard + "/Download");
                if (!file.exists()) {
                    file.mkdirs();
                }
                int idx = imgurl.lastIndexOf(".");
                String ext = imgurl.substring(idx);
                file = new File(sdcard + "/Download/" + new Date().getTime() + ext);
                InputStream inputStream = null;
                URL url = new URL(imgurl);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                conn.setRequestMethod("GET");
                conn.setConnectTimeout(20000);
                if (conn.getResponseCode() == 200) {
                    inputStream = conn.getInputStream();
                }
                byte[] buffer = new byte[4096];
                int len = 0;
                FileOutputStream outStream = new FileOutputStream(file);
                while ((len = inputStream.read(buffer)) != -1) {
                    outStream.write(buffer, 0, len);
                }
                outStream.close();
                result = "图片已保存至:" + file.getAbsolutePath();
            } catch (Exception e) {
                result = "保存失败!" + e.getLocalizedMessage();
            }
            return result;
        }

        @Override
        protected void onPostExecute(String result) {
            showToast(result);
        }
    }

原文:http://www.educity.cn/wenda/179077.html

Android WebView Long Press长按保存图片到手机

private String imgurl = "";     /***      * 功能:长按图片保存到手机      */     @Override     public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {         super.onCreateContextMenu(menu, v, menuInfo);         MenuItem.OnMenuItemClickListener handler = new MenuItem.OnMenuItemClickListener() {             public boolean onMenuItemClick(MenuItem item) {                 if (item.getTitle() == "保存到手机") {                     new SaveImage().execute(); // Android 4.0以后要使用线程来访问网络                 } else {                     return false;                 }                 return true;             }         };         if (v instanceof WebView) {             WebView.HitTestResult result = ((WebView) v).getHitTestResult();             if (result != null) {                 int type = result.getType();                 if (type == WebView.HitTestResult.IMAGE_TYPE || type == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE) {                     imgurl = result.getExtra();                     menu.setHeaderTitle("提示");                     menu.add(0, v.getId(), 0, "保存到手机").setOnMenuItemClickListener(handler);                 }             }         }     }     /***      * 功能:用线程保存图片      *       * @author wangyp      *       */     private class SaveImage extends AsyncTask<String, Void, String> {         @Override         protected String doInBackground(String... params) {             String result = "";             try {                 String sdcard = Environment.getExternalStorageDirectory().toString();                 File file = new File(sdcard + "/Download");                 if (!file.exists()) {                     file.mkdirs();                 }                 int idx = imgurl.lastIndexOf(".");                 String ext = imgurl.substring(idx);                 file = new File(sdcard + "/Download/" + new Date().getTime() + ext);                 InputStream inputStream = null;                 URL url = new URL(imgurl);                 HttpURLConnection conn = (HttpURLConnection) url.openConnection();                 conn.setRequestMethod("GET");                 conn.setConnectTimeout(20000);                 if (conn.getResponseCode() == 200) {                     inputStream = conn.getInputStream();                 }                 byte[] buffer = new byte[4096];                 int len = 0;                 FileOutputStream outStream = new FileOutputStream(file);                 while ((len = inputStream.read(buffer)) != -1) {                     outStream.write(buffer, 0, len);                 }                 outStream.close();                 result = "图片已保存至:" + file.getAbsolutePath();             } catch (Exception e) {                 result = "保存失败!" + e.getLocalizedMessage();             }             return result;         }         @Override         protected void onPostExecute(String result) {             MsgBox("提示", result);         }     }

Android WebView截取所有内容生成长图在5.0以上系统异常问题

最近在做webview截取所有内容生成长图时出现一些问题,在Android5.0以下系统能正常生成长图,但是在5.0以上会出现只能截取第一屏的内容,剩下的全部为空白,查看资料发现原来是系统在5.0+版本上,Android对webview做了优化,为了减少内存占用以提高性能,因此在默认情况下会智能的绘制html中需要绘制的部分,其实就是当前屏幕展示的html内容,因此会出现未显示的图像是空白的。解决方法如下:

 


如上图:在activity的onCreate方法中的setContentView前加上一句enableSlowWholeDocumentDraw();意思为取消系统的智能绘制,当然这样之后性能会有所下降,但为了实现功能,也只能如此。
加上之后在Android5.0以下系统会崩溃,那是因为在5.0以下没有enableSlowWholeDocumentDraw()这个方法,因此需要做个判断,获取本机系统版本号,当版本号大于5.0则调用enableSlowWholeDocumentDraw()方法,否则不调用。
代码为:API=21即为Android5.0系统

if (android.os.Build.VERSION.SDK_INT >= 21) {
    enableSlowWholeDocumentDraw();
}
下面为生成长图代码:

 

public Bitmap viewShot(final View view) {
    if (view == null)
        return null;
    view.setDrawingCacheEnabled(true);
    view.buildDrawingCache();
    int measureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
    view.measure(measureSpec, measureSpec);
    if (view.getMeasuredWidth() <= 0 || view.getMeasuredHeight() <= 0) {
        return null;
    }
    Bitmap bm;
    try {
        bm = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
    } catch (OutOfMemoryError e) {
        System.gc();
        try {
            bm = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
        } catch (OutOfMemoryError ee) {
            return null;
        }
    }
    Canvas bigCanvas = new Canvas(bm);
    Paint paint = new Paint();
    int iHeight = bm.getHeight();
    bigCanvas.drawBitmap(bm, 0, iHeight, paint);
    view.draw(bigCanvas);
    showToast(getString(R.string.already_share_save_img));
    return bm;
}
————————————————
版权声明:本文为CSDN博主「A_mnesia」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/m13984458297/article/details/78687015

 

 

相关标签: android进阶