WebView 网页滚动截屏,可对整个网页进行截屏而不是仅当前屏幕哦!
注意若Web页面存在position:fixed; 的话得在调用前设置为 position:absolute; 哦,否则会出现很多次的,请看下面的具体解说吧!!
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 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调用截屏操作
/** * 屏幕截图 * @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程序的网页截图。
测试CSDN的网页完整截图:比较长哦~ 一般截图的功能都用于特殊的页面,如活动页面之类的,不会太长,那样是没有问题的。若是这种滚动到底部自动加载的话可能就会很长很长很长啦·····,自己看着办吧。。
但这里有个BUG,顶部固定Banner条每次截屏都有,这个有解决办法,不过得是你自己的网页才有操作权限哦,需要修改JS啦。
当截图JS命令触发前,把顶部悬浮的样式设置为绝对定位,当截屏完成后再改回固定定位即可,没什么难度了。
截屏是需要一些时间的,所以需要预设一个定时器来操作,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);
恋爱进行时九游版
恋爱进行时九游版是一款以模拟恋爱玩法为核心的角色扮演手游,精
皇室对决fr(Null’s Royale)
皇室对决fr,即皇室战争的私服变态版本,在该版本中玩家能够拥
养了个猫联机版游戏
养了个猫小游戏一个猫咪主题的模拟经营类型的手游,在游戏中我那
模拟山羊收获日小米版
模拟山羊收获日小米版是一个极其魔性的手机游戏,在游戏中玩家将
女配逆袭之素衣
女配逆袭之素衣是一款恋爱养成冒险的一款游戏,可以角色扮演,在