Android 截图工具类

[贝聊科技] WebView截长图解决方案 以上是WebView截长图方法的总结和分享,对X5内核的截图也是尝试了多种途径最后找到满意的解决方案。另外,截长图会占用大量内存,容易触发OOM,所以代码中也要注意对OOM的处理。在使用了X5内核的项目中,使用WebView截取长图的判断逻辑可以是:// 有x5内核没有生效,并且Android版本是5.0及以上时,调用enableSlowWholeDocumentDraw()方便截取长图if (!/* 创建WebView ×/// 网页截图try { 阅读详情

DevUtils Github

CapturePictureUtils 截图工具类
支持 View、Activity、FrameLayout、RelativeLayout、LinearLayout、ListView、GridView、ScrollView、HorizontalScrollView、NestedScrollView、WebView、RecyclerView(GridLayoutManager、LinearLayoutManager、StaggeredGridLayoutManager)
方法 注释
setBitmapConfig 设置 Bitmap Config
setBackgroundColor 设置 Canvas 背景色
setPaint 设置画笔
snapshotWithStatusBar 获取当前屏幕截图, 包含状态栏 ( 顶部灰色 TitleBar 高度, 没有设置 android:theme 的 NoTitleBar 时会显示 )
snapshotWithoutStatusBar 获取当前屏幕截图, 不包含状态栏 ( 如果 android:theme 全屏, 则截图无状态栏 )
enableSlowWholeDocumentDraw 关闭 WebView 优化
snapshotByWebView 截图 WebView
snapshotByView 通过 View 绘制为 Bitmap
snapshotByViewCache 通过 View Cache 绘制为 Bitmap
snapshotByLinearLayout 通过 LinearLayout 绘制为 Bitmap
snapshotByFrameLayout 通过 FrameLayout 绘制为 Bitmap
snapshotByRelativeLayout 通过 RelativeLayout 绘制为 Bitmap
snapshotByScrollView 通过 ScrollView 绘制为 Bitmap
snapshotByHorizontalScrollView 通过 HorizontalScrollView 绘制为 Bitmap
snapshotByNestedScrollView 通过 NestedScrollView 绘制为 Bitmap
snapshotByListView 通过 ListView 绘制为 Bitmap
snapshotByGridView 通过 GridView 绘制为 Bitmap
snapshotByRecyclerView 通过 RecyclerView 绘制为 Bitmap
package dev.utils.app;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Picture;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Build;
import android.support.annotation.ColorInt;
import android.support.v4.widget.NestedScrollView;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.webkit.WebView;
import android.widget.FrameLayout;
import android.widget.GridView;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.ScrollView;

import dev.DevUtils;
import dev.utils.LogPrintUtils;

/**
 * detail: 截图工具类
 * @author Ttt
 * <pre>
 *     截图
 *     @see <a href="https://www.cnblogs.com/angel88/p/7933437.html"/>
 *     WebView 截长图解决方案
 *     @see <a href="https://www.jianshu.com/p/0faa70e88441"/>
 *     X5 WebView 使用 snapshotWholePage 方法清晰截图
 *     @see <a href="https://www.v2ex.com/t/583020"/>
 * </pre>
 */
public final class CapturePictureUtils {
   
   

    private CapturePictureUtils() {
   
   
    }

    // 日志 TAG
    private static final String TAG = CapturePictureUtils.class.getSimpleName();
    // Bitmap Config
    private static Bitmap.Config BITMAP_CONFIG = Bitmap.Config.RGB_565;
    // Canvas 背景色
    private static int BACKGROUND_COLOR = Color.TRANSPARENT;
    // 画笔
    private static Paint PAINT = new Paint();

    // ============
    // = 配置相关 =
    // ============

    /**
     * 设置 Bitmap Config
     * @param config {@link Bitmap.Config}
     */
    public static void setBitmapConfig(final Bitmap.Config config) {
   
   
        if (config == null) return;
        BITMAP_CONFIG = config;
    }

    /**
     * 设置 Canvas 背景色
     * @param backgroundColor 背景色
     */
    public static void setBackgroundColor(@ColorInt final int backgroundColor) {
   
   
        BACKGROUND_COLOR = backgroundColor;
    }

    /**
     * 设置画笔
     * @param paint {@link Paint}
     */
    public static void setPaint(final Paint paint) {
   
   
        if (paint == null) return;
        PAINT = paint;
    }

    // ========
    // = 截图 =
    // ========

    // ============
    // = Activity =
    // ============

    /**
     * 获取当前屏幕截图, 包含状态栏 ( 顶部灰色 TitleBar 高度, 没有设置 android:theme 的 NoTitleBar 时会显示 )
     * @param activity {@link Activity}
     * @return 当前屏幕截图, 包含状态栏
     */
    public static Bitmap snapshotWithStatusBar(final Activity activity) {
   
   
        try {
   
   
            View view = activity.getWindow().getDecorView();
            view.setDrawingCacheEnabled(true);
            // 重新创建绘图缓存, 此时的背景色是黑色
            view.buildDrawingCache();
            // 获取绘图缓存, 注意这里得到的只是一个图像的引用
            Bitmap cacheBitmap = view.getDrawingCache();
            if (cacheBitmap == null) return null;
            // 获取屏幕宽度
            int[] widthHeight = getScreenWidthHeight();

            Rect frame = new Rect();
            activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
            // 创建新的图片
            Bitmap bitmap = Bitmap.createBitmap(cacheBitmap, 0, 0, widthHeight[0], widthHeight[1]);
            // 释放绘图资源所使用的缓存
            view.destroyDrawingCache();
            return bitmap;
        } catch (Exception e) {
   
   
            LogPrintUtils.eTag(TAG, e, "snapshotWithStatusBar");
        }
        return null;
    }

    /**
     * 获取当前屏幕截图, 不包含状态栏 ( 如果 android:theme 全屏, 则截图无状态栏 )
     * @param activity {@link Activity}
     * @return 当前屏幕截图, 不包含状态栏
     */
    public static Bitmap snapshotWithoutStatusBar(final Activity activity) {
   
   
        try {
   
   
            View view = activity.getWindow().getDecorView();
            view.setDrawingCacheEnabled(true);
            // 重新创建绘图缓存, 此时的背景色是黑色
            view.buildDrawingCache();
            // 获取绘图缓存, 注意这里得到的只是一个图像的引用
            Bitmap cacheBitmap = view.getDrawingCache();
            if (cacheBitmap == null) return null;
            // 获取屏幕宽度
            int[] widthHeight = getScreenWidthHeight();
            // 获取状态栏高度
            int statusBarHeight = getStatusBarHeight(activity);

            Rect frame = new Rect();
            activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
            // 创建新的图片
            Bitmap bitmap = Bitmap.createBitmap(cacheBitmap, 0, statusBarHeight, widthHeight[0], widthHeight[1] - statusBarHeight);
            // 释放绘图资源所使用的缓存
            view.destroyDrawingCache();
            return bitmap;
        } catch (Exception e) {
   
   
            LogPrintUtils.eTag(TAG, e, "snapshotWithoutStatusBar");
        }
        return null;
    }

    // ===========
    // = WebView =
    // ===========

    /**
     * 关闭 WebView 优化
     * <pre>
     *     推荐在 setContentView 前调用
     *     {@link CapturePictureUtils#snapshotByWebView}
     * </pre>
     */
    public static void enableSlowWholeDocumentDraw() {
   
   
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
   
   
            android.webkit.WebView.enableSlowWholeDocumentDraw();
        }
    }

    /**
     * 截图 WebView
     * @param webView {@link WebView}
     * @return {@link Bitmap}
     */
    public static Bitmap snapshotByWebView(final WebView webView) {
   
   
        return snapshotByWebView(webView, Integer.MAX_VALUE, BITMAP_CONFIG, 0f);
    }

    /**
     * 截图 WebView
     * @param webView   {@link WebView}
     * @param maxHeight 最大高度
     * @return {@link Bitmap}
     */
    public static Bitmap snapshotByWebView(final WebView webView, final int maxHeight) {
   
   
        return snapshotByWebView(webView, maxHeight, BITMAP_CONFIG, 0f);
    }

    /**
     * 截图 WebView
     * @param webView {@link WebView}
     * @param scale   缩放比例
     * @return {@link Bitmap}
     */
    public static Bitmap snapshotByWebView(final WebView webView, final float scale) {
   
   
        return snapshotByWebView(webView, Integer.MAX_VALUE, BITMAP_CONFIG, scale);
    }

    /**
     * 截图 WebView
     * @param webView   {@link WebView}
     * @param maxHeight 最大高度
     * @param config    {@link Bitmap.Config}
     * @return {@link Bitmap}
     */
    public static Bitmap snapshotByWebView(final WebView webView, final int maxHeight, final Bitmap.Config config) {
   
   
        return snapshotByWebView(webView, maxHeight, config, 0f);
    }

    /**
     * 截图 WebView
     * <pre>
     *     TODO 在 Android 5.0 及以上版本, Android 对 WebView 进行了优化, 为了减少内存使用和提高性能
     *     TODO 使用 WebView 加载网页时只绘制显示部分, 如果我们不做处理, 就会出现只截到屏幕内显示的 WebView 内容, 其它部分是空白的情况
     *     TODO 通过调用 WebView.enableSlowWholeDocumentDraw() 方法可以关闭这种优化, 但要注意的是, 该方法需要在 WebView 实例被创建前就要调用,
     *     TODO 否则没有效果, 所以我们在 WebView 实例被创建前加入代码
     *     {@link CapturePictureUtils#enableSlowWholeDocumentDraw}
     * </pre>
     * @param webView   {@link WebView}
     * @param maxHeight 最大高度
     * @param config    {@link Bitmap.Config}
     * @param scale     缩放比例
     * @return {@link Bitmap}
     */
    public static Bitmap snapshotByWebView(final WebView webView, final int maxHeight,
                                           final Bitmap.Config config, final float scale) {
   
   
        if (webView != null && config != null) {
   
   
            // Android 5.0 以上
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
   
   
                try {
   
   
                    float newScale = scale;
                    if (newScale <= 0) {
   
   
                        // 该方法已抛弃, 可通过 setWebViewClient
                        // onScaleChanged(WebView view, float oldScale, float newScale)
                        // 存储并传入 newScale
                        newScale = webView.getScale();
                    }
                    int width = webView.getWidth();
                    int height = (int) (webView.getContentHeight() * newScale + 0.5);
                    // 重新设置高度
                    height = (height > maxHeight) ? maxHeight : height;
                    // 创建位图
                    Bitmap bitmap = Bitmap.createBitmap(width, height, config);
                    Canvas canvas = new Canvas(bitmap);
                    canvas.drawColor(BACKGROUND_COLOR);
                    webView.draw(canvas);
                    return bitmap;
                } catch (Exception e) {
   
   
                    LogPrintUtils.eTag(TAG, e, "snapshotByWebView - SDK_INT >= 21(5.0)");
                }
            } else {
   
   
                try {
   
   
                    Picture picture = webView.capturePicture();
                    int width = picture.getWidth();
                    int height = picture.getHeight();
                    if (width > 0 && height > 0) {
   
   
                        // 重新设置高度
                        height = (height > maxHeight) ? maxHeight : height;
                        // 创建位图
                        Bitmap bitmap = Bitmap.createBitmap(width, height, config);
                        Canvas canvas = new Canvas(bitmap);
                        canvas.drawColor(BACKGROUND_COLOR);
                        picture.draw(canvas);
                        return bitmap;
                    }
                } catch (Exception e) {
   
   
                    LogPrintUtils.eTag(TAG, e, "snapshotByWebView - SDK_INT < 21(5.0)");
                }
            }
        }
        return null;
    }

    // ========
    // = View =
    // ========

    /**
     * 通过 View 绘制为 Bitmap
     * @param view {@link View}
     * @return {@link Bitmap}
     */
    public static Bitmap snapshotByView(final View view) {
   
   
        return snapshotByView(view, BITMAP_CONFIG);
    }

    /**
     * 通过 View 绘制为 Bitmap
     * @param view   {@link View}
     * @param config {@link Bitmap.Config}
     * @return {@link Bitmap}
     */
    public static Bitmap snapshotByView(final View view, final Bitmap.Config config) {
   
   
        if (view == null || config == null) return null;
        try {
   
   
            Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), config);
            Canvas canvas = new Canvas(bitmap);
            canvas.drawColor(BACKGROUND_COLOR);
            view.layout(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
            view.draw(canvas);
            return bitmap;
        } catch (Exception e) {
   
   
            LogPrintUtils.eTag(TAG, e, "snapshotByView");
        }
        return null;
    }

    /**
     * 通过 View Cache 绘制为 Bitmap
     * @param view {@link View}
     * @return {@link Bitmap}
     */
    public static Bitmap snapshotByViewCache(final View view) {
   
   
        if (view == null) return null;
        try {
   
   
            // 清除视图焦点
            view.clearFocus();
            // 将视图设为不可点击
            view.setPressed(false);

            // 获取视图是否可以保存画图缓存
            boolean willNotCache = view.willNotCacheDrawing();
            view.setWillNotCacheDrawing(false);

            // 获取绘制缓存位图的背景颜色
            int color = view.getDrawingCacheBackgroundColor()
[贝聊科技] WebView截长图解决方案,h5前端开发入门 以上是WebView截长图方法的总结和分享,对X5内核的截图也是尝试了多种途径最后找到满意的解决方案。另外,截长图会占用大量内存,容易触发OOM,所以代码中也要注意对OOM的处理。在使用了X5内核的项目中,使用WebView截取长图的判断逻辑可以是:// 有x5内核没有生效,并且Android版本是5.0及以上时,调用enableSlowWholeDocumentDraw()方便截取长图if (!/* 创建WebView ×/// 网页截图try { 阅读详情

相关推荐

Android控件WebView实现完整截图

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

WSL2+Ubuntu-22.04搭建PX4仿真环境:从零避坑到一键起飞

本文详细指导在Windows系统上通过WSL2和Ubuntu-22.04搭建PX4仿真开发环境的完整流程,涵盖环境配置、源码下载、依赖安装、Gazebo仿真及常见错误解决方案,帮助开发者从零避坑实现无人机一键起飞仿真。

k8s6orchestrator的博客 670

Android汽车服务篇(一) CarService

本文主要说明了CarService这一系统服务的启动流程,以及一些关键成员的创建和初始化流程.同时简单介绍了一下客户端是如何获取和使用CarService对象, 如上文介绍的, CarService对象只是获取各个Manager的媒介,它本身并不承担管理传感器.空调等具体的任务.如果要获取车辆的相关信息,如车速, 车内空调温度,诊断信息, 或对车辆进行相关的控制,如升高和降低空调温度,控制座椅和车窗, 调节音量等,就要通过具体的Manager中的API和对应的服务来实现了.

u012514113的专栏 8145

当知识图谱遇见多模态:突破文本界限的智能认知革命

本文探讨了知识图谱与多模态技术的融合,揭示了其在医疗诊断、文化保护等领域的革命性应用。通过图神经网络、对比学习框架和跨模态注意力机制等技术,实现了文本、图像和音频数据的智能关联与认知。文章还分享了在Neo4j等图数据库中的实践案例和优化策略,为构建下一代智能认知系统提供了技术参考。

weixin_29197835的博客 462

Xilinx FPGA平台DDR3设计保姆式教程(1)DDR3基础简介

xilinx平台DDR3设计(1)DDR3简介 如果我们只是拿来用ddr搬砖,那么它就简单,知道IP怎么使用就好,但是要想知其所以然,理论知识是必备的,这也是我们初学者所欠缺的东西,慢慢修炼吧! 目录 一、DDR3简介 二、地址的概念及容量计算 三、重要给概念理解 3.2 列地址脉冲选通潜伏期 3.4 掩码 四、参考资料 一、DDR3简介 DDR3全称double-data-rate 3 synchronous dynamic RAM,即第三代双倍速率同步动态随机存储器。...

数字IC/FPGA杂货铺,找一找,或许有你想要的~ 1万+

【30天从零玩转AI应用开发】第16篇:智能体Agent入门——ReAct框架原理+首个会思考、会动手的AI实战

摘要: 本文介绍了AI智能体(Agent)的核心概念及其与普通大模型(LLM)的区别。通过ReAct(Reason+Act)框架,智能体实现了自主思考、调用工具和分步执行的能力。文章详细讲解了LangChain Agent的四大组件,并推荐新手使用ZERO_SHOT_REACT_DESCRIPTION类型。最后提供了一个完整的智能体实战代码示例,该智能体具备数学计算和天气查询功能,能够自主选择工具完成任务,展示了AI从”被动回答“到”主动行动“的关键进化。

在上海谋生的软件喵记录喵生 626

手把手教你学Simulink--控制执行场景实例:基于Simulink的智能车辆自动紧急制动(AEB)仿真

本文完成了基于 Simulink 的智能车辆自动紧急制动(AEB),实现了:✅ 构建前车急刹与静止障碍物典型场景✅ 设计基于 TTC 的三级 AEB 决策逻辑✅ 验证在高风险场景下有效避免碰撞✅ 掌握从风险评估到制动执行的完整安全链✅ 为ADAS 主动安全功能开发奠定基础。

MHD0815的博客 236

Calibre 3Dstack Flow Example(5-2)

本文详细介绍了Calibre3DSTACK工具在3D-IC设计验证中的应用。主要内容包括:1)连通性检查(LVS)规则编写,重点说明connected命令的使用方法和多文本标签处理;2)设计规则检查(DRC)实现,涵盖层间距检查和焊盘重叠检查;3)系统网表生成器操作流程,从芯片导入到网连通性定义;4)两种规则文件语法(扩展语法和传统语法)的编写示例;5)验证报告文件格式解析。通过具体案例演示了如何建立完整的3D-IC验证流程,包括芯片定义、装配操作、电气连接验证和物理规则检查等关键步骤,为3D-IC设计验证

u013620135的博客 2336

外骨骼机器人(二):自适应振荡器

振荡器是一种数学工具,可以用于实时跟踪、预测类周期信号的频率、相位、幅值等,而助行外骨骼机器人需要自动适应人体的行走频率、幅度,两者相结合,就能使助行外骨骼机器人拥有更舒适、更自然的行走步态。 ......

行者无疆的博客 4263

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

上一篇: Android ImageLoader 工具类
下一篇: Android View 链式调用快捷设置 Helper 类
「已注销」
博客等级 码龄11年 14粉丝 27原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值