WebView截图、截取整个网页

本次需求是要实现对WebView显示所有内容的截图 网上找了一通,基本上是实现了当前显示内容的截图,并非是整个页面的截图。

最终实现效果和代码如下所示,实现了本次WebView长截图的需求。 效果如下:

博客_WebView_长截图

代码如下,主要是使用WebView.setDrawingCacheEnabled(),WebView.buildDrawingCache(),WebView.getDrawingCache(),View.scrollBy() 实现滑动截图,再拼接合成整张图片。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
public class CaptureUtils {

/**
* 获取 当前屏幕显示区域 v 去除PaddingBottom的Bitmap对象
*
* @param v
* @return
*/
private static Bitmap getViewBitmapWithoutBottom(View v) {
if (null == v) {
return null;
}
v.setDrawingCacheEnabled(true);
v.buildDrawingCache();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
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;
}

/**
* 获取 当前屏幕显示区域 v 的Bitmap对象
*
* @param v
* @return
*/
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 webView
* @return
*/
public static Bitmap getWebViewBitmap(Context context, WebView webView) {
if (null == webView) return null;
webView.scrollTo(0, 0);
webView.buildDrawingCache(true);
webView.setDrawingCacheEnabled(true);
webView.setVerticalScrollBarEnabled(false);
Bitmap b = getViewBitmapWithoutBottom(webView);
// 可见高度
int webViewHeight = webView.getHeight();
// 容器内容实际高度
int contentHeight = (int) (webView.getContentHeight() * webView.getScale());
Bitmap temp;
if (contentHeight > webViewHeight) {
int screenWidth = getScreenWidth(context);
int absVh = webViewHeight - webView.getPaddingTop() - webView.getPaddingBottom();
do {
int restHeight = contentHeight - webViewHeight;
if (restHeight <= absVh) {
webView.scrollBy(0, restHeight);
webViewHeight += restHeight;
temp = getViewBitmap(webView);
} else {
webView.scrollBy(0, absVh);
webViewHeight += absVh;
temp = getViewBitmapWithoutBottom(webView);
}
b = mergeBitmap(webViewHeight, screenWidth, temp, 0, webView.getScrollY(), b, 0, 0);
} while (webViewHeight < contentHeight);
}
// 回滚到顶部
webView.scrollTo(0, 0);
webView.setVerticalScrollBarEnabled(true);
webView.setDrawingCacheEnabled(false);
webView.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;
}

/**
* 获取屏幕宽度
*/
public static int getScreenWidth(Context ctx) {
int w;
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB_MR2) {
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;
}
}

图片保存代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
private void takeCapture() {
Bitmap bitmap = webViewFragment.captureWebView(); //获取webview 长截图,内部代码是上面代码所示,调用了CaptureUtils.getWebViewBitmap();
String filePath = CachePathNew.getDCIMPath(activityInstance) + "线下支付_" + TimeUtils.getNowStringSimple() + ".jpg";
File file = new File(filePath);
FileOutputStream fos = null;
try {
fos = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 70, fos);
ToastUtils.makeText("图片已保存到\n" + fileName);
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
Uri uri = Uri.fromFile(file);
intent.setData(uri);
activityInstance.sendBroadcast(intent);
notification(filePath);
fos.flush();
fos.close();
} catch (Exception e) {
e.printStackTrace();
ToastUtils.makeText("保存失败");
CloseUtils.closeIO(fos);
}
}

发送notification,点击用系统图片浏览工具打开图片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
private void notification(String filePath) {
int indexS = filePath.indexOf("DCIM");
String subFilePath;
if (-1 != indexS) {
subFilePath = filePath.substring(indexS - 1);
} else {
subFilePath = filePath;
}
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

File file = new File(filePath);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "image/* ");
PendingIntent pendingIntent = PendingIntent.getActivity(activityInstance, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);

Notification.Builder builder = new Notification.Builder(activityInstance);
builder.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("已保存订单截图信息")
.setContentText(subFilePath)
.setAutoCancel(true)
.setContentIntent(pendingIntent);
Notification notification;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
notification = builder.getNotification();
} else {
notification = builder.build();
}
manager.notify((int) System.currentTimeMillis(), notification);
}

通知效果如下 本地通知

坚持原创技术分享,您的支持是对我最大的鼓励!