做者: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作處理
}
}複製代碼