前言:最近项目大量用到状态栏透明,网上也出现很多库可以直接拿来用,个人认为没有必要那么重引用到一个库(有木有同学和我有一样的想法),所以研究了一番,在此做个记录加强记忆也便后期查阅,如果无意中有幸能帮助到你那就再好不过了。
Android 从 44 (SDK 19) 开始支持 系统栏(状态栏+导航栏)半透明 效果:
翻译一下就是:
TranslucentDecor 主题设置了两个属性 windowTranslucentStatus 和 windowTranslucentNavigation 都为 true,前者指定状态栏半透明、后者指定导航栏半透明。
本文只探讨“状态栏” 。
默认样式是这样:
可见 Toolbar 和系统状态栏之间有明显的分界,我们要实现的效果是 Toolbar 和状态栏背景统一,看起来像是一个整体(自行脑补)。
按照官方文档,我们自定义主题:
对应的 Activity 引用该主题:
我看来看看效果:
虽然实现了半透明,但是布局被状态栏覆盖,接下来在布局文件中设置 fitSystemWindows (注意加到根节点 ConstraintLayout 上):
来看看效果:
虽然布局没有被状态栏覆盖,但是状态栏背景显然这不是我们想要的效果😭
为什么状态栏会这么奇怪?
文章开头的定义中我们说了,布局文件会延伸到状态栏所占区域下, fitsSystemWindows 的作用是给对应的 View 增加 padding(这里以 ConstraintLayout 为例),目的是为了让其内容不被状态栏遮挡。
在我们的布局文件中 ConstraintLayout 没有设置背景(默认白色),所以状态栏默认的半透明背景色和 ConstraintLayout 的白色背景叠加,就变成了上图中的效果。
总结两个基本概念:
1、 windowTranslucentStatus 设置为true之后,状态栏默认是 半透明 的(44 是黑色到透明色渐变,50+ 是纯黑色半透明),和我们要求的 透明 相去甚远。更重要的是,布局会延伸到状态栏底下。
2、 android:fitsSystemWindows 简单理解 就是 View 为了适配系统状态栏和导航栏(不被遮挡)自动 增加 padding ,当然真正的实现原理比这复杂很多而且不同的 View 可以自定义实现方式。
所以,为了实现文章开头提出来的“状态栏透明”效果,我们需要处理:
设置 windowTranslucentStatus 为 true,让状态栏半透明。
在根节点设置 android:fitsSystemWindows 使其不被状态栏遮挡。
Android 44 暂时没有办法去掉状态栏的渐变。
Android 50+ 开始支持修改状态栏颜色,设置透明色即可把半透明去掉。
看看效果:
我们看到即使状态栏透明了,但是其底色是一片白,因为跟节点 ConstraintLayout 没有设置背景,大多情况下我们不会给整个跟节点设置颜色,可以考虑把 android:fitsSystemWindows 设置到子 View 上,本例中是 AppBarLayout (50+ 无效,只能显式给 AppBarLayout 加 padding,可以利用其背景色),实际项目中可灵活调整。
最终效果:
至此,完成状态栏透明效果,网上有很多库,实际上都是基于此原理,在此基础上再自定义 View 做为状态栏背景。
https://developerandroidcom/about/versions/android-44html
实现功能
1步骤:
1) 创建一个工程,主布局就先做一个ImageView,自己找个好看的做src。
2) 在Activity重写的onCreate方法中获得窗口视图对象(DecorView)
3) 设置DecorView的SystemUiVisibility
4) 设置导航条、状态栏的颜色–>透明
5) 获取当前Activity的ActionBar并隐藏
2具体代码和注释:
获取DecorView对象
@Overrideprotected void onCreate(Bundle savedInstanceState) {
View decorView = getWindow()getDecorView();
}
设置SystemUiVisibility
int option = ViewSYSTEM_UI_FLAG_FULLSCREEN // 全屏标记| ViewSYSTEM_UI_FLAG_LAYOUT_FULLSCREEN // 布局全屏标记,避免退出全屏模式时内容被覆盖
| ViewSYSTEM_UI_FLAG_HIDE_NAVIGATION // 隐藏导航栏标记
| ViewSYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION // 布局隐藏导航栏标记,同理
| ViewSYSTEM_UI_FLAG_IMMERSIVE_STICKY // 粘性沉浸体验
| ViewSYSTEM_UI_FLAG_LAYOUT_STABLE; // 确保上述标记稳定// 此方法用来设置系统UI的可见性,系统UI包括状态栏、ActionBar、导航栏devorViewsetSystemUiVisibility(option);
设置状态栏、导航栏的颜色:
getWindow()setStatusBarColor(ColorTRANSPARENT);// ColorTRANSPARENT = 0 表示#00000000即透明颜色getWindow()setNavigationBarColor(ColorTRANSPARENT);
获取本页面的ActionBar并隐藏起来
ActionBar actionBar = getSupportActionBar(); // 注意:此处用的Activity继承的是AppCompatActivity(它继承的是FragmentActivity)
// 所以调用的是getSupport方法,如果继承Activity则直接调用get方法
assert actionBar != null; // 这一句可以不理会,反正我是Ctrl + F1提示出来的,意思其实是判断如果actionBar不为空则向下执行。
actionBarhide();
注意:最后一点注意事项是:只支持Android API 21以上的手机
Android44以后, 可以将状态栏设置为透明, 或者任意颜色
1 全屏模式
2 着色模式
在Android44之后提供了可以修改状态栏的属性接口后,我们可以直接通过style文件来配置状态栏, 但是需要注意的是, 为了兼容44以下的版本, 所以必须在配置多个API级别的values文件 这里直接借参考文章中的图:
最基本的在44版本之下会加载默认的values/stylesxml, 如果在44版本会加载 values-v19/stylesxml, 50以上加载 values-v21/stylesxml文件 具体配置如下:
values/stylesxml
<style name="ImageTranslucentTheme" parent="AppTheme">
<!--在Android 44之前的版本上运行,直接跟随系统主题--></style>123
values-v19/stylesxml
<style name="ImageTranslucentTheme" parent="ThemeAppCompatLightDarkActionBar">
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
</style>1234
values-v21/stylesxml
<style name="ImageTranslucentTheme" parent="ThemeAppCompatLightDarkActionBar">
<item name="android:windowTranslucentStatus">false</item>
<item name="android:windowTranslucentNavigation">true</item>
<!--Android 5x开始需要把颜色设置透明,否则导航栏会呈现系统默认的浅灰色-->
<item name="android:statusBarColor">@android:color/transparent</item>
</style>