0

I am able to convert a Layout with a TextView into a Bitmap, as long as the event that happens after onCreate(). But when I try during on create, it does not work.

Is there a way to get this to work? I have tried using inflate() in various ways with no joy.

There are various answered questions including this one that address the technique that I'm successfully using in my code. But the success does not include employing the technique from onCreate().

Bitmap null during onCreate() but works later

public class MainActivity extends AppCompatActivity {
    private static final String TAG = MainActivity.class.getSimpleName();

    private RelativeLayout mTextLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // This is what I would like to work
        replaceTheRobot(); // Fails.  Bitmap is null.
    }

    public void onClickGetBitmap(View view) {
        replaceTheRobot(); // Works.  Bitmap replaces the robot.
    }

    private void replaceTheRobot() {
        mTextLayout = (RelativeLayout) findViewById(sampleRelativeLayout);
        mTextLayout.setDrawingCacheEnabled(true);
        Bitmap bitmap = mTextLayout.getDrawingCache();
        if (bitmap == null) {
            Toast.makeText(getApplicationContext(), "The bitmap was null", Toast.LENGTH_LONG).show();
            Log.v(TAG, "The bitmap was null");
        }
        else {
            Toast.makeText(getApplicationContext(), "The bitmap size: " + bitmap.getWidth() +", " + bitmap.getHeight(), Toast.LENGTH_LONG).show();
            ImageView imageViewRobot = (ImageView) findViewById(R.id.imageViewRobot);
            imageViewRobot.setImageDrawable(new BitmapDrawable(this.getResources(), bitmap));
        }
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity">

    <RelativeLayout
        android:id="@+id/sampleRelativeLayout"
        android:layout_width="50dp"
        android:layout_height="50dp">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello World!"
            android:id="@+id/helloTextView" />
    </RelativeLayout>

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:srcCompat="@mipmap/ic_launcher"
        android:id="@+id/imageViewRobot"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true" />

    <Button
        android:text="Get Bitmap"
        android:onClick="onClickGetBitmap"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:id="@+id/button" />
</RelativeLayout>
Community
  • 1
  • 1
Dale
  • 5,520
  • 4
  • 43
  • 79

2 Answers2

1

View is not rendered yet. You can use view.getViewTreeObserver().addOnGlobalLayoutListener to get notified when your layout is ready.

So, something like this:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    final ViewTreeObserver viewTreeObserver = findViewById(sampleRelativeLayout).getViewTreeObserver();
    viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
        viewTreeObserver.removeOnGlobalLayoutListener(this);
        replaceTheRobot();
        }
    });
}
egoldx
  • 1,490
  • 1
  • 9
  • 14
  • your solution put me on the right track and I was able to enhance the solution to prevent `IllegalStateException` and allow it to work on older Android versions. Since my edits were rejected, I created another answer which I will remove if you make those additions. – Dale Mar 28 '17 at 16:23
0

Building upon the user1779222 answer, if you wish to manage earlier Android releases, you can test run the very similarly named removeGlobalOnLayoutListener instead of removeOnGlobalLayoutListener. Also, to avoid the error java.lang.IllegalStateException: This ViewTreeObserver is not alive, call getViewTreeObserver() again, you can get the observer again instead of using the original observer. With those changes, the result would be as follows:

    final ViewTreeObserver viewTreeObserver = findViewById(sampleRelativeLayout).getViewTreeObserver();
    viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
                findViewById(sampleRelativeLayout).getViewTreeObserver().removeGlobalOnLayoutListener(this);
            } else {
                findViewById(sampleRelativeLayout).getViewTreeObserver().removeOnGlobalLayoutListener(this);
            }
            replaceTheRobot();
        }
    });
Dale
  • 5,520
  • 4
  • 43
  • 79