提起沉浸式,很多人会说沉浸式状态栏,至于这个名称怎么来的,不得而知。然而Android官方文档中并没有给出沉浸式状态栏的名称,只有沉浸式模式这么一说,下面这段话出自Android官方文档,也很好的解释了沉浸式模式到底是什么。
其实,Android沉浸式模式的本质就是全屏化,将背景与状态栏融为一体,让用户可以通过手势滑动的操作隐藏或显示状态栏和导航栏。目前好多大型游戏,都实现了这种模式,比如龙珠激斗:
这样做的好处是可以让用户完全沉浸在游戏当中,不会被系统的一些UI元素所干扰。接下来我们就来一步一步实现这个功能。
Android当中一个界面包含状态栏,导航栏,ActionBar等等,要实现沉浸式模式,就要把这些元素都去掉。就以上面龙珠激斗那张图为例,开始实现我们的需求。首先,创建一个测试工程,并在布局当中加入一张宽高充满父窗体的ImageView。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/background"
android:scaleType="fitXY"
/>
</RelativeLayout>
运行当前工程,可以看到如下图所示:
由于4.4以下的版本没有提供沉浸式模式的支持,所以这里就不做SDK版本的判断了。我们先把ActionBar隐藏,在activity的onCreate中添加如下代码:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//隐藏ActionBar
getSupportActionBar().hide();
}
然后运行程序,可以看到如下效果:
可以看到,ActionBar已经被我们隐藏掉了,接下来就是隐藏顶部的状态栏了:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//隐藏ActionBar
getSupportActionBar().hide();
//隐藏状态栏
View decorView = getWindow().getDecorView();
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN);
}
这里在用decorView设置系统UI可见性的时候,使用了一个系统UI的flag,我们跟进View源码内部,看看这个flag起什么作用:
*Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
into the normal fullscreen mode so that its content can take over the screen
hile still allowing the user to interact with the application.*
这段话其实是使用这个系统UI flag,可以让View的内容接管屏幕,进入到全屏模式。好,继续运行程序:
由于我使用的测试机没有底部导航栏,所以这几张图片中也就没有导航栏了。而隐藏导航栏也非常简单,只需要再加入一个UI flag即可,将上面的部分代码修改一下:
//隐藏状态栏和导航栏
View decorView = getWindow().getDecorView();
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
这样,就可以将导航栏也一并去掉了。到此,沉浸式模式也就初步打造完成了。但是,当我们触摸屏幕的任意一个位置的时候,都会退出这种模式,状态栏又显示出来了,那么,如何打造真正的沉浸式模式呢。其实依然是几个系统UI flag配合使用,在activity当中重写onWindowFocusChanged()方法,将UI flag组合使用,如下面代码所示:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if(hasFocus){
View decorView = getWindow().getDecorView();
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}
}
}
再次运行程序,可以看到,界面和刚才一样,当我们需要显示状态栏的时候,可以在屏幕顶部向下拉,这样状态栏就显示出来了,过几秒钟状态栏又会自动隐藏回去,到这里,真正的沉浸式就实现了。