将xml布局加载成Bitmap(图片)

2,633 阅读2分钟

起因

有一个需求,需要将xml布局,生成成一张图片。这样可以将图片导出保存,或者在ImageView上自适应的展示。(在布局多变的情况下,不用一直改字体大小啥的)。
百度了一圈,都达不到想要的,然后自己写了一个

功能

  1. 将xml布局加载成Bitmap
  2. 将随便什么View加载成Bitmap
  3. View已经渲染完成显示在页面上
  4. 加载的xml是ScrollView
  5. 背景可以透明,保存以后不会有黑色的底

效果

将这个xml,加载生成一个bitmap,然后加载到ImageView上,这样可以随意改变大小,自适应展示。或者可以保存图片到本地。

image.png

image.png

image.png

代码

使用

fun loadImageView(){
    var bitmap= ImageUtils.loadBitmap(this,R.layout.window_coupon)
    iv_image.setImageBitmap(bitmap)
}

工具类

/**
 * 将 Bitmap 保存到SD卡
 *
 * @param context
 * @param mybitmap
 * @param
 * @return
 */
public static Uri saveBitmapToSdCard(Context context, Bitmap mybitmap) {
    Uri uri = null;
    //创建位图保存目录
    String path = Environment.getExternalStorageDirectory() + "/1000ttt/";
    File sd = new File(path);
    if (!sd.exists()) {
        sd.mkdir();
    }
    String fileName = "mm_" + System.currentTimeMillis();
    File file = new File(path + fileName + ".png");
    FileOutputStream fileOutputStream = null;
    if (!file.exists()) {
        try {
            // 判断SD卡是否存在,并且是否具有读写权限
            if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                fileOutputStream = new FileOutputStream(file);
                mybitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOutputStream);
                fileOutputStream.flush();
                fileOutputStream.close();

                //update gallery
                Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
                uri = Uri.fromFile(file);
                intent.setData(uri);
                context.sendBroadcast(intent);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    if (Build.VERSION.SDK_INT >= 24) {
        try {
            uri = Uri.parse(MediaStore.Images.Media.insertImage(context.getContentResolver(), file.getAbsolutePath(), fileName, null));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    } else {
        uri = Uri.fromFile(file);
    }
    return uri;
}

/**
 * 获取一个 View 的缓存视图
 *  (前提是这个View已经渲染完成显示在页面上)
 * @param view
 * @return
 */
public static Bitmap getCacheBitmapFromView(View view) {
    final boolean drawingCacheEnabled = true;
    view.setDrawingCacheEnabled(drawingCacheEnabled);
    view.buildDrawingCache(drawingCacheEnabled);
    final Bitmap drawingCache = view.getDrawingCache();
    drawingCache.setConfig(Bitmap.Config.ARGB_8888);
    Bitmap bitmap;
    if (drawingCache != null) {
        bitmap = Bitmap.createBitmap(drawingCache);
        bitmap.setConfig(Bitmap.Config.ARGB_8888);
        view.setDrawingCacheEnabled(false);
    } else {
        bitmap = null;
    }
    return bitmap;
}


public static View loadView(Context context, int viewResId) {
    if (context == null || viewResId <= 0) return null;
    FrameLayout frameLayout = new FrameLayout(context);
    View view = LayoutInflater.from(context).inflate(viewResId, frameLayout, false);
    return view;
}

/**
 * 从静态资源中,渲染并导出一张Bitmap图片
 *
 * @param context
 * @param viewResId
 * @return
 */
public static Bitmap loadBitmap(Context context, int viewResId) {
    if (context == null || viewResId <= 0) return null;
    return loadBitmap(loadView(context, viewResId));
}

public static Bitmap loadBitmap(View v) {
    int measuredWidth = View.MeasureSpec.makeMeasureSpec(v.getLayoutParams().width, View.MeasureSpec.EXACTLY);
    int measuredHeight = View.MeasureSpec.makeMeasureSpec(v.getLayoutParams().height, View.MeasureSpec.EXACTLY);
    v.measure(measuredWidth, measuredHeight);
    v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
    v.buildDrawingCache();
    Bitmap bitmap = v.getDrawingCache();
    return bitmap;
}

/**
 * 加载的xml是ScrollView
 *
 * @param bgResId scrollView的背景
 * @return
 */
public static Bitmap loadBitmapScrollView(View v, ScrollView scrollView,int bgResId) {
    int measuredWidth = View.MeasureSpec.makeMeasureSpec(v.getLayoutParams().width, View.MeasureSpec.UNSPECIFIED);
    int measuredHeight = View.MeasureSpec.makeMeasureSpec(v.getLayoutParams().height, View.MeasureSpec.UNSPECIFIED);
    v.measure(measuredWidth, measuredHeight);
    v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());

    int h = 0;
    Bitmap bitmap = null;
    for (int i = 0; i < scrollView.getChildCount(); i++) {
        h += scrollView.getChildAt(i).getHeight();
        scrollView.getChildAt(i).setBackgroundResource(bgResId);
    }
    if(h <= 0){
        return null;
    }
    bitmap = Bitmap.createBitmap(scrollView.getWidth(), h, Bitmap.Config.ARGB_8888);
    final Canvas canvas = new Canvas(bitmap);
    scrollView.draw(canvas);
    return bitmap;
}

补充
1:背景透明(不黑色)
存图片的格式 = png。(jpg会丢弃背景透明的属性);
Bitmap的Config = ARGB_8888(别的会丢失透明度信息,如RGB_565)