Android 工具类 —— 截屏
16lz
2021-01-23
Android 8.0 截屏
/** * 快照工具 */public class SnapShotUtil { /** * 获取屏幕截图。 */ public static Bitmap getScreen(Activity activity) { View view = activity.getWindow().getDecorView(); //启用绘制缓存 view.setDrawingCacheEnabled(true); //构建缓存视图 view.buildDrawingCache(); //获得视图的缓存图像 Bitmap cache = view.getDrawingCache(); //状态栏区只有背景色,却截取不到任何文字,因此要手动裁剪掉 Rect activityRect = new Rect(); //获取当前activity的可见区域 view.getWindowVisibleDisplayFrame(activityRect); Bitmap bitmap = BitmapUtil.crop(cache, activityRect); //关闭视图缓存机制 view.setDrawingCacheEnabled(false); //删除视图缓存 view.destroyDrawingCache(); return bitmap; } /** * 通过系统录屏截图 */ public static void getScreenProjection(FragmentActivity activity, Callback callback) { //调用系统服务,会弹出一个是否允许录屏的对话框 MediaProjectionManager mediaProjectionManager = (MediaProjectionManager) activity.getSystemService(Context.MEDIA_PROJECTION_SERVICE); Intent intent = mediaProjectionManager.createScreenCaptureIntent(); ActivityLauncher.init(activity).startActivityForResult(intent, (resultCode, data) -> { MediaProjection mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, data); //返回null,说明用户拒绝 if (mediaProjection == null) { return; } Point screenSize = DisplayUtil.getResolution(activity); /* The producer output buffer format 0x1 doesn't match the ImageReader's configured buffer format 0x4. 所以各式只能用8888,不能用565 */ ImageReader imageReader = ImageReader.newInstance(screenSize.x, screenSize.y, PixelFormat.RGBA_8888, 1); int densityDpi = DisplayUtil.getDensityDpi(activity); VirtualDisplay virtualDisplay = mediaProjection.createVirtualDisplay("screen-mirror", screenSize.x, screenSize.y, densityDpi, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, imageReader.getSurface(), null, //传null表示在回调在主线程中执行 null); //在获取Image的时候,得先暂停1秒左右,不然就会获取失败(原因未知) SystemClock.sleep(1000); Image image = imageReader.acquireLatestImage(); Bitmap bitmap = BitmapUtil.fromImage(image); image.close(); callback.invoke(bitmap); virtualDisplay.release(); }); } /* Android 在5.0 之后支持了实时录屏的功能。 通过实时录屏我们可以拿到截屏的图像。 同时可以通过在Service中处理实现后台的录屏。 */ @RequiresApi(Build.VERSION_CODES.O) public static void getViewBySystem(Activity activity, View view, Callback callback) { int width = view.getWidth(); int height = view.getHeight(); //这里只能用8888,不能用其它的,否则一片黑取不到图像 Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888, true); Window window = activity.getWindow(); final int[] location = new int[2]; view.getLocationInWindow(location); Rect rect = new Rect(location[0], location[1], location[0] + view.getWidth(), location[1] + view.getHeight()); final Handler handler = new Handler(Looper.getMainLooper()); PixelCopy.request(window, rect, bitmap, copyResult -> { callback.invoke(copyResult == PixelCopy.SUCCESS ? bitmap : null); }, handler); } /** * 截取视图 */ public static Bitmap getView(View view) { view.setDrawingCacheEnabled(true); view.buildDrawingCache(); Bitmap cache = view.getDrawingCache(); Bitmap bitmap = BitmapUtil.clone(cache); view.setDrawingCacheEnabled(false); view.destroyDrawingCache(); return bitmap; } /** * 截取 ScrollView 视图 */ public static Bitmap getRecyclerView(RecyclerView recyclerView, int maxSize) { RecyclerView.Adapter adapter = recyclerView.getAdapter(); int height = 0; //取列表项和缓存项中的最小值 int size = Math.min(maxSize, adapter.getItemCount()); //把每个item的绘图缓存存储在LruCache中 LruCache bitmapCache = new LruCache<>(maxSize); for (int i = 0; i < size; i++) { //手动调用创建和绑定ViewHolder方法, RecyclerView.ViewHolder holder = adapter.createViewHolder(recyclerView, adapter.getItemViewType(i)); adapter.onBindViewHolder(holder, i); /* 测量 MeasureSpec.EXACTLY - 视图应该是这么多像素,无论它实际上有多大。 MeasureSpec.AT_MOST - 如果视图的尺寸较小,则视图可以是此尺寸或更小。 MeasureSpec.UNSPECIFIED - 视图可以是它需要的任何大小,以显示它需要显示的内容。 */ holder.itemView.measure( View.MeasureSpec.makeMeasureSpec(recyclerView.getWidth(), View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)); //布局 holder.itemView.layout(0, 0, holder.itemView.getMeasuredWidth(), holder.itemView.getMeasuredHeight()); //开启视图绘制缓存 holder.itemView.setDrawingCacheEnabled(true); holder.itemView.buildDrawingCache(); Bitmap drawingCache = holder.itemView.getDrawingCache(); Bitmap cacheClone = BitmapUtil.clone(drawingCache); if (cacheClone != null) { bitmapCache.put(i, cacheClone); } //禁用视图绘制缓存 holder.itemView.setDrawingCacheEnabled(false); //销毁视图绘制缓存 holder.itemView.destroyDrawingCache(); //获取itemView的实际高度并累加// height += holder.itemView.getMeasuredHeight(); height += cacheClone.getHeight(); } //这里只能用8888,不能用其它的,否则一片黑取不到图像 Bitmap dstBitmap = Bitmap.createBitmap(recyclerView.getWidth(), height, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(dstBitmap); Paint paint = new Paint(); for (int i = 0, top = 0; i < size; i++) { Bitmap bitmap = bitmapCache.get(i); canvas.drawBitmap(bitmap, 0, top, paint); top += bitmap.getHeight(); } return dstBitmap; } /** * 截取 ScrollView 视图 */ public static Bitmap getScrollView(ScrollView scrollView) { int height = 0; //ScrollView理论上只有一个子View for (int i = 0; i < scrollView.getChildCount(); i++) { height += scrollView.getChildAt(i).getHeight(); } //这里只能用8888,不能用其它的,否则一片黑取不到图像 Bitmap bitmap = Bitmap.createBitmap(scrollView.getWidth(), height, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); scrollView.draw(canvas); return bitmap; }}
public interface Callback { void invoke() {}}
更多相关文章
- android 从webview中读取缓存的图片
- android对大图片的缓存处理
- android image cache 图片缓存 异步 下载
- 简析Android中LruCache缓存类
- Android中如何实现图像的闪动
- Android Studio 无法预览xml布局视图
- android如何让webview里的资源访问本地缓存
- Android 中的图形图像的渲染
- Android视图绘画与属性动画