Android 将带有子项的 ViewGroup 转换为位图时出现问题
我成功使用 Canvas 将 ViewGroup (RelativeLayout) 转换为位图。但是,当绘制发生时,我只能看到 ViewGroup 及其背景可绘制对象,而不是其子视图(两个 TextView),这些子视图应该使用 FILL_PARENT 等规则在relativelayout 中布局。
使用以下静态函数创建relativelayout:
public static RelativeLayout createProgrammeView(Context context, int width, int height, String title, String time) {
RelativeLayout.LayoutParams params;
// Layout Root View (RelativeLayout)
RelativeLayout rlv = new RelativeLayout(context);
params = new RelativeLayout.LayoutParams(width, height);
rlv.setLayoutParams(params);
rlv.setPadding(3, 3, 3, 3);
rlv.setBackgroundResource(R.drawable.background);
// Layout Title
TextView tv = new TextView(context);
params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.FILL_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
params.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
tv.setId(R.id.title);
tv.setLayoutParams(params);
tv.setGravity(Gravity.CENTER_VERTICAL);
tv.setSingleLine(true);
tv.setEllipsize(TruncateAt.END);
tv.setTextColor(Color.parseColor("#fff"));
tv.setTextSize(11);
tv.setText(title);
rlv.addView(tv);
// Layout Start Time
tv = new TextView(context);
params = new RelativeLayout.LayoutParams(16, RelativeLayout.LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.BELOW, R.id.title);
params.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
params.setMargins(0, 4, 0, 0);
tv.setId(R.id.time);
tv.setLayoutParams(params);
tv.setGravity(Gravity.CENTER_VERTICAL);
tv.setSingleLine(true);
tv.setEllipsize(null);
tv.setTextColor(Color.parseColor("#fff"));
tv.setTextSize(10);
tv.setText(time);
rlv.addView(tv);
}
return rlv;
}
然后我使用以下命令将relativelayout转换为位图:
public static Bitmap loadBitmapFromView(RelativeLayout v) {
Bitmap b = Bitmap.createBitmap(v.getLayoutParams().width, v.getLayoutParams().height, Bitmap.Config.RGB_565);
Canvas c = new Canvas(b);
v.draw(c);
return b;
}
正如预期的那样,这为我提供了一个漂亮的位图,其尺寸符合背景可绘制的要求,但子级不在位图中。我经常调用这些函数来构建一个大图像,然后将其绘制到我的活动中的自定义视图上。
这是调用静态函数的循环:
public static void renderViews(final Context context) {
largeBitmap = Bitmap.createBitmap(largeWidth, largeHeight, Bitmap.Config.RGB_565);
Canvas largeCanvas = new Canvas(largeBitmap);
for (int i = 0; i < items.size(); i++) {
int leftMargin = ...SOME CALCULATIONS...;
RelativeLayout newView = createProgrammeView(context, width, rowHeight, "Title", "21:00");
Bitmap newViewBitmap = loadBitmapFromView(newView);
largeCanvas.drawBitmap(newViewBitmap, leftMargin, 0, new Paint());
}
myCustomView.invalidate();
}
我的自定义视图覆盖了 onDraw() 函数:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(largeBitmap, 0, 0, null);
}
从我所看到的情况来看,我相信这是因为 Android 不会在子视图上调用measure()。我尝试过手动调用它,但这并不能解决问题。
所以,我想我想知道的是,如何实现将带有子项的relativelayout转换为位图,并让Android测量子项,以便它们尊重其相对布局规则。
非常感谢任何可以帮助我解决这个问题的人。
抢
I'm successfully converting a ViewGroup (RelativeLayout) into Bitmap using a Canvas. However, when the draw happens I only see the ViewGroup with its background drawable and not its children (two TextViews) who should be laid out within the RelativeLayout using rules like FILL_PARENT.
The RelativeLayout is created using the following static function:
public static RelativeLayout createProgrammeView(Context context, int width, int height, String title, String time) {
RelativeLayout.LayoutParams params;
// Layout Root View (RelativeLayout)
RelativeLayout rlv = new RelativeLayout(context);
params = new RelativeLayout.LayoutParams(width, height);
rlv.setLayoutParams(params);
rlv.setPadding(3, 3, 3, 3);
rlv.setBackgroundResource(R.drawable.background);
// Layout Title
TextView tv = new TextView(context);
params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.FILL_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
params.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
tv.setId(R.id.title);
tv.setLayoutParams(params);
tv.setGravity(Gravity.CENTER_VERTICAL);
tv.setSingleLine(true);
tv.setEllipsize(TruncateAt.END);
tv.setTextColor(Color.parseColor("#fff"));
tv.setTextSize(11);
tv.setText(title);
rlv.addView(tv);
// Layout Start Time
tv = new TextView(context);
params = new RelativeLayout.LayoutParams(16, RelativeLayout.LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.BELOW, R.id.title);
params.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
params.setMargins(0, 4, 0, 0);
tv.setId(R.id.time);
tv.setLayoutParams(params);
tv.setGravity(Gravity.CENTER_VERTICAL);
tv.setSingleLine(true);
tv.setEllipsize(null);
tv.setTextColor(Color.parseColor("#fff"));
tv.setTextSize(10);
tv.setText(time);
rlv.addView(tv);
}
return rlv;
}
I then use the following to turn the RelativeLayout into a Bitmap:
public static Bitmap loadBitmapFromView(RelativeLayout v) {
Bitmap b = Bitmap.createBitmap(v.getLayoutParams().width, v.getLayoutParams().height, Bitmap.Config.RGB_565);
Canvas c = new Canvas(b);
v.draw(c);
return b;
}
As expected this gives me a nice Bitmap in the dimensions that I require with the background drawable, but the children are not in the bitmap. I call these functions quite a lot to build a large image which then gets drawn onto a custom view in my activity.
This is the loop which calls the static function:
public static void renderViews(final Context context) {
largeBitmap = Bitmap.createBitmap(largeWidth, largeHeight, Bitmap.Config.RGB_565);
Canvas largeCanvas = new Canvas(largeBitmap);
for (int i = 0; i < items.size(); i++) {
int leftMargin = ...SOME CALCULATIONS...;
RelativeLayout newView = createProgrammeView(context, width, rowHeight, "Title", "21:00");
Bitmap newViewBitmap = loadBitmapFromView(newView);
largeCanvas.drawBitmap(newViewBitmap, leftMargin, 0, new Paint());
}
myCustomView.invalidate();
}
My custom view overrides the onDraw() function:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(largeBitmap, 0, 0, null);
}
From what I can see I believe this is because Android doesn't call a measure() on the child Views. I have tried calling this manually, but this doesn't solve the problem.
So, I guess what I would like to know is, how can I achieve converting a RelativeLayout with children into a Bitmap and get Android to measure the children so they respect their relative layout rules.
Many thanks to anyone who can help me work this out.
Rob
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
问题是您没有测量和布局容器。您必须调用
v.measure(widthSpec, heightSpec)
,然后调用v.layout(left, top ,右,下)
之前绘图可以工作。第一种方法将确保视图知道您想要它有多大,第二种方法将确保子级的位置正确。在你的情况下你会这样做:
The problem is that you did not measure and layout the container. You must call
v.measure(widthSpec, heightSpec)
and thenv.layout(left, top, right, bottom)
before drawing can work. The first method will make sure the view knows how big you want it to be, and the second method will ensure the children are positioned properly.In your case you would do:
基于
DisplayMetrics
的布局解决方案也可能很有用。为了不重复 - 看这里。Solution that based on
DisplayMetrics
for the Layouts could be useful as well. In order not to repeat - look here .