Status Bar和Navigation Bar的显示与隐藏

实现仿微信查看大图的时候StatusBar和NavigationBar的状态变化

两篇不错的关于这两个Bar状态的文章:

1.http://angeldevil.me/2014/09/02/About-Status-Bar-and-Navigation-Bar/
2. http://vitiy.info/small-guide-how-to-support-immersive-mode-under-android-4-4/
3.http://developer.android.com/training/system-ui/immersive.html

1
2
3
4
//得到contentView的父布局,是一个FrameLayout
rootContent = (ViewGroup) findViewById(android.R.id.content);
//add 大图控件到 rootContent
root.addView(bview);

System UI的显示和隐藏通过下面两个函数实现。在hideSystemUI()方法中,通过SYSTEM_UI_FLAG_LAYOUT_FULLSCREENSYSTEM_UI_FLAG_FULLSCREEN来隐藏Status Bar,让Activity的UI占满全屏(不会占据Navigation Bar的空间),通过SYSTEM_UI_FLAG_IMMERSIVE_STICKY模式,使得系统以半透明方法显示System UI方便用户操作,并会在一段时间后自动隐藏,此时并不会引起onSystemUiVibilityChanged的调用.

1
2
3
4
5
6
7
8
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private void hideSystemUI() {
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}

showSystemUI()方法中,通过SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN使得Activity的UI占据全屏,但是这个时候Status Bar和Navigation Bar都没有被隐藏,所以Status Bar会遮挡住Activity UI的部分空间。解决办法就是给ContentView设置fitSystemWindows为true。这样系统会把被Status Bar遮挡住的区域自动转化成Activity UI的内边距,这样被StatusBar遮挡的问题就得到了解决。

1
2
3
4
5
6
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private void showSystemUI() {
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
}

但是当Window的焦点发生变化的时候,SYSTEM_UI_FLAG_IMMERSIVE_STICKY就会失效,Status Bar会重新出现,并且不是透明的。可以监听onWindowFocusChanged事件来重新调用hideSystemUI()方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus && hasView) {
mPhotoView.postDelayed(new Runnable() {
@Override
public void run() {
hideSystemUI();
}
}, 500);
}
}