Android之WebView网页滚动截图

WebView 网页滚动截屏,可对整个网页进行截屏而不是仅当前屏幕哦!
注意若Web页面存在position:fixed; 的话得在调用前设置为 position:absolute; 哦,否则会出现很多次的,请看下面的具体解说吧!!


    private static Bitmap getViewBitmapWithoutBottom(View v) {
        if (null == v) {
            return null;
        }
        v.setDrawingCacheEnabled(true);
        v.buildDrawingCache();
        if (Build.VERSION.SDK_INT >= 11) {
            v.measure(View.MeasureSpec.makeMeasureSpec(v.getWidth(), View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(v.getHeight(), View.MeasureSpec.EXACTLY));
            v.layout((int) v.getX(), (int) v.getY(), (int) v.getX() + v.getMeasuredWidth(), (int) v.getY() + v.getMeasuredHeight());
        } else {
            v.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
            v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
        }
        Bitmap bp = Bitmap.createBitmap(v.getDrawingCache(), 0, 0, v.getMeasuredWidth(), v.getMeasuredHeight() - v.getPaddingBottom());
        v.setDrawingCacheEnabled(false);
        v.destroyDrawingCache();
        return bp;
    }

    public static Bitmap getViewBitmap(View v) {
        if (null == v) {
            return null;
        }
        v.setDrawingCacheEnabled(true);
        v.buildDrawingCache();
        if (Build.VERSION.SDK_INT >= 11) {
            v.measure(View.MeasureSpec.makeMeasureSpec(v.getWidth(), View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(v.getHeight(), View.MeasureSpec.EXACTLY));
            v.layout((int) v.getX(), (int) v.getY(), (int) v.getX() + v.getMeasuredWidth(), (int) v.getY() + v.getMeasuredHeight());
        } else {
            v.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
            v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
        }
        Bitmap b = Bitmap.createBitmap(v.getDrawingCache(), 0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
        v.setDrawingCacheEnabled(false);
        v.destroyDrawingCache();
        return b;
    }

    /**
     * 获取 WebView 视图截图
     * @param context
     * @param view
     * @return
     */
    public static Bitmap getWebViewBitmap(Context context, WebView view) {
        if (null == view) return null;
        view.scrollTo(0, 0);
        view.buildDrawingCache(true);
        view.setDrawingCacheEnabled(true);
        view.setVerticalScrollBarEnabled(false);
        Bitmap b = getViewBitmapWithoutBottom(view);
        // 可见高度
        int vh = view.getHeight();
        // 容器内容实际高度
        int th = (int)(view.getContentHeight()*view.getScale());
        Bitmap temp = null;
        if (th > vh) {
            int w = getScreenWidth(context);
            int absVh = vh - view.getPaddingTop() - view.getPaddingBottom();
            do {
                int restHeight = th - vh;
                if (restHeight <= absVh) {
                    view.scrollBy(0, restHeight);
                    vh += restHeight;
                    temp = getViewBitmap(view);
                } else {
                    view.scrollBy(0, absVh);
                    vh += absVh;
                    temp = getViewBitmapWithoutBottom(view);
                }
                b = mergeBitmap(vh, w, temp, 0, view.getScrollY(), b, 0, 0);
            } while (vh < th);
        }
        // 回滚到顶部
        view.scrollTo(0, 0);
        view.setVerticalScrollBarEnabled(true);
        view.setDrawingCacheEnabled(false);
        view.destroyDrawingCache();
        return b;
    }

    /**
     * 拼接图片
     * @param newImageH
     * @param newImageW
     * @param background
     * @param backX
     * @param backY
     * @param foreground
     * @param foreX
     * @param foreY
     * @return
     */
    private static Bitmap mergeBitmap(int newImageH, int newImageW, Bitmap background, float backX, float backY, Bitmap foreground, float foreX, float foreY) {
        if (null == background || null == foreground) {
            return null;
        }
        Bitmap bitmap = Bitmap.createBitmap(newImageW, newImageH, Bitmap.Config.RGB_565);
        Canvas cv = new Canvas(bitmap);
        cv.drawBitmap(background, backX, backY, null);
        cv.drawBitmap(foreground, foreX, foreY, null);
        cv.save(Canvas.ALL_SAVE_FLAG);
        cv.restore();
        return bitmap;
    }

    /**
     * get the width of screen
     */
    public static int getScreenWidth(Context ctx) {
        int w = 0;
        if (Build.VERSION.SDK_INT > 13) {
            Point p = new Point();
            ((WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getSize(p);
            w = p.x;
        } else {
            w = ((WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getWidth();
        }
        return w;
    }

    /**
     * 保存图片
     * @param context
     * @param bitmap
     * @param file
     * @param quality
     * @return
     */
    public static boolean save(Context context, Bitmap bitmap, File file, int quality) {
        if (bitmap == null) return false;
        // 获得后缀格式
        String abs = file.getAbsolutePath();
        String suffix = abs.substring(abs.lastIndexOf(".")+1).toLowerCase();
        Bitmap.CompressFormat format;
        if ("jpg".equals(suffix) || "jpeg".equals(suffix)) {
            format = Bitmap.CompressFormat.JPEG;
        } else {
            format = Bitmap.CompressFormat.PNG;
            quality = 100;
        }
        if (file.exists() && ! file.delete()) return false;
        try {
            FileOutputStream stream = new FileOutputStream(file);
            bitmap.compress(format, quality, stream);
            stream.flush();
            stream.close();
            context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(file)));
            return true;
        } catch (Exception e) {
            return false;
        }
    }

JS调用截屏操作

    /**
     * 屏幕截图
     * @param name
     * @param isRecover
     */
    @JavascriptInterface
    public String Capture(String name, boolean isRecover) {
        File dir = new File(Config.PUBLIC_PICTURES_PATH);
        LogUtil.i("capture", dir.getAbsolutePath());
        if (! dir.exists() && ! dir.mkdirs()) return null;
        final File file = new File(dir, name);
        String path = file.getAbsolutePath();
        if (file.exists() && ! isRecover) return path;
        body.post(new Runnable() {
            @Override
            public void run() {
                Bitmap bitmap = CaptureUtil.getWebViewBitmap(activity, body);
                if (null != bitmap) ImageUtil.save(activity, bitmap, file, 100);
            }
        });
        return path;
    }
    @JavascriptInterface
    public String Capture(String name) {
        return Capture(name, true);
    }
    @JavascriptInterface
    public String Capture() {
        String name = String.valueOf(System.currentTimeMillis()) + ".png";
        return Capture(name);
    }

示例图:我先通过 JS 触发显示了一个原生的 Button按钮, 然后WebView跳转到 csdn 页面,然后点击截屏按钮用来触发网页截屏的。下面的图是我手动截的图,不是上面代码的效果哈,下下面很长的那张才是Java程序的网页截图。。。

Android之WebView网页滚动截图

测试CSDN的网页完整截图:比较长哦~ 一般截图的功能都用于特殊的页面,如活动页面之类的,不会太长,那样是没有问题的。若是这种滚动到底部自动加载的话可能就会很长很长很长啦·····,自己看着办吧。。

Android之WebView网页滚动截图

但这里有个BUG,顶部固定Banner条每次截屏都有,这个有解决办法,不过得是你自己的网页才有操作权限哦,需要修改JS啦。

当截图JS命令触发前,把顶部悬浮的样式设置为绝对定位,当截屏完成后再改回固定定位即可,没什么难度了。

截屏是需要一些时间的,所以需要预设一个定时器来操作,JS栗子如下:

JS.Capture 是 WebView 绑定的自定义 Javascript 类对象

        var file = '';
        var $header = $("#layout-header");
        $header.css({ position: "absolute" });
        setTimeout(function(){
            if (typeof name == "function" || typeof name == "undefined") {
                file = JS.Capture();
            } else {
                file = JS.Capture(name, isRecover);
            }
        }, 500);
        setTimeout(function(){
            JS.Toast("截图已保存", "fast");
            JS.Toast(file.replace("storage/emulated/0/", ""));
            $header.css({ position: "fixed" });
            if ($.isFunction(callback)) {
                callback(file);
            }
        }, 1500);
  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

神神的蜗牛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值