0

私のアプローチは次のとおりです。

私は 3 つTextViews( にネストされていLinearLayoutます) を持っており、それらが壁にあるように見えるように、それらにゆがみ効果を持たせたいと考えています (下の画像を参照)。ユーザーは背景 (別の壁) を変更できるため、DrawingCacheからを使用しLinearLayout、それをゆがめ、最終的に背景画像の上に配置される透明な画像でレンダリングします。

ここに画像の説明を入力

テキストがすべてのデバイスで適切な位置にあることを確認するために、背景画像 (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 としましょう)、同じ位置でもクラッシュしません。これが私の実装です:

最初に、LinearLayout にネストされている TextViews からユーザー入力を取得し、それを特定の高さと幅にスケーリングして (#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);

私はこの非常に良い記事を見つけました:ビットマップオブジェクトに画像をロードしているときにメモリ不足の問題が発生しましたが、それでも私の問題は解決しません。私はまだ多すぎると思いcreateBitmapsます。これを行うためのより良い方法があるかもしれないので、すべての提案に満足しています!

4

2 に答える 2

1

この場合の最終的な解決策は、AsyncTaskをレンダリングするために を使用することでしたImage。をLinearLayout含むへの参照TextViews(これがレンダリングするものです)、ImageViewレンダリングされた画像を挿入する場所への参照、およびProgressBarImage がレンダリングされた後に非表示になる 参照を渡します。

public class RenderBitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {
  private final WeakReference<ImageView> imageViewReference;
  private final LinearLayout signViewReference;
  private final ProgressBar progressBar;

  public RenderBitmapWorkerTask(ImageView imageView, LinearLayout signView, ProgressBar mProgressBar) {
      // Use a WeakReference to ensure the ImageView can be garbage collected
      imageViewReference = new WeakReference<ImageView>(imageView);
      signViewReference = signView;
      progressBar = mProgressBar;
  }

  // Decode image in background.
  @Override
  protected Bitmap doInBackground(Integer... params) {
    signViewReference.setDrawingCacheEnabled(true);

    Bitmap mOfferText = signViewReference.getDrawingCache();

    int mTextViewWidth = 560;
        int mTextViewHeight = 720;

        mOfferText = Bitmap.createScaledBitmap(mOfferText, mTextViewWidth, mTextViewHeight, false);

        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);
        mOfferText = Bitmap.createBitmap(mOfferText, 0, 0, mTextViewWidth, mTextViewHeight, mMatrix2, false);

      return mOfferText;
  }

  // Once complete, see if ImageView is still around and set bitmap.
  @Override
  protected void onPostExecute(Bitmap bitmap) {
      if (imageViewReference != null && bitmap != null) {
          final ImageView imageView = imageViewReference.get();
          if (imageView != null) {

                progressBar.setVisibility(View.GONE);

              imageView.setImageBitmap(bitmap);
          }
      }
  }
}
于 2013-07-03T21:15:10.257 に答える