Android 沉浸式( Translucent System
样式
沉浸式有两种实现方式,如图:
图片1 图片2第一张图来自于 YouTube Android 客户端,这种实现方式是将 Toolbar 和 Status Bar 沉浸。第二张图来自于 Google Play 客户端,与第一幅图不同的是,它将 Status Bar 设置为透明,并将布局直接顶到了手机屏幕的最顶部。
第一种沉浸式实现比较容易,这里不再赘述。本文记录的是第二种的实现方式。
实现
- 配置不同 API 版本下的样式
首先新建一个 Translucent System Bar 风格的 Theme。因为不同的 SDK 版本下 Translucent System Bar 的实现方式略有不同。为了兼容版本,我们需要多新建 values-v19 和 values-v21 下的style。
-
values/styles
<!--Android 4.4 以下版本,不实现沉浸样式,跟随系统样式--> <style name="ImageTranslucentTheme" parent="AppTheme" />
-
values-v19/styles
<!--4.4版本后 5.0以前--> <style name="ImageTranslucentTheme" parent="AppTheme"> <item name="android:windowTranslucentStatus">true</item> <item name="android:windowTranslucentNavigation">true</item> </style>
-
values-v21/styles
```xml
<!--5.0以后-->
<style name="ImageTranslucentTheme" parent="AppTheme">
<item name="android:windowTranslucentStatus">false</item>
<item name="android:windowTranslucentNavigation">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
</style>
```
-
配置 AndroidManifest.xml 中的 Activity
AndroidManifest.xml 中 <application/> 标签内
<activity android:name=".MainActivity" android:theme="@style/ImageTranslucentTheme"> </activity>
-
在 Activity 的布局文件中设置背景图片
layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent"> <View android:layout_width="match_parent" android:layout_height="300dp" android:background="#ff0000" /> </RelativeLayout>
以上就基本完成了一个简单的图片沉浸,效果如下:
图片3踩坑
问题
在上面的实现效果可以发现,底部导航栏的虚拟按键其实已经覆盖住了布局(如果我们将红色充满整个布局,则更为明显):
图片4可以很清晰的看到,这个界面里布局最底部有一部分被导航栏遮盖,如果底部存在可以交互的控件(如 按钮,底部导航栏等),控件本身的交互就会与虚拟按键冲突。
解决
从 style 中的属性我们猜测,我们需要将 <item name="android:windowTranslucentNavigation">false</item>
属性设置为 false ,是 Navigation Bar 不透明,但效果却并没有变成我们想象的那样,Status Bar 的样式完全失效。
事实上,android:windowTranslucentNavigation
这个属性额外设置了 SYSTEM_UI_FLAG_LAYOUT_STABLE
和 SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
两个 flag。所以我们需要再绘制完 Status Bar 以后重新请求这两个 flag 。
在 onCrate 方法中调用
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
即可实现效果。效果如图:
图片5