Android 状态栏、底部导航栏的那些事

1. 需求

平常项目中,对顶部状态栏Status Bar,以及底部导航栏Navigation Bar的操作一般可以概括为以下几个场景:

  • 隐藏状态栏,导航栏,用户交互时(点击或滑动屏幕)出现(或不出现)。如欢迎、登录、全屏视频播放、阅读等界面使用。
  • 透明状态栏,图片或布局延伸到状态栏
  • 状态栏字体默认为白色,部分 app 修改为黑色
  • 变色状态栏,修改状态栏背景颜色

2. 相关API

我们沿着Android API的发展时间从头来说,另外,建议多看源码,这块内容,在源码注释里写的非常清楚

1. API 1
  • FLAG_FULLSCREEN

在Android 3.0及以前,StatusBar只能显示与隐藏,即全屏模式,通过WindowManager.LayoutParams.FLAG_FULLSCREEN来实现:

// 全屏布局且隐藏状态栏:
//4.4 上,顶部下滑,出现半透明状态栏,过一会儿状态栏消失
//4.1 上,顶部下滑,没反应
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

效果和通过主题样式的方式在styles.xml文件中设置属性android:windowFullscreen 是一样的,都是通过设置window的属性来影响窗口上修饰控件的显示

2. Android3.0 (API 11)

在Android3.0中,View添加了一个重要的方法:View.setSystemUiVisibility(int),用于控制包括Status Bar在内的一些窗口装饰元素的显示,通过窗口根View(DecorView)提供的方法来直接控制其上的窗口装饰元素System UI的显示和隐藏,并添加了

  • View.STATUS_BAR_VISIBLE
  • View.STATUS_BAR_HIDDEN :实测statusbar不会消失,仅隐藏statusbar 部分内容

两个Flag用于控制Status Bar的显示与隐藏,不过在4.0(API 14)中就废弃了。
一般是这么用的:

 View decorView = getWindow().getDecorView();
 int uiOptions =  View.STATUS_BAR_VISIBLE;
 decorView.setSystemUiVisibility(uiOptions);
3. Android4.0 (API 14)

在4.0(API 14)中,Andorid引入了Navigation Bar,并相应添加了一个flag:

  • SYSTEM_UI_FLAG_HIDE_NAVIGATION
    用来控制NavigationBar的显示,但是由于NavigationBar是非常重要的,因此只要有用户交互(例如点击屏幕),系统就会清除这个flag使NavigationBar就会再次出现。

  • View.STATUS_BAR_VISIBLE 改为 View.SYSTEM_UI_FLAG_VISIBLE

  • View.STATUS_BAR_HIDDEN 更名为 View.SYSTEM_UI_FLAG_LOW_PROFILE,该 flag 会同时影响 StatusBar 和 NavigationBar ,但不会使Status Bar和Navigation Bar消失,而是会使它们变暗,降低它们对视觉的干扰,使用户可以专注于应用的内容,但仍可响应用户的交互,当和它们的交互发生时,会退出Low Profile的状态。

4. Android 4.1 (API 16)

在4.1(API 16)中,对Status Bar和Navigation Bar的控制进一步增强。

  • View.SYSTEM_UI_FLAG_FULLSCREEN: 这个标志与WindowManager.LayoutParams.FLAG_FULLSCREEN有相同的视觉效果(全屏布局且隐藏状态栏),但在系统手势交互后两者在4.4以上有不同表现
    —— 4.1 上顶部下滑没反应
    —— 4.4 上顶部下滑重新出现状态栏,不透明,且挤压 Activity 的布局。
  • View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN: Activity全屏显示,但状态栏不会被隐藏覆盖,状态栏依然可见,Activity顶端布局部分会被状态遮住。此flag与透明状态栏一起使用,就可以实现现在不少app实现的状态栏透明,图片或布局延伸到状态栏的效果了,不过这块需要针对不同API级别进行适配,主要因为状态栏透明在不同的API上显示不尽相同。

  • View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION: 使内容布局到NavigationBar之下。

  • View.SYSTEM_UI_FLAG_LAYOUT_STABLE: 在使用View.SYSTEM_UI_FLAG_FULLSCREEN|View.SYSTEM_UI_FLAG_HIDE_NAVIGATION时,Status Bar和Navigation Bar都会隐藏,Activity的UI占据整个屏幕,当System UI再次显示时,应用程序窗口会被重新Resize和Layout,为System UI腾出空间。而这个标签就是解决这个问题,它需要与上面提到的两个layout的flag配合使用,控制当Status Bar或Navigation Bar显示或隐藏时,Activity的UI是被重新Resize和Layout,防止因系统栏的显示和隐藏导致内容区域发生变化。

5. Android 4.4 (API 19)

由于对Status Bar,和Navigation Bar 都是很重要的功能,尤其是Navigation Bar,对于只有虚拟按键的手机,如果隐藏掉Navigation Bar,连切换程序都做不到,所以,当用户和手机有任何交互的时候都会强制清除掉隐藏状态栏和导航栏的flag,重新显示Status Bar和Navigation Bar,而且不会再次隐藏消失,一些情况下这可能就不是我们想要的效果,比如读书,看视频,所以在4.4(API 19)中引入了沉浸模式。

  • View.SYSTEM_UI_FLAG_IMMERSIVE

该标志是SYSTEM_UI_FLAG_HIDE_NAVIGATION修饰符,也只有和它结合使用时才有效果,并且它只有一个作用,单独使用 SYSTEM_UI_FLAG_HIDE_NAVIGATION ,导航栏消失,不过系统将在任何用户交互时强制清除SYSTEM_UI_FLAG_HIDE_NAVIGATION,导航栏再次出现。添加 View.SYSTEM_UI_FLAG_IMMERSIVE 后,普通交互时导航栏不会出现,只有在系统交付手势时(如底部向上滑动时),导航栏才会出现,不过也不会再次隐藏。

  • View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY

使用此标志创建沉浸式体验,它是SYSTEM_UI_FLAG_FULLSCREEN和SYSTEM_UI_FLAG_HIDE_NAVIGATION的修饰符,因此只有与其中一个或两个标志组合使用时才会产生效果。该标志和View.SYSTEM_UI_FLAG_IMMERSIVE的不同之处在于当用户在系统手势操作后,状态栏或导航栏出现,但短时间后会自动再次隐藏。

该标志和 View.SYSTEM_UI_FLAG_FULLSCREEN 配合使用:状态栏隐藏在沉浸模式下,但可以通过系统手势暂时显示出来,比如从屏幕顶部滑动。这些暂时的系统栏将覆盖应用程序的内容,可能有一定程度的透明度,并会在短时间后自动隐藏。

该标志和 SYSTEM_UI_FLAG_HIDE_NAVIGATION 配合使用:导航栏隐藏在沉浸模式下,底部向上滑动出现,过一段时间自动隐藏。

除了控制System UI的显示和隐藏外,还可以使它们变成透明的,在4.4(API 19)中还引入了

  • FLAG_TRANSLUCENT_STATUS

这个属于Window flag,也可以在主题中设置android: windowTranslucentStatus设置该属性,当使用这个flag时SYSTEM_UI_FLAG_LAYOUT_STABLE和SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN会被自动添加,同时,设置FLAG_TRANSLUCENT_STATUS也会影响到StatusBar的背景色,但并没有固定的表现:

—— 对于7.0以上的机型,设置此flage会使得StatusBar半透明
—— 对于6.0以上的机型,设置此flage会使得StatusBar完全透明
—— 对于5.x的机型,大部分是使背景色半透明,小米和魅族以及其它少数机型会全透明
—— 对于4.4的机型,小米和魅族是透明色,而其它系统上就只是黑色到透明色的渐变。

  • FLAG_TRANSLUCENT_NAVIGATION

Window flag,也可以在主题中设置android: windowTranslucentNavigation设置该属性,当使用这这个flag时SYSTEM_UI_FLAG_LAYOUT_STABLE和SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION会被自动添加。同时,设置FLAG_TRANSLUCENT_STATUS也会影响到 NavigationBar 的背景色,效果与 FLAG_TRANSLUCENT_STATUS 相同。

6. Android 5.0
  • 主题里通过colorPrimaryDark来指定 StatusBar 背景色

  • 可以调用 window.setStatusBarColor(@ColorInt int color) 来修改状态栏颜色,但是让这个方法生效有一个前提条件:你必须给window添加FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS并且取消FLAG_TRANSLUCENT_STATUS

7. Android 6.0

在Android6以后,我们只要给SystemUI加上SYSTEM_UI_FLAG_LIGHT_STATUS_BAR这个flag,就可以让字体和图标变为黑色。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容