郭霖的博客这样实现
透明状态栏
新建一个项目,只放一张图片
可以看到 状态栏、ActionBar、底部导航栏都显示,现在修改 Activity 中代码
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
View decorView = getWindow().getDecorView();
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN);
getSupportActionBar().hide();
}
}
重新运行程序,可以看到 状态栏、ActionBar 都隐藏了
这里先调用getWindow().getDecorView()
方法获取到了当前界面的 DecorView,然后调用它的setSystemUiVisibility()
方法来设置系统UI元素的可见性。其中,SYSTEM_UI_FLAG_FULLSCREEN
表示全屏的意思,也就是会将状态栏隐藏
另外,根据Android的设计建议,ActionBar 是不应该独立于状态栏而单独显示的,因此状态栏如果隐藏了,我们同时也需要调用 ActionBar 的hide()
方法将ActionBar也进行隐藏
虽说这才是正统的沉浸式含义,但有些朋友可能想实现的就是饿了么那样的状态栏效果,而不是直接把整个系统状态栏给隐藏掉,那么又该如何实现呢?
方法一:
修改代码如下:
View decorView = getWindow().getDecorView();
int options = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN|View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
decorView.setSystemUiVisibility(options);
getWindow().setStatusBarColor(Color.TRANSPARENT);
getSupportActionBar().hide();
我们使用了SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
和SYSTEM_UI_FLAG_LAYOUT_STABLE
,注意两个Flag必须要结合在一起使用,表示会让应用的主体内容占用系统状态栏的空间,最后再调用 Window 的setStatusBarColor()
方法将状态栏设置成透明色就可以了
方法二:
可以用以下代码完成相同的效果
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
getSupportActionBar().hide();
当 window 的FLAG_TRANSLUCENT_STATUS
属性有效的时候,会自动设置 system ui visibility 的标志SYSTEM_UI_FLAG_LAYOUT_STABLE
和SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
当然也可以在 style 中设置属性 windowTranslucentStatus
android:windowTranslucentStatus
方法三:
如果有 actionbar 的话,可以设置 状态栏和 actionbar 颜色相同来实现
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
getWindow().setStatusBarColor(Color.parseColor("#2F90E5"));
设置了FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
,表明会 Window 负责系统 bar的 background 绘制,绘制透明背景的系统 bar(状态栏和导航栏),然后用getStatusBarColor()
和getNavigationBarColor()
的颜色填充相应的区域。这就是 Android 5.0 以上实现沉浸式导航栏的原理
当然 theme 中也可以设置相应属性来设置样式
<style name="Theme.TestApplication" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<item name="android:statusBarColor">#2F90E5</item>
<item name="android:windowTranslucentStatus">false</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
</style>
隐藏导航栏
隐藏导航栏也就是使用了不同的UI Flag而已,修改MainActivity中的代码,如下所示:
View decorView = getWindow().getDecorView();
int options = View.SYSTEM_UI_FLAG_FULLSCREEN|View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
decorView.setSystemUiVisibility(options);
getSupportActionBar().hide();
好像是完全全屏了,但是我们触摸屏幕的任意位置都会退出全屏
除了隐藏导航栏之外,我们同样也可以实现和刚才透明状态栏类似的效果,制作一个透明导航栏:
View decorView = getWindow().getDecorView();
int options = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
decorView.setSystemUiVisibility(options);
getWindow().setNavigationBarColor(Color.TRANSPARENT);
getWindow().setStatusBarColor(Color.TRANSPARENT);
getSupportActionBar().hide();
这里使用了SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
,表示会让应用的主体内容占用系统导航栏的空间,然后又调用了setNavigationBarColor()
方法将导航栏设置成透明色
真正的沉浸式模式
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);
View decorView = getWindow().getDecorView();
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);
}
}
可以看到,界面默认情况下是全屏的,状态栏和导航栏都不会显示。而当我们需要用到状态栏或导航栏时,只需要在屏幕顶部向下拉,或者在屏幕底部向上拉,状态栏和导航栏就会显示出来,此时界面上任何元素的显示或大小都不会受影响。过一段时间后如果没有任何操作,状态栏和导航栏又会自动隐藏起来,重新回到全屏状态
这就是最标准的沉浸式模式
轮子
Github:ImmersionBar
ImmersionBar的使用说明