Android WebView實現(xiàn)網(wǎng)頁滾動截圖
WebView 網(wǎng)頁滾動截屏,可對整個網(wǎng)頁進行截屏而不是僅當(dāng)前屏幕哦!
注意若Web頁面存在position:fixed; 的話得在調(diào)用前設(shè)置為 position:absolute; 哦,否則會出現(xiàn)很多次的,請看下面的具體解說吧?。?/p>
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();
// 容器內(nèi)容實際高度
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調(diào)用截屏操作
/**
* 屏幕截圖
* @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 觸發(fā)顯示了一個原生的 Button按鈕, 然后WebView跳轉(zhuǎn)到 csdn 頁面,然后點擊截屏按鈕用來觸發(fā)網(wǎng)頁截屏的。下面的圖是我手動截的圖,不是上面代碼的效果哈,下下面很長的那張才是Java程序的網(wǎng)頁截圖。

測試CSDN的網(wǎng)頁完整截圖:比較長哦~ 一般截圖的功能都用于特殊的頁面,如活動頁面之類的,不會太長,那樣是沒有問題的。若是這種滾動到底部自動加載的話可能就會很長很長很長啦·····,自己看著辦吧。。

但這里有個BUG,頂部固定Banner條每次截屏都有,這個有解決辦法,不過得是你自己的網(wǎng)頁才有操作權(quán)限哦,需要修改JS啦。
當(dāng)截圖JS命令觸發(fā)前,把頂部懸浮的樣式設(shè)置為絕對定位,當(dāng)截屏完成后再改回固定定位即可,沒什么難度了。
截屏是需要一些時間的,所以需要預(yù)設(shè)一個定時器來操作,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);
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android WebView打開網(wǎng)頁一片空白的解決方法
- Android開發(fā)筆記之如何正確獲取WebView的網(wǎng)頁Title
- 詳解android 用webview加載網(wǎng)頁(https和http)
- Android開發(fā)中使用WebView控件瀏覽網(wǎng)頁的方法詳解
- Android編程實現(xiàn)webview將網(wǎng)頁打包成apk的方法
- Android中替換WebView加載網(wǎng)頁失敗時的頁面
- Android中Webview打開網(wǎng)頁的同時發(fā)送HTTP頭信息方法
- Android webView如何輸出自定義網(wǎng)頁
相關(guān)文章
Android模擬器接收UDP數(shù)據(jù)包的若干問題分析
這篇文章主要介紹了Android模擬器接收UDP數(shù)據(jù)包的若干問題,結(jié)合實例形式較為詳細(xì)的分析了Android模擬器接收UDP數(shù)據(jù)的使用方法與相關(guān)注意事項,需要的朋友可以參考下2016-04-04
Android為TextView添加字體庫和設(shè)置描邊的方法
本篇文章主要介紹了Android為TextView添加字體庫和設(shè)置描邊的方法,具有一定的參考價值,有興趣的可以了解一下2017-09-09
Eclipse打開時“發(fā)現(xiàn)了以元素''d:skin''”開頭的無效內(nèi)容。此處不應(yīng)含有子元素的解決方法
這篇文章主要介紹了Eclipse打開時“發(fā)現(xiàn)了以元素'd:skin'”開頭的無效內(nèi)容。此處不應(yīng)含有子元素的解決方法,涉及Android sdk中devices.xml文件的修改,需要的朋友可以參考下2016-01-01
Android編程布局(Layout)之AbsoluteLayout用法實例分析
這篇文章主要介紹了Android編程布局(Layout)之AbsoluteLayout用法,結(jié)合實例形式簡單分析了Android絕對布局AbsoluteLayout的實現(xiàn)方法,需要的朋友可以參考下2015-12-12
Android scheme 跳轉(zhuǎn)的設(shè)計與實現(xiàn)詳解
這篇文章主要介紹了Android scheme 跳轉(zhuǎn)的設(shè)計與實現(xiàn),本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-06-06
Android N 7.0中報錯:android.os.FileUriExposedException的解決方法
這篇文章主要給大家介紹了關(guān)于在Android N 7.0中報錯:android.os.FileUriExposedException的解決方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起看看吧2018-05-05

