我的方法如下:
我有三个TextViews
(嵌套在LinearLayout
中)我希望它们具有偏斜效果,因此它看起来像是在墙上(见下图)。由于用户可以更改背景(不同的墙),我使用DrawingCache
中的LinearLayout
,使其倾斜,最后将其渲染在背景图像上方的透明图像中。< / p>
为了确保文本位于每个设备的正确位置,我想出了一个具有背景图像(720x1022)的解决方案,并将文本渲染为透明图像并将其放置在图形中的右侧坐标处。相同的尺寸(720x1022)。在应用程序中,图片按比例缩放和放置。也许这不是最好的主意,因为有时候(让我们说10次中有1次)我遇到了OutOfMemory错误。
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)
并且堆突然增长。
Grow heap (frag case) to 73.520MB for 11773456-byte allocation
它不会每次都崩溃(让我们说10分中的1分),而不是在同一个位置。这是我的实施:
首先,我们从TextViews获取用户输入,这些输入嵌套在LinearLayout中并将其缩放到特定的高度和宽度(#2)以执行偏斜矩阵(#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);
我发现这篇文章非常好:Strange out of memory issue while loading an image to a Bitmap object但它仍然无法解决我的问题。我想我还有太多createBitmaps
。也许有更好的方法来做到这一点,所以我很高兴看到每一个建议!
答案 0 :(得分:1)
我们针对此案例的最终解决方案是使用AsyncTask
来呈现Image
。我们传递了LinearLayout
的引用,其中包含TextViews
(这是我们正在渲染的内容),ImageView
的引用,我们插入渲染的图片和{{1}的引用在渲染图像后隐藏它
ProgressBar
答案 1 :(得分:0)
我在您发布的de code snippet中看到至少4个Bitmap
s。请务必阅读this android developer training link或on this stackoverflow question处的正确位图回收。
添加recycle()
次调用时,请确保不显示已回收的位图,否则会出现其他错误。在分配新的位图信息之前,请执行视图的循环(如果不是null
)和onDestroy
(或onPause
,如果您足够小心重新创建位图onResume
)< / p>
一个简单的例子:
// you see how I moved this up to class scope instead?
private Bitmap mScaledBitmap = null;
void someMethod(){
// some code here
// ...
if(mScaledBitmap != null)
mScaledBitmap.recycle();
mScaledBitmap = Bitmap.createScaledBitmap(mOfferText, 560, 720, false);
// more code here
// ...
}
public void onDestroy(){
// always call super
super.onDestroy();
// free memory from bitmap here
if( mScaledBitmap != null ) {
mScaledBitmap.recycle();
mScaledBitmap = null;
}
}
如果即使进行了适当的回收,此代码仍会提供内存不足的例外情况,您可以尝试使用sampleSize选项。确保使用2的幂。
另一个简单的例子:
Options opts = new Options();
opts.inSampleSize = 4;
// insert recycle here with proper checks
mScaledBitmap = BitmapFactory.decodeFile(imagePath, opts);