Android WebView实现网页滚动截图

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 <= 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调用截屏操作

/**
  * 屏幕截图
  * @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);

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

您可能感兴趣的文章:

  • Android控件WebView实现完整截图
  • Android使用WebView实现截图分享功能
  • Android 中WebView 截图的实现方式
  • Android中通过view方式获取当前Activity的屏幕截图实现方法
  • Android中如何获取视频文件的截图、缩略图
  • Android模拟器中窗口截图存成文件实现思路及代码
  • Android实现截图和分享功能的代码
  • 详解有关Android截图与录屏功能的学习
  • Android获取常用辅助方法(获取屏幕高度、宽度、密度、通知栏高度、截图)
  • android webView截图的4种方法
(0)

相关推荐

  • Android获取常用辅助方法(获取屏幕高度、宽度、密度、通知栏高度、截图)

    我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现.下面就分享一下Android中常用的一些辅助方法: 获取屏幕高度: /** * 获得屏幕高度 * @param context * @return * by Hankkin at:2015-10-07 21:15:59 */ public static int getScreenWidth(Context context) { WindowManager wm = (WindowManager) cont

  • Android中通过view方式获取当前Activity的屏幕截图实现方法

    此方法是通过view的方式获取当前activity的屏幕截图,并不是framebuffer的方式,所以有一定的局限性.但是这种方法相对简单,容易理解. 首先通过下面的函数获取Bitmap格式的屏幕截图: 复制代码 代码如下: public Bitmap myShot(Activity activity) { // 获取windows中最顶层的view View view = activity.getWindow().getDecorView(); view.buildDrawingCache()

  • android webView截图的4种方法

    android 在webView里面截图大概有四种方式,具体内容如下 1.获取到DecorView然后将DecorView转换成bitmap然后写入到文件里面. View view = getWindow().getDecorView(); Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitma

  • Android实现截图和分享功能的代码

    先给大家展示下效果图吧 直接上代码: xml的布局: <Button android:id="@+id/btn_jp" android:layout_marginTop="10dip" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:tex

  • Android使用WebView实现截图分享功能

    在APP项目的开发过程中,经常会用到分享图片的功能,有时候还需要根据当前用户信息获取指定的分享图片,比如要求在用户分享图中显示用户名.Uid.用户头像等信息.想到的实现方法主要有两点: 1.通过android SDK自带的Canvas方法进行绘制. 2.通过webView实现客户端与H5交互,然后将H5界面做截图处理. 本文主要介绍第二种方式的实现过程,第一种方式的实现方法,后续有时间会在博客中做说明,下面开始本文内容. 首先确定我们要实现的逻辑: 1.客户端与H5的交互,客户端将用户信息(用户

  • Android中如何获取视频文件的截图、缩略图

    背景 公司最近要求给我负责的APP加上视频录制和发布的功能,我简单的完成了基本的录制和视频压缩功能,后来发现发布接口需要上传视频的截图,网上搜索了一下资料,在这里整理一下. 代码实现 /** * 获取视频文件截图 * * @param path 视频文件的路径 * @return Bitmap 返回获取的Bitmap */ public static Bitmap getVideoThumb(String path) { MediaMetadataRetriever media = new Me

  • Android 中WebView 截图的实现方式

    Hybrid App 中网页部分的分享方式越来越趋向于多元化,比较常见的用户操作方式有:复制网页链接式,直接选择目标应用自动分享式等.其中,截图行为,越来越成为丰富用户操作.备受用户喜爱的互动方式之一,我们在很多内容社区类应用中都能看到这种功能.这篇文章总结一下 Android 应用中 WebView 截图的实现方式. WebView 作为一种特殊的控件,自然不能像其他系统 View 或者截屏的方式来获取截图(多为截取长图).如: public static Bitmap getScreenSh

  • Android模拟器中窗口截图存成文件实现思路及代码

    Android模拟器内容是用OpenGL渲染的,所以用一般的编程截图(如PrintWindow()等)会是黑屏.这是因为画的东西放在framebuffer里. 一种方法是通过adb把guest的framebuffer数据/dev/graphics/fb0倒到host,再转为图片.但这样速度比较慢. 好在Android模拟器中把guest的framebuffer传到host进行显示,所以在host端只要将framebuffer输出到文件即可. 首先定义每次framebuffer更新时的回调函数:

  • Android控件WebView实现完整截图

    最近总能看到好多APP都支持文章和网页的长截图,出于好奇研究了一下,分享给大家. 网上有好多的例子,其中好多都是已经过时的就不在复述了,我发现有一种还是比较通用的方法. //android 5.0 之后需要开启浏览器的整体缓存才能截取整个Web if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { WebView.enableSlowWholeDocumentDraw(); } 首先需要在WebView初始化之前(一般就是set

  • 详解有关Android截图与录屏功能的学习

    简单的截屏和录屏功能. 因为MediaProjection是5.0以上才出现的,所以今天所讲述功能实现,只在5.0以上的系统有效. 截屏: 步骤如下: 1:获取MediaProjectionManager 2:通过MediaProjectionManager.createScreenCaptureIntent()获取Intent 3:通过startActivityForResult传入Intent然后在onActivityResult中通过MediaProjectionManager.getMe

随机推荐