I want to convert a RelativeLaout view into a Bitmap. I've tried another answers and different options without success.
My XML View is kind of:
----RelativeLayout
-------ImageView
-------TextView
Every ones have wrap_content measures.
As i need several bitmaps of the view, im inflating it this way:
LayoutInflater inflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(R.layout.localviewlayout, null);
ImageView img = (ImageView) v.findViewById(R.id.imgPlace);
img.setImageBitmap(MyDynamicBitmap);
TextView txt1 = (TextView)v.findViewById(R.id.text1);
txt1.setText(MyDynamicText);
return v;
After that :
//in measure() i get a nullpointerException on RelativeLayout.onMeasure().I also have tried //with MeasureSpec.EXACTLY
v.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
Bitmap b = Bitmap.createBitmap( v.getWidth(), v.getHeight(), Bitmap.Config.ARGB_8888);
v.draw(new Canvas(b));
Paint p = new Paint();
myMainCanvas.drawBitmap(b, myPointX, myPointY, p);
The content of textView of the RelativeLayout is dynamic, so i cant know the width or height of the text.
Besides of the exception, if i manually set enough size on the measure function (insted of 0), my dynamic text doesnt display entirely.
I hope you can help me because right now, im stuck. Thank youuu
Try adding
v.setLayoutParams(new LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
before calling measure(). Does that fix the NullPointerException?
Related
I am facing a situation in which I need to draw bitmap for a given text. I tried to render a TextView with required properties and then draw its bitmap using canvas. My try looks like this:
TextView nameTv = new TextView(context);
Bitmap bmp = Bitmap.createBitmap(200, 200, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bmp);
nameTv.layout(0, 0, 200, 200);
nameTv.setGravity(Gravity.CENTER);
nameTv.setText("Test");
nameTv.setBackgroundColor(Color.RED);
nameTv.draw(canvas);
The problem with this code is that the text on TextView not center aligned, which I require.
Any suggestions are welcomed :)
Thanks,
Ammar
I think the problem is in measuring. You not calling measure for that and it don't have properly size. Call nameTv.measure() before layout().
Call measure like this:
int measureSpecWidth = MeasureSpec.makeMeasureSpec(200, MeasureSpec.EXACTLY);
int measureSpecHeight = MeasureSpec.makeMeasureSpec(200, MeasureSpec.EXACTLY);
nameTv.measure(measureSpecWidth, measureSpecHeight);
my problem is similar to How to get all children (visible and invisible) from a ListView?
i need to save all listview items to bitmap, listview item is inflated by textview. whatever they are visible or invisible in the lisview.
i want to get all child views and convert to bitmap, i tried as below:
view = adapter.getView(i,null,lv);
view.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
Bitmap bitmap = Bitmap.createBitmap(view.getMeasuredWidth()
view.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
bitmap.eraseColor(Color.WHITE);
Canvas canvas = new Canvas(bitmap);
canvas.translate(10, 10);
view.draw(canvas);
mybitmap = combineImages(mybitmap, bitmap);
but if item text is too much (some of them contain long text) the methods ,view.getMeasuredWidth() and view.getMeasuredHeight(), which are not working properly.
I`m wondering if my idea to this problem is right , if not , how can I solve it ?
Used the following to fix:
view.measure(MeasureSpec.makeMeasureSpec(lv.getWidth(),
MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(0,
MeasureSpec.UNSPECIFIED));
I'm developing a sphere which should show text at certain positions. I tried it with CBFG and it's API, but I just counld saw a text at a fixed position on the screen. But I need to have a dynamic text which I can move around with a onTouchListener. With my Sphere it works fine, also with a Bitmap on it, but how can i make it with the text?
I solved my problem:
TextView textV = new TextView(context);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(128, 128);
textV.setLayoutParams(layoutParams);
textV.setTextColor(Color.WHITE);
textV.setBackgroundColor(Color.TRANSPARENT);
textV.setGravity(Gravity.CENTER);
textV.setText(text);
textV.setDrawingCacheEnabled(true);
Bitmap b = Bitmap.createBitmap( textV.getLayoutParams().width, textV.getLayoutParams().height, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
textV.layout(0, 0, textV.getLayoutParams().width, textV.getLayoutParams().height);
textV.draw(c);
textV.setDrawingCacheEnabled(false);
With that code I'll get a Bitmap which I can use as a texture ;-)
I have been trying to create a bit map of a list view, where the entire list view is not visible on the screen. I am using
Bitmap mBitmap = fullView.getDrawingCache();
to create bitmap. It works ok for the part of list view that is visible on the screen but, not for the part that isn't.I would like to know if a bitmap of a list view can be created without having to display it completely on the screen. All suggestions and or solutions are appreciated.
As android only draws what is visible, may idea would be to take bitmaps in pieces and then group the bitmaps into a single one. You could first get the bitmap of first n items. Then use the scrollTo method to scroll beyond the previous n items and get the bitmap for the next n items. This way you can get bitmap of the whole list view.
Try using this method. Hack here is calling the layout and measure method of the view yourself.
public Bitmap loadBitmapFromView(View v) {
v.setLayoutParams(new ViewGroup.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT));
v.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
Bitmap bitmap = Bitmap.createBitmap(v.getMeasuredWidth(),
v.getMeasuredHeight(),
Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(bitmap);
v.layout(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
v.draw(c);
return bitmap;
}
Pass the view in this method like
LayoutInflater inflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View inflatedFrame = inflater.inflate(R.layout.my_view, null);
Bitmap bitmap = loadBitmapFromView(inflatedFrame.findViewById(R.id.id_of_your_view_in_layout));
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
The problem is that you did not measure and layout the container. You must call v.measure(widthSpec, heightSpec) and then v.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:
v.measure(MeasureSpec.makeMeasureSpec(v.getLayoutParams().width, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(v.getLayoutParams().height, MeasureSpec.EXACTLY));
v.layout(0, 0, v.getMeasuredWidth(), v.getMeasuredHeight());
Bitmap b = Bitmap.createBitmap(v.getWidth(), v.getHeight(), Bitmap.Config.RGB_565);
Canvas c = new Canvas(b);
v.draw(c);
Solution that based on DisplayMetrics for the Layouts could be useful as well. In order not to repeat - look here .