Android 截图工具类

本文介绍了Android开发中的截图工具类CapturePictureUtils,它支持对View、Activity、多种布局及滚动视图如ScrollView、WebView等进行截图操作,包括RecyclerView的截图功能,无论其使用哪种LayoutManager。
摘要由CSDN通过智能技术生成

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();
            // 设置绘图背景颜色
            view.setDrawingCacheBackgroundColor(0);
            if (color != 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值