Android侵入状态栏+沉浸式体验(启动页和普通侵入状态栏)

2,821 阅读6分钟

Android侵入状态栏+沉浸式体验

Theme实现

这里测试机器的安卓版本基本都在安卓8以上了,不知道低版本的安卓适配程度如何

属性说明

  1. 侵入状态栏,屏幕内容会进入状态栏,内容整体平移进入,true进入,false不进入

    <item name="android:android:windowTranslucentStatus">true</item>
    
  2. 内容不被状态栏遮挡,和上面属性并不冲突,true不被遮挡,false被遮挡

    <item name="android:fitsSystemWindows">true</item>
    
  3. 修改状态栏的背景色,状态栏最底层是背景,背景之上就是图标和文字了,这里需要注意,android11测试的时候如果侵入状态栏了,颜色默认半透明,修改不生效,也就是和第一条有影响关系,这个设置后就会影响第一条

    <item name="android:statusBarColor">@android:color/transparent</item>
    

    还有个属性也可以修改状态栏的颜色,如下,需要最外层布局为CoordinatorLayout,并且侵入状态栏目和设置<item name="android:fitsSystemWindows">true</item>才生效,同时上一条设置如果没有侵入状态栏以上一条为主,侵入了并且最外层为CoordinatorLayout就以这条为主

    <item name="statusBarBackground">@color/red_FF7878</item>
    
  4. 修改状态栏图标和文字颜色,系统API限制,只有两者颜色,黑或者白,下面true就是黑,false就是白

    <item name="android:windowLightStatusBar">true</item>
    
  5. 全屏,让状态栏消失,true隐藏,false显示,启动页常用

    <item name="android:windowFullscreen">true</item>
    
  6. 刘海屏和挖孔屏幕适配,否则全屏,也就是第5条属性在部分机型的状态栏侧有黑边,需要在value-v27设置,适配api27版本,刘海屏是在api28才支持的

    <item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
    
  7. 冷启动空内容时背景,如启动页可以设置为带logo的drawable等等,冷启动优化部分,不讲了

    <item name="android:windowBackground">@color/black_000000</item>
    

具体使用

侵入状态栏,内容不被遮挡,显示状态栏,但状态栏颜色固定为半透明的灰色

不需要最外层为CoordinatorLayout,需要状态栏背景为其他色修改<item name="android:statusBarColor">@android:color/transparent</item>即可,<item name="android:windowBackground">@color/black_000000</item>可不在这里设置的,可以另外一个主题继承这个IntrusionActivityTheme,在单独的activity设置

    <!--侵入状态栏,内容不被遮挡,显示状态栏,状态栏图标文字为白,背景透明-->
    <style name="IntrusionActivityTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar.Bridge">
        <!--侵入状态栏-->
        <item name="android:windowTranslucentStatus">true</item>
        <!--防止内容被遮挡但侵入状态栏-->
        <item name="android:fitsSystemWindows">true</item>
        <!--由于界面主黑色,状态栏文字设置为白-->
        <item name="android:windowLightStatusBar">false</item>
        <!--进入加载第一屏背景色-->
        <item name="android:windowBackground">@color/black_000000</item>
    </style>

效果如下,效果貌似不是很好,但是背景是暗色,也就是黑色效果就很完美

_20240729152014.jpg _20240729152117.jpg

可以使用<item name="android:statusBarColor">@android:color/white</item>将状态栏颜色直接设置为跟内容背景颜色一样也可以实现侵入状态栏的效果,同时 <item name="android:windowTranslucentStatus">false</item>不侵入状态栏,并且这个情况下还可以随意修改状态栏颜色,下面这里背景为黑色,状态栏设为了黑色

_20240729152021.jpg

另外的古老方法就是在代码中直接,但是 window.decorView.systemUiVisibility被废弃了,但还可以用

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            // 设置状态栏完全透明
            window.statusBarColor = Color.TRANSPARENT
            window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
                    View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
        }
侵入状态栏,内容不被遮挡,显示状态栏,需要借助CoordinatorLayout

需要布局最外层为CoordinatorLayout,需要状态栏背景为其他色修改<item name="statusBarBackground">@android:color/transparent</item>即可

    <!--侵入状态栏,内容不被遮挡,显示状态栏,状态栏图标文字为白,背景透明,要求最外层为CoordinatorLayout-->
    <style name="IntrusionActivityByCoordinatorLayoutTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar.Bridge">
        <!--状态栏透明-->
       <!-- <item name="android:statusBarColor">@android:color/transparent</item>-->
        <!--状态栏透明-->
        <item name="statusBarBackground">@android:color/holo_blue_light</item>
        <!--侵入状态栏-->
        <item name="android:windowTranslucentStatus">true</item>
        <!--防止内容被遮挡但侵入状态栏-->
        <item name="android:fitsSystemWindows">true</item>
        <!--由于界面主黑色,状态栏文字设置为白-->
        <item name="android:windowLightStatusBar">false</item>
    </style>

这个是修改颜色的样式,效果如下,同样可以修改状态栏颜色

_20240729153603.jpg
个人经常使用

个人经常使用下面来完成应用开发,效果完美,需要最外层为CoordinatorLayout,但是增加了视图层次

    <!--侵入状态栏,内容不被遮挡,显示状态栏,状态栏图标文字为白,背景透明,要求最外层为CoordinatorLayout-->
    <style name="IntrusionActivityByCoordinatorLayoutTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar.Bridge">
        <!--状态栏透明-->
        <item name="android:statusBarColor">@android:color/transparent</item>
        <!--防止内容被遮挡但侵入状态栏-->
        <item name="android:fitsSystemWindows">true</item>
        <!--由于界面主黑色,状态栏文字设置为白-->
        <item name="android:windowLightStatusBar">false</item>
    </style>
_20240729153610.jpg
侵入状态栏,内容不被遮挡,不显示状态栏,启动页常用

value-v27下的theme加入,当然可以让工具忽略这个api检查,如果是适配白天黑夜双模式,注意在value-night-v27下也加上,否则调用的value-night下的适配不到这个取消黑边

    <style name="SplashTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!--状态栏透明-->
        <item name="android:statusBarColor">@android:color/transparent</item>
        <!--全屏,隐藏状态栏-->
        <item name="android:windowFullscreen">true</item>
        <!--侵入状态栏-->
        <item name="android:windowTranslucentStatus">true</item>
        <!--防止内容被遮挡但侵入状态栏-->
        <item name="android:fitsSystemWindows">true</item>
        <!--进入加载-->
        <item name="android:windowBackground">@color/black_000000</item>
        <!--v27加入 挖孔屏和刘海屏全屏黑边消失-->
        <item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
    </style>

在value-v27下的theme加入,原本的theme不要加上<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>即可

_20240729153747.jpg

在AndroidManifest引用

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <application
        android:name=".App"
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_app_launch_7_9"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_app_launch_7_9_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.AccountBook"
        tools:targetApi="31">
        <activity
            android:name=".ui.activity.HomeActivity"
            android:exported="false"
            android:theme="@style/MainActivityTheme" />
        <activity
            android:name=".ui.activity.EditSingleAccountActivity"
            android:exported="false"
            android:launchMode="singleTask"
            android:theme="@style/IntrusionActivityTheme" />
        <activity
            android:name=".ui.activity.SplashActivity"
            android:exported="true"
            android:theme="@style/SplashTheme">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

代码实现(有空待补充)

还有底部导航栏属性

android:windowTranslucentStatusandroid:windowTranslucentNavigation 是Android系统中的两个窗口属性,它们用于设置应用窗口的状态栏和导航栏是否为半透明状态。以下是这两个属性的区别:

  1. android:windowTranslucentStatus
    • 作用:这个属性用于控制状态栏是否为半透明状态。
    • 效果:当设置为true时,状态栏会变成半透明。应用的内容可以延伸到状态栏区域,但状态栏上依然会显示系统信息(如时间、电池状态等)。应用可以自定义背景或图片在状态栏下方显示。
  2. android:windowTranslucentNavigation
    • 作用:这个属性用于控制导航栏是否为半透明状态。
    • 效果:当设置为true时,导航栏会变成半透明。应用的内容可以延伸到导航栏区域,并且导航栏上的按钮(如返回、主页、最近任务等)仍然可见并且可以操作。

使用场景和注意事项

  • 这些属性常用于全屏显示或需要让内容延伸到整个屏幕的应用,如视频播放应用、图片浏览应用等。
  • 当使用这些属性时,需要特别注意布局的调整,以避免内容被状态栏或导航栏遮挡。通常需要配合FitsSystemWindows等属性或使用系统提供的WindowInsets来处理。
  • 在Android 5.0(API Level 21)及以上版本,开发者通常会选择使用android:statusBarColorandroid:navigationBarColor来直接设置状态栏和导航栏的颜色,而不是使用半透明状态。

通过合理使用这两个属性,可以使应用的UI更加现代化和富有层次感。