Android中显示,隐藏Status Bar和Navigation Bar,沉浸式体验
随着Android版本的迭代更新,如何使某项特性能够兼容各个版本,一直困扰开发人员。比如状态栏(Status Bar)的显示与隐藏,本篇文章也主要讨论Android中状态栏(Status Bar)以及导航栏(Navigation Bar)的显示与隐藏。
1.在Android4.0及以下隐藏Status Bar
在Android4.0(API level 14)及以下你可以通过设置 WindowManager 的标志来隐藏Status Bar,你可以通过在代码中设置或者通过在manifest中设置activity的主题来实现。如果在你的APP中Status Bar需要一直隐藏,那么最好的方法是在manifest中设置activity或者application的主题。
...
当然,你也可以在代码中设置 WindowManager 的标志来实现。这种方式使得当程序需要根据用户的交互来显示或者隐藏Status Bar变得很容易。
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // If the Android version is lower than Jellybean, use this call to hide // the status bar. if (Build.VERSION.SDK_INT < 16) { getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); } setContentView(R.layout.activity_main); } ...}
当你设置了WindowManager 的标志时,它会一直起作用,除非你清除这些标志。
那么问题来了,当我们因为需要隐藏Status Bar而激活FLAG_FULLSCREEN标志时,如果来清除此标记使得Status Bar重新显示出来。这个时候我们可以通过设置 FLAG_LAYOUT_IN_SCREEN 标记来使Status Bar重新显示,这也避免了你的布局在Status Bar显示或隐藏时需要重新调整大小。
2.在Android4.1(API level 16) 及以上隐藏Status Bar
在Android4.1(API level 16) 及以上隐藏Status Bar可以调用 setSystemUiVisibility()方法,该方法在一个独特的视图水平设置UI的标记,这些设置会聚集到window层级,相比设置WindowManager 的标记,使用这个方法可以让你对Status Bar有更细粒度的控制。
View decorView = getWindow().getDecorView();// Hide the status bar.int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN;decorView.setSystemUiVisibility(uiOptions);// Remember that you should never show the action bar if the// status bar is hidden, so hide that too if necessary.ActionBar actionBar = getActionBar();actionBar.hide();
注意: 1.一旦UI标记被清除(比如离开当前activity),如果你想继续隐藏Status Bar,你需要重新设置他们。
2.在哪个位置设置UI标记很重要。如果你在 onCreate()
方法中设置,当用户点击home键时,此时Status Bar会出现,当用户再次打开该activity时, onCreate()
方法不会被调用,导致Status Bar会一直显示。如果你想在用户导航到当前activity或者导航出当前activity时一直保持系统UI的改变,你应该在 onResume()
或者 onWindowFocusChanged()
.中设置UI标记。
3.当你离开当前视图时,通过该方法设置的UI标记会被清除。
3.使内容出现在Status Bar的后面(在Android 4.1及以上 )
在Android 4.1 及以上你可以设置你的应用程序的内容显示在Status Bar的后面,这样一来,当Status Bar显示或者隐藏时,你的内容不仅就不需要重新调整大小了。要达到这样的效果使用 SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
标记。你可能同时需要使用 SYSTEM_UI_FLAG_LAYOUT_STABLE来帮助你的app持有一个稳定的布局。
在大多数情况下,你可以通过在你的布局xml文件中添加一个标记android:fitsSystemWindows
,并设置为true,这会导致系统窗口的父布局调整为系统窗口留的padding。这种方式对大多数app有效。
然而,在某些情况下,你需要更改默认的padding,来直接操作你的布局相对于system bars如何放置,通过覆写fitSystemWindows(Rect insets)方法。
4.Dim the Status and Navigation Bars
你可以使用 SYSTEM_UI_FLAG_LOW_PROFILE
标记来dim Status and Navigation Bars,如下:
// This example uses decor view, but you can use any visible view.View decorView = getActivity().getWindow().getDecorView();int uiOptions = View.SYSTEM_UI_FLAG_LOW_PROFILE;decorView.setSystemUiVisibility(uiOptions);
通过这种方式,当用户触摸Status 和 Navigation Bars的区域时,会导致清除掉这个标记,一旦清除,如果你想继续dim Status 和 Navigation Bars,你需要重新设置它。
5.显示Status and Navigation Bars
如果你想在代码里清除所有使用setSystemUiVisibility()
方法设置的标记,可以按照如下方式:
View decorView = getActivity().getWindow().getDecorView();// Calling setSystemUiVisibility() with a value of 0 clears// all flags.decorView.setSystemUiVisibility(0);
6.隐藏导航栏(Hiding the Navigation Bar)
隐藏导航栏(Android 4.0 (API level 14))及以上引入,可以使用 SYSTEM_UI_FLAG_HIDE_NAVIGATION
标记来隐藏导航栏,如下代码:
View decorView = getWindow().getDecorView();// 同时隐藏 navigation bar 和 status bar.// SYSTEM_UI_FLAG_FULLSCREEN 标记仅仅存在于 Android 4.1 及以上, 但是当你隐藏navigation bar时也应该隐藏status barint uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN;decorView.setSystemUiVisibility(uiOptions);
注意:
1.通过这种方式,触摸屏幕的任何地方都会导致navigation bar (and status bar) 出现并且一直显示,用户的交互使得标记被清除。
2.一旦标记被清除,需要重新设置。
3.在哪个位置设置UI标记很重要。如果你在 onCreate()
方法中设置,当用户点击home键时,此时Status Bar会出现,当用户再次打开该activity时, onCreate()
方法不会被调用,导致Status Bar会一直显示。如果你想在用户导航到当前activity或者导航出当前activity时一直保持系统UI的改变,你应该在 onResume()
或者 onWindowFocusChanged()
.中设置UI标记。
4.当你离开当前视图时,通过该方法设置的UI标记会被清除。
7.使程序的内容出现在导航栏(Navigation Bar)的后面
在 Android 4.1 及以上你可以设置你的应用程序的内容显示在Navigation Bar的后面,这样一来,当Navigation Bar显示或者隐藏时,你的内容不仅就不需要重新调整大小了。要达到这样的效果使用
SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
标记。你可能同时需要使用
SYSTEM_UI_FLAG_LAYOUT_STABLE
来
帮助你的app持有一个稳定的布局。
8.使用沉浸式的全屏模式
在Android 4.4 (API Level 19)为setSystemUiVisibility()
引进了一个新的标记 SYSTEM_UI_FLAG_IMMERSIVE,来使你的app真正的全屏。当这个标记与
SYSTEM_UI_FLAG_HIDE_NAVIGATION
和 SYSTEM_UI_FLAG_FULLSCREEN
结合使用,隐藏 navigation 和 status bars并且让你的app能够捕获屏幕上的所有触摸事件。
当沉浸式全屏模式启用,你的activity任然可以接收所有的触摸事件。用户可以在system bars本来在的位置向内滑动从而使system bars显示出来。当然这会导致标记 SYSTEM_UI_FLAG_HIDE_NAVIGATION
(如果设置了SYSTEM_UI_FLAG_FULLSCREEN也会被清除)会被清除。如果设置了监听器 View.OnSystemUiVisibilityChangeListener
,此时会触发这个监听器。当然,如果你想让system bars 隔一会后自动隐藏,你应该使用SYSTEM_UI_FLAG_IMMERSIVE_STICKY
标记。注意,该标记不会触发任何监听器。
9.使用非粘性沉浸式
// This snippet hides the system bars.private void hideSystemUI() { // Set the IMMERSIVE flag. // Set the content to appear under the system bars so that the content // doesn't resize when the system bars hide and show. mDecorView.setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar | View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar | View.SYSTEM_UI_FLAG_IMMERSIVE);}// This snippet shows the system bars. It does this by removing all the flags// except for the ones that make the content appear under the system bars.private void showSystemUI() { mDecorView.setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);}
10.使用粘性沉浸式
@Overridepublic void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); if (hasFocus) { decorView.setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);}}
11.监听系统UI变化
要监听系统UI的变化,需要注册监听器,如下所示:
View decorView = getWindow().getDecorView();decorView.setOnSystemUiVisibilityChangeListener (new View.OnSystemUiVisibilityChangeListener() { @Override public void onSystemUiVisibilityChange(int visibility) { // Note that system bars will only be "visible" if none of the // LOW_PROFILE, HIDE_NAVIGATION, or FULLSCREEN flags are set. if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) { // TODO: The system bars are visible. Make any desired // adjustments to your UI, such as showing the action bar or // other navigational controls. } else { // TODO: The system bars are NOT visible. Make any desired // adjustments to your UI, such as hiding the action bar or // other navigational controls. } }});
更多相关文章
- Android 虚化图片的方法
- android完全退出程序的方法
- android常用方法汇总-更新中
- Android结束进程的方法
- Android 比Timer更好方法
- Android中AppWidget使用方法
- Android 官方 Lambda支持方法
- android BroadcastReceiver遇到 java.lang.IllegalAccessExcepti
- Android 调用系统相机拍照保存以及调用系统相册的方法