专栏名称: 鸿洋
你好,欢迎关注鸿洋的公众号,每天为您推送高质量文章,让你每天都能涨知识。点击历史消息,查看所有已推送的文章,喜欢可以置顶本公众号。此外,本公众号支持投稿,如果你有原创的文章,希望通过本公众号发布,欢迎投稿。
目录
相关文章推荐
开发者全社区  ·  瓜!药科大学的PDF ·  16 小时前  
开发者全社区  ·  某软jx ·  19 小时前  
开发者全社区  ·  DB总的瓜 ·  2 天前  
开发者全社区  ·  光大的瓜 ·  2 天前  
51好读  ›  专栏  ›  鸿洋

文末赠书 | WebView截长图解决方案

鸿洋  · 公众号  · android  · 2017-12-14 07:30

正文

本文作者


作者: Windin 贝聊移动Android工程师

链接:

http://www.jianshu.com/p/0faa70e88441

本文由作者授权发布。


前言:本文主要讲述了以下两个方面:


1. 普通WebView如何截取长图

2. 针对X5内核中WebView如何截取长图


日常开发中,遇到为WebView截取长图算是一种常见的需求。网上聪明的程序员们提供了多种截取WebView长图的方法,这为我们的开发提供了很多便利。


现在,也有很多APP是集成了X5内核的,网上对于X5内核的截长图方案介绍比较少,所以这里我整理了对WebView截取长图的比较通用可行的方法,并且对使用了x5内核的WebView的截图方法进行分享。


1
普通WebView截长图方案


普通WebView截取长图,这里是指项目中没有集成X5内核的情况。利用Google文档上的api可以顺利截图。以Android5.0为版本分界线,截图采用不同的处理方式。


1. Android5.0以下版本


/**
* 对WebView进行截屏,虽然使用过期方法,
* 但在当前Android版本中测试可行
* @param webView
* @return
*/

private static Bitmap captureWebViewKitKat(WebView webView) {
       Picture picture = webView.capturePicture();
       int width = picture.getWidth();
       int height = picture.getHeight();
       if (width > 0 && height > 0) {
           Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
           Canvas canvas = new Canvas(bitmap);
           picture.draw(canvas);
           return bitmap;
       }
       return null;
   }
}


2. Android5.0及以上版本


在Android5.0及以上版本,Android对WebView进行了优化,为了减少内存使用和提高性能,使用WebView加载网页时只绘制显示部分。


如果我们不做处理,仍然使用上述代码截图的话,就会出现只截到屏幕内显示的WebView内容,其它部分是空白的情况。


这时候,我们通过调用WebView.enableSlowWholeDocumentDraw()方法可以关闭这种优化,但要注意的是,该方法需要在WebView实例被创建前就要调用,否则没有效果。


所以我们在WebView实例被创建前加入代码:


if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
   android.webkit.WebView.enableSlowWholeDocumentDraw();
}


根据Google文档中描述,capturePicture()方法已不鼓励使用,推荐我们通过webView的onDraw(Canvas)去获取图像,所以这里我们去拿到网页的宽高后,就调用webView.draw(Canvas)方法生成webView截图。


private void captureWebViewLollipop(WebView webView) {
   float scale = webView.getScale();
   int width = webView.getWidth();
   int height = (int) (webView.getContentHeight() * scale + 0.5);
   Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
   Canvas canvas = new Canvas(bitmap);
   webView.draw(canvas);
   return bitmap;
}


2
X5内核截取长图


使用X5内核截取长图有两种方法,并且都可以不用考虑版本问题,这为我们提供了方便。在X5内核下,如果使用WebView的onDraw(Canvas)方法,会出现或多或少的问题,所以对这个方法弃坑了。以下是两个截图方法:


1. 使用X5内核方法 snapshotWholePage(Canvas, boolean, boolean)


在X5内核中提供了一个截取整个WebView界面的方法snapshotWholePage(Canvas, boolean, boolean),但是这个方法有个缺点,就是不以屏幕上WebView的宽高截图,只是以WebView的contentWidth和contentHeight为宽高截图,所以截出来的图片会不怎么清晰,但作为缩略图效果还是不错了。


private static Bitmap captureX5WebViewUnsharp(Context context, WebView webView) {
   if (webView == null) {
       return null;
   }
   if (context == null) {
       context = webView.getContext();
   }
   int width = webView.getContentWidth();
   int height = webView.getContentHeight();
   Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
   Canvas canvas = new Canvas(bitmap);
   webView.getX5WebViewExtension().snapshotWholePage(canvas, false, false);
   return bitmap;
}


2. 使用capturePicture()截取清晰长图


如果想要在X5内核下截到清晰的长图,不能使用snapshotWholePage(),依然可以采用capturePicture()。X5内核下使用capturePicture()进行截图,可以直接拿到WebView的清晰长图,但这是个Deprecated的方法,使用的时候要做好异常处理。


3
总结


以上是WebView截长图方法的总结和分享,对X5内核的截图也是尝试了多种途径最后找到满意的解决方案。另外,截长图会占用大量内存,容易触发OOM,所以代码中也要注意对OOM的处理。


在使用了X5内核的项目中,使用WebView截取长图的判断逻辑可以是:


// 有x5内核没有生效,并且Android版本是5.0及以上时,调用enableSlowWholeDocumentDraw()方便截取长图
if (!isX5Enabled() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
   android.webkit.WebView.enableSlowWholeDocumentDraw();
}
/* 创建WebView ×/
...
/*网页截图*/

public void captureWholePage()






请到「今天看啥」查看全文


推荐文章
开发者全社区  ·  瓜!药科大学的PDF
16 小时前
开发者全社区  ·  某软jx
19 小时前
开发者全社区  ·  DB总的瓜
2 天前
开发者全社区  ·  光大的瓜
2 天前
台海军事热点  ·  刚刚,朝鲜400门火炮直指韩国首尔!
7 年前
注册风险管理师  ·  风险管理失败的三大原因及10个案例
7 年前