将layout转为bitmap绘制的步骤:
方法一:不将bitmap放入内存缓存当中
1、调用measure方法、设置视图的大小,应传入父级的layout的宽高(int类型)
2、传入measure的属性,可以通过以下方法进行设置并传入:View.MeasureSpec.makeMeasuereSpec(int width, int model),其中width为view的大小,
model有三种,详细见MeasureSpec的model详解
3、设置view的布局尺寸和位置,调用view.layout(int, int, int, int)方法,例如view.layout(0,0,view.getMeasureWidth(),view.getMeasureHeight())表示在左上角开始,右下角结束点为view的长度和宽度
4、构建bitmap,调用Bitmap.createBitmap(view.getWidth(), view.getHeight())生成bitmap
5、利用bitmap生成画布
6、将view的内容绘制在画布上,即可完成
方法二:将bitmap放入内存缓存当中
1、调用view.setDrawingCacheEnabled(true);将draw设置为可缓存
2、调用measure方法、设置视图的大小,应传入父级的layout的宽高(int类型)
3、传入measure的属性,可以通过以下方法进行设置并传入:View.MeasureSpec.makeMeasuereSpec(int width, int model),其中width为view的大小,根据需要进行设置;
model有三种,详细见MeasureSpec的model详解
4、设置view的布局尺寸和位置,调用view.layout(int, int, int, int)方法,例如view.layout(0,0,view.getMeasureWidth(),view.getMeasureHeight())表示在左上角开始,右下角结束点为view的长度和宽度
5、构建bitmap,调用Bitmap.createBitmap(view.getWidth(), view.getHeight())生成bitmap
6、调用view.buildDrawingCache();将view写入内存缓存当中
7、利用Bitmap bitmap = view.getDrawingCache()获取内存当中view缓存
8、将view的内容绘制在画布上,即可完成
@Override
public View getView(int position, View convertView, ViewGroup parent) {
/** 此处省略代码 */
// 方法一
// // 如果没有调用这个方法,得到的bitmap为null
// convertView.measure(View.MeasureSpec.makeMeasureSpec(256, View.MeasureSpec.EXACTLY),
// View.MeasureSpec.makeMeasureSpec(256, View.MeasureSpec.EXACTLY));
// // 设置布局的尺寸和位置
// convertView.layout(0, 0, convertView.getMeasuredWidth(), convertView.getMeasuredHeight());
// // 生成bitmap
// Bitmap bitmap = Bitmap.createBitmap(convertView.getWidth(), convertView.getHeight(),
// Bitmap.Config.RGB_565);
// // 利用bitmap生成画布
// Canvas canvas = new Canvas(bitmap);
// // 把view中的内容绘制在画布上
// convertView.draw(canvas);
// 方法二
// 调用该方法你应该避免启用硬件加速时调用该方法,如果你不需要绘制位图缓存,调用该方法会增加内存使用和导致软件视图呈现一次,因此负面影响性能
// 获取屏幕宽度大小、设置bitmap的宽度
WindowManager windowManager = ((Activity) mContext).getWindowManager();
Display display = windowManager.getDefaultDisplay();
// 以下方法将bitmap加入缓存当中
convertView.setDrawingCacheEnabled(true);
// 如果没有调用这个方法,得到的bitmap为null
// 高度最好选用UNSPECTIFIED模式、这样才会使得每个item的高度能自适应
convertView.measure(View.MeasureSpec.makeMeasureSpec(display.getWidth(), View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(256, View.MeasureSpec.UNSPECIFIED)); // 关于MeasureSpec.EXACTLY的说明和理解,见以下
// 设置布局的尺寸和位置
convertView.layout(0, 0, convertView.getMeasuredWidth(), convertView.getMeasuredHeight());
// 获得绘图缓存中的Bitmap
convertView.buildDrawingCache();
Bitmap bitmap = convertView.getDrawingCache();
converView.draw(bitmap);
/** 此处省略其他代码 */
return converView;
}
以下是Android官方文档的解释/** * A MeasureSpec encapsulates the layout requirements passed from parent to child. * Each MeasureSpec represents a requirement for either the width or the height. * A MeasureSpec is comprised of a size and a mode. There are three possible * modes: * <dl> * <dt>UNSPECIFIED</dt> * <dd> * The parent has not imposed any constraint on the child. It can be whatever size * it wants. * </dd> * * <dt>EXACTLY</dt> * <dd> * The parent has determined an exact size for the child. The child is going to be * given those bounds regardless of how big it wants to be. * </dd> * * <dt>AT_MOST</dt> * <dd> * The child can be as large as it wants up to the specified size. * </dd> * </dl> * * MeasureSpecs are implemented as ints to reduce object allocation. This class * is provided to pack and unpack the <size, mode> tuple into the int. */UNSPECIFIED:如果你的layout的xml文件中含有隐藏的控件,则改model可以动态根据你的view来获取width和height,不会将隐藏的控件高度计算进来
EXACTLY:完全按照你的layout的xml文件的宽高设置,如果含有隐藏的控件,也会将隐藏的控件宽高度计算进来
AT_MOST:最大按照你设置的宽高度,例如View.MeasureSpec.makeMeasureSpec(256, View.MeasureSpec.AT_MOST),则不管你的view有多大,最大只能为256