Anroid沉浸式状态栏

本文详细介绍如何在Android应用中实现透明及彩色状态栏的效果,包括针对不同Android版本的适配策略,以及如何通过代码实现全屏模式和着色模式的状态栏。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概要

Metarial Design是2014年Google IO的一个重点,在过去的两年时光里,越来越多的公司已经开始认可MD设计规范。在dribbble上可以越来越多的设计师开始投入到MD设计实践中,MD设计规范终于有底气可以和IOS的设计规范对抗啦Android程序员可以很叫嚣滴告诉设计师这就是Android的设计规范。

很少写Material Design的东西,今天趁着手热,在Material化财经APP的时候,看了些透明状态栏/沉浸式状态栏的东西,觉得自己可能还有很多不足之处只是希望能分享出来,一方面是自己的学习成果,另一方面是希望大家指正自己在理解的不到位或者错误。

先放一张我的五儿子手机原生的短信截图:

228435-b73c8e45b9d40b25.png
图1

从上到下,一次是状态栏,内容View,导航栏(有些机器上不一定有导航栏这个虚拟栏),可以看到状态栏是彩色的,不是以前那种黑乎乎的状态栏,现在你也可以定制自己的状态栏了。

现在我们就来看下我手机上装的APP的一些截图:
<span id="pic2">

228435-c9c209fe3c54ef7d.png
图2

</span>
这个五个应用分别是网易新闻、豌豆荚、微信、小米天气、小气天气。

关于这个状态栏变色到底叫「Immersive Mode」/「Translucent Bars」有兴趣可以去 为什么在国内会有很多用户把 「透明栏」(Translucent Bars)称作 「沉浸式顶栏」?以及何为沉浸模式,沉浸式顶栏,变色龙状态栏,这个历史原因我们就没法去说大家错误,所有就错说错有了沉浸式状态栏一说。

在5.0之后我们是可以通过v7包下的Theme.AppCompat一些列主题为APP的页面设置Activity的的状态栏,但是为了兼容低版本的我们放弃这种方式。为了能定制自己的状态栏,我们可以手动设置状态栏的颜色,可以随时改变状态栏的透明度等,所以我们需要自己来定制一套可行的方案。

实现

准备

分类

  1. 全屏模式和着色模式
    根据内容延伸的角度可以分为两类:全屏模式和着色模式。其中,图2 中前三个页面都是状态栏固定在上方,无论下面怎么滑动,内部View都是那一块固定的大小区域滑动,由于状态栏是固定在一定位置且有着色,我们称之为着色模式,而图2中后两个页面截图中,内容View和状态栏像放在一个FrameLayout一样,是层叠关系并且状态栏是透明,内容View可以延伸到状态栏,我们称之为全屏模式。

  2. 透明状态栏和彩色状态栏
    根据状态栏的颜色,可以分为状态栏透明和不透明(网易新闻、小米天气都是透明,而豌豆荚、wechat都是不透明)。
    以上两种分为是不同维度的,从不同维度来看可以组合如下图:

228435-f2aebf60a7e7777d.png

setFitsSystemWindows

在android doc是这么描述的:

void setFitsSystemWindows (boolean fitSystemWindows)
Sets whether or not this view should account for system screen decorations such as the status bar and inset its content; that is, controlling whether the default implementation of fitSystemWindows(Rect) will be executed. See that method for more details.

Note that if you are providing your own implementation of fitSystemWindows(Rect), then there is no need to set this flag to true -- your implementation will be overriding the default implementation that checks this flag.

大概意思是:setFitsSystemWindows用来设置影响系统的工具栏如状态栏,决定了这个view是否插入到它的ContentView。当您设置了fitSystemWindows(Rect)而没有将setFitsSystemWindows设置为true,你对fitSystemWindows(Rect)设置是无效的.

该属性可以设置是否为系统 View 预留出空间, 当设置为 true 时,会预留出状态栏的空间。

由于这个实在API14(4.0)之后的函数,为了兼容低版本,才有V4里面的

 ViewCompat.setFitsSystemWindows(rootView,false);

透明状态栏

由于Android 4.4才加入透明状态栏,Android 5.0之后可以直接设置状态栏和导航栏,而不是之前的黑乎乎的状态栏,但是,在4.4以下的系统上,想自己定义状态栏就无能为力了。所以,我们将Android 4.4和Android5.0视为边界。

Android 4.4设置透明状态栏

设置方法有两种:

代码

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            // 设置状态栏透明
             activity.getWindow()
                .setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            
}

XML

在values-v19文件夹下,为activity的Style 添加一个属性:

<resources>

   <style name="AppTheme" parent="@style/BaseAppTheme">
       <item name="android:windowTranslucentStatus">true</item>
   </style>
</resources>

5.0+透明状态栏

不过对于5.0系统,上面的设置后的结果可能不是透明哦(在原生机器是不透明的,但是在小米的是透明的,估计MIUI做了一些优化工作)

228435-767eb79e55371d67.png

若是要完全透明,就需要看额外处理,在内容延伸到状态栏一节有介绍。

当然了你也可以用5.0的setStatusBarColor

<span id="5status">全屏模式的透明状态栏</span>

Window window = activity.getWindow();
//设置透明状态栏,这样才能让 ContentView 向上
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 

//需要设置这个 flag 才能调用 setStatusBarColor 来设置状态栏颜色
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); 
//设置状态栏颜色
window.setStatusBarColor(statusColor);

//为了设置全屏
ViewGroup mContentView = (ViewGroup) activity.findViewById(Window.ID_ANDROID_CONTENT);
View mChildView = mContentView.getChildAt(0);
if (mChildView != null) {
    //注意不是设置 ContentView 的 FitsSystemWindows, 而是设置 ContentView 的第一个子 View . 使其不为系统 View 预留空间.
    ViewCompat.setFitsSystemWindows(mChildView, false);
    
}

ViewCompat.setFitsSystemWindows(mChildView, false)中的第二个参数设置为false就是全屏模式,而设置成true。像上述实例中, ViewCompat.setFitsSystemWindows(mChildView, false)就是说mChildView可以直接延伸到phoneWindow的顶部,相当于小米天气的那种效果。

彩色状态栏

有透明状态栏,就有彩色状态栏。
在5.0+设置状态栏很简单就参照全屏模式的透明状态栏中的代码做修改window.setStatusBarColor(int color),而对于Android 4.4--5.0的怎么办呢,Android4.4是提供setStatusBarColor这个方法的。

我们就想到了在上面提到的全屏透明状态栏的基础上加一个和状态栏一样高度的空白View放到顶部。

228435-3719fb8fc608383e.png

好了说干就干:

        activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
 //添加一个空白的view到手机屏幕的顶部
addStatusBarBehind(activity, color, statusBarAlpha);
public static void addStatusBarBehind(Activity activity, int color, int statusBarAlpha) {
        ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
        int       count     = decorView.getChildCount();
        if (count > 0 && decorView.getChildAt(count - 1) instanceof StatusBarView) {
            decorView.getChildAt(count - 1).setBackgroundColor(calculateStatusColor(color, statusBarAlpha));
        } else {
            StatusBarView statusView = createStatusBarView(activity, color, statusBarAlpha);
            decorView.addView(statusView);
        }
        setRootView(activity);
    }

全屏模式

全屏模式,内容延伸到状态栏类似与小米天气的APP,先考虑下怎么做?

答案:将内容移到状态栏下,并且状态栏背景透明.

4.4--5.0

  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            // 设置状态栏透明
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            //  设置根布局的参数
            ViewGroup rootView = (ViewGroup) ((ViewGroup) activity.findViewById(android.R.id.content)).getChildAt(0);
            ViewCompat.setFitsSystemWindows(rootView,false);
            rootView.setClipToPadding(true);
        }

其实就先将状态栏设置了透明activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS),而后可以直接设置内容的根View来直接设置ViewCompat.setFitsSystemWindows(rootView,false),这样就可以直接讲根rootView直接顶上去,和状态栏的顶部对齐。

5.0+

在Android 4.4上设置透明状态栏,在5.0上依然可以正常显示,利用5.0实现的全屏模式的透明状态栏不过状态栏实际上并不完全为透明色,会有些许灰色。一般情况下,这个使我们能接受的,如微信、QQ等都是状态栏颜色暗与下面的Toolbar的。

若是能通过Activity的Theme的colorPrimaryDark设状态栏颜色颜色设置,也是可行的,但是若你must实现透明额状态栏,也只能出狠招了。

Window window = activity.getWindow(); 

window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS|
| WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); 
window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN| View.SYSTEM_UI_FLAG_LAYOUT_STABLE);           window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Color.TRANSPARENT);    

setSystemUiVisibility这个可以参考Using Immersive Full-Screen Mode


这样的组合,让我们可以按照自己的需求来定制自己的状态栏,随后会开源自己封装的开源库工供大家参考。

参考文章

  1. Using Immersive Full-Screen Mode
  1. Android实现沉浸式状态栏

  2. Android-transulcent-status-bar

  3. Android状态栏合集-管你透不透明

内容概要:本文档详细介绍了基于MATLAB实现多目标差分进化(MODE)算法进行无人机三维路径规划的项目实例。项目旨在提升无人机在复杂三维环境中路径规划的精度、实时性、多目标协调处理能力、障碍物避让能力和路径平滑性。通过引入多目标差分进化算法,项目解决了传统路径规划算法在动态环境和多目标优化中的不足,实现了路径长度、飞行安全距离、能耗等多个目标的协调优化。文档涵盖了环境建模、路径编码、多目标优化策略、障碍物检测与避让、路径平滑处理等关键技术模块,并提供了部分MATLAB代码示例。 适合人群:具备一定编程基础,对无人机路径规划和多目标优化算法感兴趣的科研人员、工程师和研究生。 使用场景及目标:①适用于无人机在军事侦察、环境监测、灾害救援、物流运输、城市管理等领域的三维路径规划;②通过多目标差分进化算法,优化路径长度、飞行安全距离、能耗等多目标,提升无人机任务执行效率和安全性;③解决动态环境变化、实时路径调整和复杂障碍物避让等问题。 其他说明:项目采用模块化设计,便于集成不同的优化目标和动态环境因素,支持后续算法升级与功能扩展。通过系统实现和仿真实验验证,项目不仅提升了理论研究的实用价值,还为无人机智能自主飞行提供了技术基础。文档提供了详细的代码示例,有助于读者深入理解和实践该项目。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值