Show and hide android notification bar without causing a layout jerk

Many android apps require toggling between full screen and non full screen view (lets call it framed screen) smoothly.
Typical apps which require this feature include social networking apps (which require maximum use of the space to accomodate infinite timeline like features), ebook reader apps, image gallery apps, video player etc.

Hiding action bar and go full screen

By default, whenever you request for full screen mode, the activity will resize instantly to take the extra space and the this causes the child views to shift in position slightly to the top. This leads to a bad UX since the user does not expect the view to shift in position.

You can use the following method in your Activity to switch to full screen mode (which will hide the top notification bar)

private void setScreenMode(boolean fullscreen)
{
   if(fullscreen)
   {
     getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
     getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
    }
    else
    {
      getWindow().addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
      getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
    }

}

Please note that some devices (like galaxy tab) dont have the top notification bar (a.k.a status bar), but have a navigation bar at the bottom which also acts like a notification/status bar. For such devices, there is no difference between full screen and framed screen modes. The navigation bar at the bottom can never be hidden. It can only be put into low profile mode, where the buttons turn into tiny dim dots. If you use the above code snippet to switch to fullscreen, the device will silently ignore the flags (no exceptions). Also you cannot make a generalisation about tablets not having a top notification bar, since devices like nexus 7 have both top and bottom bars. Be warned that there is no direct api to detect whether the device has a top bar and/or a bottom bar nor their heights. People have figured out a few hacks which rely on subtracting the app height from the device’s screen height to figure out things, but they are not very reliable. So do not try to write any code which makes any kind of assumption about the height of the bars.

In Mac OSX Lion GUI, fullscreen mode is handled in a clever way. Whenever a window goes into fullscreen mode, they crossfade between a snapshot of the windowed layout and a snapshot of the fullscreen. Doing the same in android would be a overkill, since the window resizes only by about 40dp, unlike mac where it could be commonly in the range of 100 – 1000 pixels width and height;

Let us go through some of the common methods we can use for a smooth transition between full screen and framed views in android.

FLAG_LAYOUT_NO_LIMITS | FLAG_LAYOUT_IN_SCREEN

For most apps this would be the easiest way of smooth transitioning. This flag basically lets android know that your layout should always take up all the available screen space (irrespective of the notification bar).

Try this code snippet in your onCreate method :

WindowManager.LayoutParams attributes = getWindow().getAttributes();
attributes.flags |= WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
getWindow().setAttributes(attributes);

This means that the first child in your view group will start drawing from the top left of your screen (behind your notification bar). So switching between full screen and framed screen would not cause a resize and hence avoid a jerk. What you could do additionally is,specify a top padding of around 40 – 50 dp. Now, when you go fullscreen, you will see an empty space behind the notification bar which might work well for most applications.

The only problem with this approach is when you use honeycomb’s action bar (or its gingerbread backport called action bar sherlock).

Since you have specified that the application has no limits, action bar gets drawn behind the notification bar, which looks ugly since all your icons gets clipped at the top. A quick fix to this problem is to specify a top padding for your action bar.

This can be done using action bar styles. Refer this article which talks about theming action bar. Using this technique, you can specify android:paddingTop to around 40 dp which will draw some empty space to accomodate the notification bar. You will also need to increase the height of the action bar using android:height attribute.

This technique leads to 3 issues. One is that in tablets, the top padding looks bad. Since there is no accurate way to determine the height of the top notification bar, we cannot dynamically specify the padding. Some techniques which determine the height of notification bar return values like 48 dp even for devices which dont have a notification bar. The second issue is that, I noticed a bug in API > 11, where specifying a top padding acts like specifying both top margin and top padding, which means that it shifts the action bar downwards and also gives some extra space inside the action bar. Although this issue didnt occur in action bar sherlock (API<11) library. The third issue is that when the action bar has a drop down menu as the last visible item, the menu goes out of screen due the NO_LIMITS flag.

Gravity : Bottom

For some applications, this technique can be used to avoid the issues in the previous method. Using this method we let the layout get resized when the activity goes fullscreen, but at the same time, we specify that the child views have a gravity bottom and an absolute height. This means that when additional space becomes available due to removal of the notification bar, since the views are aligned to the bottom of the screen, no jerk occurs.

Be warned that if any of your views have the height set to match_parent, then a jerk can occur. For such views you should programmatically set the height to display.getHeight() in your onCreate and onConfigurationChanged method so that you have a view which takes most of the screen height.

The idea is to set the position of all views relative to the bottom of the screen because we know that the bottom of the screen will never change when we toggle between full screen and framed screen modes for any kind of device (be it galaxy tab or a galaxy nexus phone or a nexus 7 tab).

Animating resize

If you would like to animate any positional changes whenever the top bar hides, you could use the onSizeChanged method present in the view class. For e.g, you can create an empty custom view which has a height of “match_parent” and in the onSizeChanged method of this view, you can start your animation of other views. This will give a cool animation whenever the activity resizes.

Incoming search terms:

2 thoughts on “Show and hide android notification bar without causing a layout jerk

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>