做者:Windin 贝聊移动开发部 Android工程师
前言:本文主要讲述了如下两个方面:android
- 普通
WebView
如何截取长图- 针对
X5内核中WebView
如何截取长图
平常开发中,遇到为WebView
截取长图算是一种常见的需求。网上聪明的程序员们提供了多种截取WebView
长图的方法,这为咱们的开发提供了不少便利。如今,也有不少APP是集成了X5内核的,网上对于X5内核的截长图方案介绍比较少,因此这里我整理了对WebView
截取长图的比较通用可行的方法,而且对使用了x5内核的WebView
的截图方法进行分享。程序员
WebView
截长图方案普通WebView
截取长图,这里是指项目中没有集成X5内核的状况。利用Google
文档上的api能够顺利截图。以Android5.0
为版本分界线,截图采用不一样的处理方式。web
/**
* 对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;
}
}复制代码
在Android5.0及以上版本,Android对WebView
进行了优化,为了减小内存使用和提升性能,使用WebView
加载网页时只绘制显示部分。若是咱们不作处理,仍然使用上述代码截图的话,就会出现只截到屏幕内显示的WebView
内容,其它部分是空白的状况。
这时候,咱们经过调用WebView.enableSlowWholeDocumentDraw()
方法能够关闭这种优化,但要注意的是,该方法须要在WebView
实例被建立前就要调用,不然没有效果。因此咱们在WebView
实例被建立前加入代码:canvas
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
android.webkit.WebView.enableSlowWholeDocumentDraw();
}复制代码
根据Google
文档中描述,capturePicture()
方法已不鼓励使用,推荐咱们经过webView
的onDraw(Canvas)
去获取图像,因此这里咱们去拿到网页的宽高后,就调用webView.draw(Canvas)
方法生成webView
截图。api
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;
}复制代码
使用X5内核截取长图有两种方法,而且均可以不用考虑版本问题,这为咱们提供了方便。在X5内核下,若是使用WebView
的onDraw(Canvas)
方法,会出现或多或少的问题,因此对这个方法弃坑了。如下是两个截图方法:bash
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;
}复制代码
capturePicture()
截取清晰长图若是想要在X5内核下截到清晰的长图,不能使用snapshotWholePage()
,依然能够采用capturePicture()
。X5内核下使用capturePicture()
进行截图,能够直接拿到WebView
的清晰长图,但这是个Deprecated
的方法,使用的时候要作好异常处理。测试
以上是WebView
截长图方法的总结和分享,对X5内核的截图也是尝试了多种途径最后找到满意的解决方案。另外,截长图会占用大量内存,容易触发OOM,因此代码中也要注意对OOM的处理。优化
在使用了X5内核的项目中,使用WebView
截取长图的判断逻辑能够是:ui
// 有x5内核没有生效,而且Android版本是5.0及以上时,调用enableSlowWholeDocumentDraw()方便截取长图
if (!isX5Enabled() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
android.webkit.WebView.enableSlowWholeDocumentDraw();
}
/* 建立WebView ×/
...
// 网页截图
public void captureWholePage() {
try {
Bitmap bitmap = captureWebView();
/* 对拿到的bitmap根据须要进行处理 */
} catch (OutOfMemoryError oom) {
/* 对OOM作处理
}
}复制代码