服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Android - Android WebView实现网页滚动截图

Android WebView实现网页滚动截图

2022-02-12 17:26神神的蜗牛 Android

这篇文章主要为大家详细介绍了Android WebView实现网页滚动截图,对整个网页进行截屏,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

WebView 网页滚动截屏,可对整个网页进行截屏而不是仅当前屏幕哦!

注意若Web页面存在position:fixed; 的话得在调用前设置为 position:absolute; 哦,否则会出现很多次的,请看下面的具体解说吧!!

?
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
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();
  // 容器内容实际高度
  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调用截屏操作

?
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
/**
  * 屏幕截图
  * @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 触发显示了一个原生的 Button按钮, 然后WebView跳转到 csdn 页面,然后点击截屏按钮用来触发网页截屏的。下面的图是我手动截的图,不是上面代码的效果哈,下下面很长的那张才是Java程序的网页截图。

Android WebView实现网页滚动截图

测试CSDN的网页完整截图:比较长哦~ 一般截图的功能都用于特殊的页面,如活动页面之类的,不会太长,那样是没有问题的。若是这种滚动到底部自动加载的话可能就会很长很长很长啦·····,自己看着办吧。。

Android WebView实现网页滚动截图

但这里有个BUG,顶部固定Banner条每次截屏都有,这个有解决办法,不过得是你自己的网页才有操作权限哦,需要修改JS啦。

当截图JS命令触发前,把顶部悬浮的样式设置为绝对定位,当截屏完成后再改回固定定位即可,没什么难度了。

截屏是需要一些时间的,所以需要预设一个定时器来操作,JS栗子如下:

JS.Capture 是 WebView 绑定的自定义 Javascript 类对象

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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);

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://blog.csdn.net/zhouzme/article/details/51804824

延伸 · 阅读

精彩推荐