My approach is the following:
I have three TextViews
(nested in a LinearLayout
) and I want them to have a skewing effect, so that it looks like they are at a wall (look at the image below). Since the user can change the background (different wall), I am using the DrawingCache
from the LinearLayout
, skew it, and finally render it in a transparent image which is placed above the background image..
To ensure that the text is at the right position at every device, I came up with the solution to have a background image (720x1022) and render the text to a transparent image and place it at the right coordinates in a graphic with the same size (720x1022). In the app, pictures are scaled and placed the same way. Maybe it's not the best idea, because sometimes (let's say 1 time out of 10) I am running into an OutOfMemory Error.
java.lang.OutOfMemoryError
at android.graphics.Bitmap.nativeCreate(Native Method)
at android.graphics.Bitmap.createBitmap(Bitmap.java:689)
at android.graphics.Bitmap.createBitmap(Bitmap.java:666)
at android.graphics.Bitmap.createBitmap(Bitmap.java:633)
//or
java.lang.OutOfMemoryError
at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:502)
at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:355)
at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:785)
at android.content.res.Resources.loadDrawable(Resources.java:1965)
at android.content.res.TypedArray.getDrawable(TypedArray.java:601)
and the heap is growing suddenly.
Grow heap (frag case) to 73.520MB for 11773456-byte allocation
It doesn't crash every time (let's say 1 out of 10), and not at the same position. Here's my implementation:
First, we get the user input from the TextViews which are nested in a LinearLayout and scale it to a specific height and width (#2) to perform the skewing matrix (#3).
//#1 get Text from TextViews
View test = findViewById(R.id.signFakeContainer);
test.setDrawingCacheEnabled(true);
Bitmap mOfferText = test.getDrawingCache();
//#2 scale Text to specific width & height to perform skew effect
Bitmap mScaledBitmap = Bitmap.createScaledBitmap(mOfferText, 560, 720, false);
int mTextViewWidth = mScaledBitmap.getWidth();
int mTextViewHeight = mScaledBitmap.getHeight();
//#3 create skewing matrix
Matrix mMatrix2 = new Matrix();
float[] mStartSrc = new float[] { 0, 0, mTextViewWidth, 0, mTextViewWidth, mTextViewHeight, 0, mTextViewHeight };
float[] mDestSrc = new float[] { 0, 4f, 520f, 0f, 552f, 704f, 22f, 720f };
mMatrix2.setPolyToPoly(mStartSrc, 0, mDestSrc, 0, 4);
//#4 perform skewing
Bitmap mStrechtedTextView = Bitmap.createBitmap(mScaledBitmap, 0, 0, mTextViewWidth, mTextViewHeight, mMatrix2, false);
//#5 place 560x720 image in 720x1022 image at specific coordinates, to ensure its right position
Bitmap bmp = Bitmap.createScaledBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.transparent_dummy), 720, 1022, false);
Canvas comboImage = new Canvas(bmp);
comboImage.drawBitmap(mStrechtedTextView, 98, 110, null);
//#6 set rendered textview to image
ImageView mOfferImageView = (ImageView) findViewById(R.id.choose_sign_offer_image);
mOfferImageView.setImageBitmap(bmp);
I found this really good article: Strange out of memory issue while loading an image to a Bitmap object but still it doesn't solve my issue. I guess I still have too many createBitmaps
. Maybe there's a better way to do this, so I'm happy for every suggestion!