Sunday, November 15, 2009

Smooth full screen transition

I finally found out how to smoothly transition to and from Android's full-screen mode. I wanted the status bar to be displayed most of the time, but switched off when the user views an image.

To create the main screen:

setContentView(mGLView);
addContentView(mTopView);

WindowManager.LayoutParams attrs = getWindow().getAttributes();
attrs.flags |= WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
getWindow().setAttributes(attrs);
mTopView.setPadding(0, 25, 0, 0);

mTopView is a FrameLayout at the top of my window hierarchy. 25 is the height of the status bar.

mGLView is a GLSurfaceView that I use to display the image. Note that at this point, the size of both mTopView and mGLView will fill the entire screen (but be clipped by the status bar at the top edge).

The setPadding() call offsets the child of mTopView so that the child appears just beneath the status bar.

To switch to full screen mode, call this

WindowManager.LayoutParams attrs = getWindow().getAttributes();
attrs.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN;
getWindow().setAttributes(attrs);
change_my_layout();

The above code will essentially hide the status bar and give you an extra 25 pixels at the top of the screen. In change_my_layout(), I do this:

mTopView.setVisibility(View.GONE);
mGLView.setVisibility(View.VISIBLE);

The key here is to use FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_NO_LIMITS. Otherwise the screen will "jerk" a little bit when you apply FLAG_FULLSCREEN.

Also note that mGLView must be positioned behind mTopView in the view stack. Otherwise the mGLView will not be visible to the user EVEN IF the mTopView is set to View.GONE (due to interesting design in Android that's too much to explain here ....).

Failed Attempts:

I tried the "True Android Way" but creating a new full-screen Activity to hold the mGLView. However, this proved to be too slow (at least 500ms on the G1).