tddian
tddian

Reputation: 43

TextView can't draw on Canvas correctly after calling setText() and invalidate()

My purpose is to make an Bitmap image which shows user supplied text, and the image can later be saved into cache.

After calling TextView.setText() and TextView.invalidate(), the TextView is not being updated as I expected. It still draws previous texts on Canvas.

@Override
public void onClick(View v) {
    // tv is a TextView and et is an EditText.
    tv.setText(et.getText().toString());
    tv.invalidate();
    // if measure() isn't called, getMeasuredWidth() returns previous value.tv.measure(0, 0);

    int screenWidth = (int) tv.getMeasuredWidth();
    int screenHeight = (int) tv.getMeasuredHeight();

    if (screenHeight * screenWidth != 0) {
        LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
                                                    screenWidth, screenHeight);
        Bitmap testB;

        testB = Bitmap.createBitmap(screenWidth, screenHeight, Bitmap.Config.ARGB_8888);
        Canvas c = new Canvas(testB);

        tv.draw(c);
        // tv draws previous String on Canvas c.

        iv = (ImageView) findViewById(R.id.image);
        iv.setLayoutParams(layoutParams);
        iv.setBackgroundColor(Color.RED);
        iv.setImageBitmap(testB);
    }
}

The document says

public void invalidate ()

Invalidate the whole view. If the view is visible, onDraw(android.graphics.Canvas) will be called at some point in the future. This must be called from a UI thread. To call from a non-UI thread, call postInvalidate().

Does it mean I should override the onDraw() method?

Upvotes: 1

Views: 1878

Answers (3)

tddian
tddian

Reputation: 43

I found the solution... (may be a solution)

It is needed to add this line before calling draw():

tv.layout(0, 0, screenWidth, screenHeight);

I think the width and height aren't updated yet, because getWidth() returns previous value.

Upvotes: 1

Caner
Caner

Reputation: 59168

I think it should be updated, you don't even need to call invalidate(). Maybe there is a problem in some other place in your code. Your onClick function seems right to me.

Upvotes: 0

Daud Arfin
Daud Arfin

Reputation: 2499

Invalidate means its a just refresh kind of thing. Once you try with gone and bring to front it should work. E.g :

// Try this ...
tv.setVisibility(View.GONE);
tv.bringToFront();
tv.setVisibility(View.VISIBLE);

Upvotes: 0

Related Questions