Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android WebView flicker bug while animating view on device

I am attempting to implement slide-in navigation (a la Facebook, Path, or Google+ Android apps). The complete source to reproduce this bug can be found here.

When animating a WebView off the screen however, on a device, flickering occurs, as if the device is taking a bite out of my WebView just before pushing it off the screen.

WebView slide nav menu IN (device)

The artifact does not occur on the emulator! The animation proceeds smoothly.

WebView slide nav menu IN (emulator)

Interestingly, this flickering seems to only occur when the view being animated is a WebView! Here is the same project using a TextView as the main content view.

TextView slide nav menu IN (device)

Layout for the web view activity:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/blue" >

    <WebView
        android:id="@+id/web_content"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true" />

</RelativeLayout>

And for the text view activity:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/blue" >

    <TextView
        android:id="@+id/web_content"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello there. no flicker!"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
         />

</RelativeLayout>

Code called to slide the navigation menu in:

 private void slideIn() {
        LinearLayout actionBarFrame = (LinearLayout) findViewById(android.R.id.content).getParent();

        LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
        menuView = inflater.inflate(R.layout.menu, null);
        menuView.setLayoutParams(new FrameLayout.LayoutParams(SIZE, LayoutParams.MATCH_PARENT, Gravity.LEFT));
        FrameLayout decorView = (FrameLayout) getWindow().getDecorView();
        decorView.addView(menuView);
        decorView.bringChildToFront(actionBarFrame);

        FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) actionBarFrame.getLayoutParams();
        params.setMargins(SIZE, 0, -SIZE, 0);
        actionBarFrame.setLayoutParams(params);

        TranslateAnimation ta = new TranslateAnimation(-SIZE, 0, 0, 0);
        ta.setDuration(DURATION); 
        actionBarFrame.startAnimation(ta);
    }

And to slide it back out:

    private void slideOut() {
        LinearLayout actionBarFrame = (LinearLayout) findViewById(android.R.id.content).getParent();

        FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) actionBarFrame.getLayoutParams();
        params.setMargins(0, 0, 0, 0);
        actionBarFrame.setLayoutParams(params);

        TranslateAnimation ta = new TranslateAnimation(SIZE, 0, 0, 0);
        ta.setDuration(DURATION);
        ta.setAnimationListener(new  AnimationListener() {
            @Override 
            public void onAnimationEnd(Animation arg0) {
                ((FrameLayout) getWindow().getDecorView()).removeView(menuView);
                menuView = null;
            }
            @Override public void onAnimationRepeat(Animation arg0) { }
            @Override public void onAnimationStart(Animation arg0) { }
        });
        actionBarFrame.startAnimation(ta);
    }

I uploaded the code to BitBucket as a public repo so you can try this project exactly as I have.

Any help or ideas about why this is happening or how to fix it would be greatly appreciated! What is desired is to smoothly animate the WebView out of the picture and back in. Thanks!

like image 965
Robert Karl Avatar asked Oct 09 '12 18:10

Robert Karl


1 Answers

Generally speaking, it seems the problem has to do with a bug when using WebViews with hardware acceleration enabled on 3.0+ devices. I also tried using the sliding menu library with a WebView but experienced the same flicker problem. After looking around I found a workaround here:

WebView “flashing” with white background if hardware acceleration is enabled (Android 3.0+)

The workaround uses the following code to set the layer type of the WebView to software rendering:

webview.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

This code solved the flicker for me with the drawback of lower performance.

like image 95
Stephen Asherson Avatar answered Sep 20 '22 19:09

Stephen Asherson