zoukankan      html  css  js  c++  java
  • 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程序的网页截图。。。

    Android之WebView网页滚动截图

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

    Android之WebView网页滚动截图

    但这里有个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);
  • 相关阅读:
    在.net C#里怎样调用非托管动态库函数dll?
    Visual C#中的MDI编程
    c#图形装置接口
    粗糙集理论介绍
    Using .NET DataSet in Flex 2
    图象光照研究路线
    基于光照模型应用前景
    使用netsh.exe配置TCP/IP
    vb.net 防止MDI子窗体被多次实例化的四种方法
    一定概率选中某一字母
  • 原文地址:https://www.cnblogs.com/zhouzme/p/5758388.html
Copyright © 2011-2022 走看看