美文网首页Android开发Android技术知识Android开发
Android屏幕截图,View截图(干货)

Android屏幕截图,View截图(干货)

作者: 冰点k | 来源:发表于2018-07-23 15:28 被阅读46次

    不多说废话,直接上代码

    屏幕截图,亲测可用,基于Activity

    /**
         * 屏幕截图
         * @param activity
         * @return
         */
        public static Bitmap screenShot(AppCompatActivity activity,String filePath) {
            if (activity == null){
                Logger.getLogger().e("screenShot--->activity is null");
                return null;
            }
            View view = activity.getWindow().getDecorView();
            //允许当前窗口保存缓存信息
            view.setDrawingCacheEnabled(true);
            view.buildDrawingCache();
    
            int navigationBarHeight = ScreenUtils.getNavigationBarHeight(view.getContext());
    
    
            //获取屏幕宽和高
            int width = ScreenUtils.getScreenWidth(view.getContext());
            int height = ScreenUtils.getScreenHeight(view.getContext());
    
            // 全屏不用考虑状态栏,有导航栏需要加上导航栏高度
            Bitmap bitmap = null;
            try {
                bitmap = Bitmap.createBitmap(view.getDrawingCache(), 0, 0, width,
                        height + navigationBarHeight);
            } catch (Exception e) {
                // 这里主要是为了兼容异形屏做的处理,我这里的处理比较仓促,直接靠捕获异常处理
                // 其实vivo oppo等这些异形屏手机官网都有判断方法
                // 正确的做法应该是判断当前手机是否是异形屏,如果是就用下面的代码创建bitmap
    
    
                String msg = e.getMessage();
                // 部分手机导航栏高度不占窗口高度,不用添加,比如OppoR15这种异形屏
                if (msg.contains("<= bitmap.height()")){
                    try {
                        bitmap = Bitmap.createBitmap(view.getDrawingCache(), 0, 0, width,
                                height);
                    } catch (Exception e1) {
                        msg = e1.getMessage();
                        // 适配Vivo X21异形屏,状态栏和导航栏都没有填充
                        if (msg.contains("<= bitmap.height()")) {
                            try {
                                bitmap = Bitmap.createBitmap(view.getDrawingCache(), 0, 0, width,
                                        height - ScreenUtils.getStatusHeight(view.getContext()));
                            } catch (Exception e2) {
                                e2.printStackTrace();
                            }
                        }else {
                            e1.printStackTrace();
                        }
                    }
                }else {
                    e.printStackTrace();
                }
            }
    
            //销毁缓存信息
            view.destroyDrawingCache();
            view.setDrawingCacheEnabled(false);
    
            if (null != bitmap){
                try {
                    compressAndGenImage(bitmap,filePath);
                    Logger.getLogger().d("--->截图保存地址:" + filePath);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return bitmap;
        }
    

    View截图,亲测可用   参考

    /**
         * view截图
         * @return
         */
        public static void viewShot(@NonNull final View v, @Nullable final String filePath,
                      @Nullable final ShotCallback shotCallback){
            if (null == v) {
                Logger.getLogger().e("view is null");
                return;
            }
            v.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout() {
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                        v.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                    } else {
                        v.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                    }
                    // 核心代码start
                    Bitmap bitmap = Bitmap.createBitmap(v.getWidth() , v.getHeight(), Bitmap.Config.ARGB_8888);
                    Canvas c = new Canvas(bitmap);
                    v.layout(0, 0, v.getLayoutParams().width, v.getLayoutParams().height);
                    v.draw(c);
                    // end
                    String savePath = filePath;
                    if (TextUtils.isEmpty(savePath)){
                        savePath = createImagePath();
                    }
                    try {
                        compressAndGenImage(bitmap,savePath);
                        Logger.getLogger().d("--->截图保存地址:" + savePath);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    if (null != shotCallback){
                        shotCallback.onShotComplete(bitmap,savePath);
                    }
                }
            });
        }
    
    关于View截图,如果需要实现后台截图,也就是截图的时候view不在屏幕显示显示,只需要把要截图的View设置成invisible就可以了。

    另外再附上生成图片和保存到手机SD卡上的方法,一步到位,直接粘贴拿去就用

      private static final String IMAGE_FILE_NAME_TEMPLATE = "Image%s.jpg";
      private static final String IMAGE_FILE_PATH_TEMPLATE = "%s/%s";
    
        /**
         * 存储到sdcard
         *
         * @param bmp
         * @param maxSize 为0不压缩
         * @return
         */
        public static String saveToSD(Bitmap bmp,int maxSize) {
            if (bmp == null){
                Logger.getLogger().e("saveToSD--->bmp is null");
                return "";
            }
            //判断sd卡是否存在
            if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                //文件名
                long systemTime = System.currentTimeMillis();
                String imageDate = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date(systemTime));
                String mFileName = String.format(IMAGE_FILE_NAME_TEMPLATE, imageDate);
    
                //文件全名
                String mstrRootPath = FileUtil.getPackageDCIMPath(AFApplication.applicationContext);
                String filePath = String.format(IMAGE_FILE_PATH_TEMPLATE, mstrRootPath, mFileName);
    
                Logger.getLogger().d("saveToSD--->file path:" + filePath);
                File file = new File(filePath);
                if (!file.exists()) {
                    try {
                        file.createNewFile();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                Logger.getLogger().d("saveToSD--->file AbsolutePath:" + filePath);
                try {
                    compressAndGenImage(bmp,filePath,maxSize);
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    bmp.recycle();
                }
    
                return filePath;
            }
            return "";
        }
    
        public static String createImagePath(){
            //判断sd卡是否存在
            if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                //文件名
                long systemTime = System.currentTimeMillis();
                String imageDate = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date(systemTime));
                String mFileName = String.format(IMAGE_FILE_NAME_TEMPLATE, imageDate);
    
                //文件全名
                String mstrRootPath = FileUtil.getPackageDCIMPath(AFApplication.applicationContext);
                String filePath = String.format(IMAGE_FILE_PATH_TEMPLATE, mstrRootPath, mFileName);
                File file = new File(filePath);
                if (!file.exists()) {
                    try {
                        file.createNewFile();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                return filePath;
            }
            return "";
        }
    
        public static void compressAndGenImage(Bitmap image, String outPath, int maxSize) throws IOException {
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            // scale
            int options = 100;
            // Store the bitmap into output stream(no compress)
            image.compress(Bitmap.CompressFormat.JPEG, options, os);
            // Compress by loop
            if (maxSize != 0) {
                while (os.toByteArray().length / 1024 > maxSize) {
                    // Clean up os
                    os.reset();
                    // interval 10
                    options -= 10;
                    image.compress(Bitmap.CompressFormat.JPEG, options, os);
                }
            }
    
            // Generate compressed image file
            FileOutputStream fos = new FileOutputStream(outPath);
            fos.write(os.toByteArray());
            Logger.getLogger().d("compressAndGenImage--->文件大小:" + os.size()+",压缩比例:" + options);
            fos.flush();
            fos.close();
        }
    
        public static void compressAndGenImage(Bitmap image, String outPath) throws IOException {
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            // scale
            int options = 70;
            // Store the bitmap into output stream(no compress)
            image.compress(Bitmap.CompressFormat.JPEG, options, os);
    
            // Generate compressed image file
            FileOutputStream fos = new FileOutputStream(outPath);
            fos.write(os.toByteArray());
            Logger.getLogger().d("compressAndGenImage--->文件大小:" + os.size()+",压缩比例:" + options);
            fos.flush();
            fos.close();
        }
    

    喜欢的麻烦动动小手点个赞来支持我,有不对的地方欢迎大家指正,有什么问题也可以在下方留言,我看到后会第一时间回复!

    相关文章

      网友评论

      • Leoxhmm:代码能不能贴全一点呀 对新手十分不友好
      • 100岁的Android工程师:这种方案只能针对普通view的,当遇到surfaceview的时候就截不到了,而且目前还没有优雅的方法能够用代码能够静默截图,用canvas也实现不到,比如对于使用了unity的player的activity,根本截不到,因为你拿不到视图帧!5.0以上可以用Media截屏,但是又会要权限,而且会有延迟
      • 一铁木真一:如果activity里面放了一个视频(surfaceview),或者当前可视界面有通过WindowManger添加显示的view。那么文章里的方案就不可行了。楼主有什么好办法?(基于4.4版本)
        冰点k:SurfaceView的话,可以参考View的截图方式,创建一个Canvas,把SurfaceView的内容绘制在Canvas上,然后就可以拿到Bitmap了,然后再拼接到原来SurfaceView的位置上

      本文标题:Android屏幕截图,View截图(干货)

      本文链接:https://www.haomeiwen.com/subject/qokjmftx.html