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

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

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

