Search code examples
androidviewredraw

How to force a view to redraw immediately before saving it as an image


I have a custom TextView that I am treating like an EditText view. The user presses a Share button and the layout containing the TextView is saved as a PNG image and shared to social networks.

My problem is that the TextView has a cursor character in it. Before I create the image I want to remove the cursor character. However, if I remove the character in the same method that I create and share the image, the app crashes because it didn't get a chance to redraw the view first.

My question is basically the same as How to force a view to redraw immediately before the next line of code is executed, but unlike this question I don't need to change background resources.

I tried calling invalidate(), but that doesn't solve the problem because the UI never gets a chance to redraw before I need the view.

What should I do?

Here is my code:

public void shareToOtherApps(View v) {

    RelativeLayout messageOutline = (RelativeLayout) findViewById(R.id.rlMessageOutline);

    // Remove cursor from display (inputWindow is a TextView)
    inputWindow.setText(converter
            .unicodeToFontReadable(unicodeText.toString()));
    inputWindow.invalidate(); // This line makes no difference

    // Code to save image
    messageOutline.setDrawingCacheEnabled(true);
    Bitmap bitmap = messageOutline.getDrawingCache(true);
    ...

    // Code to share image
    ...

    // Add cursor back to display
    updateDisplay();
}

Solution

  • I solved the problem but putting the code to save/share the image inside of a runnable and running it after removing the cursor character. This puts the runnable code at the end of the message stack and allows the UI to update its view before trying to save an image of the view.

    Here is the code summary:

    public void shareToOtherApps(View v) {
    
        // Remove cursor from display (inputWindow is a TextView)
        inputWindow.setText(converter.unicodeToFontReadable(unicodeText.toString()));
    
        // Put this in a runnable to allow UI to update itself first
        inputWindow.post(new Runnable() {
            @Override
            public void run() {
    
                // Code to save image
                RelativeLayout messageOutline = (RelativeLayout) findViewById(R.id.rlMessageOutline);
                messageOutline.setDrawingCacheEnabled(true);
                Bitmap bitmap = messageOutline.getDrawingCache(true);
    
                // Code to share image
                ...
    
                // Add cursor back to display
                updateDisplay();
            }
        });
    
    }