美文网首页Android开发经验谈Android开发Android技术知识
Android之布局(layout)转化成图片(bitmap)

Android之布局(layout)转化成图片(bitmap)

作者: Android开发架构 | 来源:发表于2019-01-30 16:31 被阅读12次

    以前和IOS同事讨论过怎么截屏的操作,当时也不明白,怎么可能将列表截图呢?毕竟列表可以上下滑动呀!

    最近有个需求,原生布局的界面,生成一个体检报告,我知道这个界面用H5做是可以生成pdf打印的。但已经使用原生做了,并且打印机可以打印bitmap转的byte数组文件。在此记录:布局转图片。

    布局文件没有超出屏幕高度:

    private Bitmap getViewBitmap(View v) {
            v.clearFocus();
            v.setPressed(false);
            boolean willNotCache = v.willNotCacheDrawing();
            v.setWillNotCacheDrawing(false);
            int color = v.getDrawingCacheBackgroundColor();
            v.setDrawingCacheBackgroundColor(0);
            if (color != 0) {
                v.destroyDrawingCache();
            }
            v.buildDrawingCache();
            Bitmap cacheBitmap = v.getDrawingCache();
            if (cacheBitmap == null) {
                return null;
            }
            Bitmap bitmap = Bitmap.createBitmap(cacheBitmap);
            v.destroyDrawingCache();
            v.setWillNotCacheDrawing(willNotCache);
            v.setDrawingCacheBackgroundColor(color);
            return bitmap;
        }
    

    布局超出了屏幕的高度(Scrollview处理):

    public static Bitmap getBitmapByView(ScrollView scrollView) {
            int h = 0;
            Bitmap bitmap = null;
            for (int i = 0; i < scrollView.getChildCount(); i++) {
                h += scrollView.getChildAt(i).getHeight();
            }
            bitmap = Bitmap.createBitmap(scrollView.getWidth(), h,
                    Bitmap.Config.RGB_565);
            final Canvas canvas = new Canvas(bitmap);
            scrollView.draw(canvas);
            return bitmap;
        }
    

    以上两种方法则可以满足layout生成bitmap,然后bitmap可以再生成图片:

    public static void savePhotoToSDCard(Bitmap photoBitmap, String path, String photoName) {
            if (checkSDCardAvailable()) {
                File dir = new File(path);
                if (!dir.exists()) {
                    dir.mkdirs();
                }
     
                File photoFile = new File(path, photoName + ".png");
                FileOutputStream fileOutputStream = null;
                try {
                    fileOutputStream = new FileOutputStream(photoFile);
                    if (photoBitmap != null) {
                        if (photoBitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream)) {
                            fileOutputStream.flush();
                        }
                    }
                } catch (FileNotFoundException e) {
                    photoFile.delete();
                    e.printStackTrace();
                } catch (IOException e) {
                    photoFile.delete();
                    e.printStackTrace();
                } finally {
                    try {
                        fileOutputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
     
    //检查是否有SD卡
    public static boolean checkSDCardAvailable() {
            return android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED);
        }
    

    使用方法:

    //contentLly是布局文件   
    Bitmap bitmap = getBitmapByView(contentLly);                
    ImageUtils.savePhotoToSDCard(bitmap, "/sdcard/file", "img");
    

    按照指定的宽高(或指定比例)来重新设置bitmap

        //把传进来的bitmap对象转换为宽度为x,长度为y的bitmap对象
        public static Bitmap  transform(Bitmap b, float x, float y) {
            int w = b.getWidth();
            int h = b.getHeight();
            float sx = (float) x / w;
            float sy = (float) y / h;
            Matrix matrix = new Matrix();
     
            // 也可以按两者之间最大的比例来设置放大比例,这样不会是图片压缩
            // float bigerS = Math.max(sx, sy);
            // matrix.postScale(bigerS, bigerS);
     
            // 长和宽放大缩小的比例
            matrix.postScale(sx, sy);
            Bitmap resizeBmp = Bitmap.createBitmap(b, 0, 0, w,
                    h, matrix, true);
            return resizeBmp;
        }
    

    对于没有在屏幕上显示的控件获取bitmap

    //然后View和其内部的子View都具有了实际大小,也就是完成了布局,相当与添加到了界面上。接着就可以创建位图并在上面绘制了:
        private void layoutView(View v) {
            DisplayMetrics metric = new DisplayMetrics();
            mActivity.getWindowManager().getDefaultDisplay().getMetrics(metric);
            int width = metric.widthPixels;     // 屏幕宽度(像素)
            int height = metric.heightPixels;   // 屏幕高度(像素)
            // 整个View的大小 参数是左上角 和右下角的坐标
            v.layout(0, 0, width, height);
            int measuredWidth = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY);
            int measuredHeight = View.MeasureSpec.makeMeasureSpec(10000, View.MeasureSpec.AT_MOST);
            /** 当然,measure完后,并不会实际改变View的尺寸,需要调用View.layout方法去进行布局。
             * 按示例调用layout函数后,View的大小将会变成你想要设置成的大小。
             */
            v.measure(measuredWidth, measuredHeight);
            v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
        }
     
        private Bitmap loadBitmapFromView(View v) {
            int w = v.getWidth();
            int h = v.getHeight();
            Bitmap bmp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
            Canvas c = new Canvas(bmp);
     
            c.drawColor(Color.WHITE);
            /** 如果不设置canvas画布为白色,则生成透明 */
     
            v.layout(0, 0, w, h);
            v.draw(c);
     
            return bmp;
        }
    

    使用方法:

    //相当与添加到了界面上
    layoutView(contentLly);
     
    //获取bitmap数据
    loadBitmapFromView(contentLly);
    

    免费获取安卓开发架构的资料(包括Fultter、高级UI、性能优化、架构师课程、 NDK、Kotlin、混合式开发(ReactNative+Weex)和一线互联网公司关于android面试的题目汇总可以加:936332305 / 链接:点击链接加入【安卓开发架构】:https://jq.qq.com/?_wv=1027&k=515xp64

    image

    相关文章

      网友评论

        本文标题:Android之布局(layout)转化成图片(bitmap)

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