Day20-沉浸式状态栏

概念

  1. 全屏模式
  2. 变色状态栏模式
  3. 背景全屏+变色状态栏模式
  4. 图片全屏+变色状态栏模式
  5. ContentView: activity.findViewById(Window.ID_ANDROID_CONTENT) 获取的 View , 即 setContentView 方法所设置的 View, 实质为 FrameLayout.
  6. ContentParent: ContentView 的 parent , 实质为 LinearLayout.
  7. ChildView: ContentView 的第一个子 View ,即布局文件中的 layout.

相关函数

  1. fitsSystemWindows, 该属性可以设置是否为系统 View 预留出空间, 当设置为 true 时,会预留出状态栏的空间.
  2. ContentView, 实质为 ContentFrameLayout, 但是它的 dispatchFitSystemWindows 重写了 fitsSystemWindows 方法, 所以对其设置 fitsSystemWindows 无效.
  3. ContentParent, 实质为 FitWindowsLinearLayout, 里面第一个 View 是 ViewStubCompat, 如果主题没有设置 title ,它就不会 inflate .第二个 View 就是 ContentView.
  4. setClipToPadding: 保持padding, true为保持

概述

  • 先看一下四张图
  • 4.4.4默认
  • 4.4.4 去掉 ActionBar
  • 5.0 默认
  • 5.0去掉 ActionBar
  • DecorView结构:
    --DecorView == extends FrameLayout
    ------View (4.4在这自定义个伪状态栏)
    ------LinearLayout
    ----------ViewStub
    ----------FrameLayout
    --------------FitWindowsLinearLayout(style设置了不带toolbar)
    ------------------ViewStubCompat
    ------------------ContentFrameLayout == ContentView
    --------------ActionBarOverlayLayout(style设置了带toolbar)
    ------------------ContentFrameLayout == ContentView
    ------------------ActionBarContainer
    ------view(5.0才有的statusbarbackground, 系统级, getChildAt找不到,得finsViewById找)
    ------view(5.0才有的navigationbackground, 系统级, getChildAt找不到,得finsViewById找)
总结一下:
可以看出 DecorView 作为根布局, 持有一个 LinearLayout,
* 5.0在LinearLayout下持有四个View, 两个系统级的 View(StatusBar 和 Navigation), 和两个 FrameLayout, 一个是ViewStub, 一个是给了 ContentFraneLayout + ActionBar(当设置不需要 ActionBar 时, 是ViewStubCompat).
* 4.4在LinearLayout下只有两个View, 可以推出5.0可以直接```setStatusBarColor```是因为多了这俩view, 那我们只要在 LinearLayout 中插入一个 view 就可以学着5.0的样子, 让ContentFraneLayout下移.

4.4 以下放弃

4.4.4 kitcat

谷歌在 Android 的 Window 属性里添加了可以让状态栏和导航栏被穿透(ContentView覆盖StatusBar)的属性

WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION
  • 建议使用代码设置(国产ROM有迷之bug)
activity.getWindow().setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

全屏模式

  1. 给 Window 添加 FLAG_TRANSLUCENT_STATUS
  2. 给 ContentView 的子 view 设置 setFitsSystemWindows

FLAG_TRANSLUCENT_STATUS 效果:
自动设置了 SYSTEM_UI_FLAG_LAYOUT_STABLE 和 SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 让 ContentView 满屏

变色状态栏模式

  1. 给 Window 添加 FLAG_TRANSLUCENT_STATUS
  2. 给 DecorView 添加一个伪状态栏
  3. 给 ContentView 的子 view 全部设置 setFitsSystemWindows

背景全屏+变色状态栏模式

  1. 给 Window 添加 FLAG_TRANSLUCENT_STATUS
  2. 给 ContentView 的子 view 全部设置 fitsSystemWindows, 空出StatusBar的高给伪状态栏
  3. 给 ContentView 添加一个伪 StatusBar

图片全屏+变色状态栏模式

  1. 给 Window 添加 FLAG_TRANSLUCENT_STATUS
  2. 给 ContentView 添加一个伪 StatusBar
  3. 如果是 Imageview 浮在布局上, 即下一个布局也怼上了 StatusBar, 需要手动给后续布局加 topMargin

5.0 LOLLIPOP

比起 4.4, 不需要 FLAG_TRANSLUCENT_STATUS, 因为谷歌又�提供了setStatusBarColor, 不过默认 StatusBar 的会添加半透明灰条, 所以还得改下 StatusBar 的颜色为透明

全屏模式:

  1. 给 Window 设置FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS 让 ContentView 怼到顶
  2. 给 Window 设置setStatusBarColor 修改透明颜色

变色状态栏模式

  1. 给 Window 设置FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS 让 ContentView 怼到顶
  2. 给 windiw 设置setStatusBarColor 修改指定颜色

背景全屏+变色状态栏模式

  1. 给 Window 设置FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS 让 ContentView 怼到顶
  2. 给 Window 设置setStatusBarColor 修改透明颜色
  3. 给 ContentView 的子 view 全部设置 fitsSystemWindows, 空出StatusBar的高给伪状态栏
  4. 给 ContentView 添加伪 StatusBar

图片全屏+变色状态栏模式(3,4步和4.4处理方式一样)

  1. 给 StatusBar 设置透明
  2. 给 DecorView 设置 SYSTEM_UI_FLAG_LAYOUT_STABLE 和 SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN

是不是很眼熟, 对, 就是FLAG_TRANSLUCENT_STATUS自动附带的设置, 不过5.0 可以直接改 StatusBar 的颜色了, 不需要 TRANSLUCENT_STATUS

  1. 给 ContentView 添加伪 StatusBar
  2. 如果是 Imageview 浮在布局上, 即下一个布局也怼上了 StatusBar, 需要手动给后续布局加 topMargin

特殊需求:

如果一个 StatusBar 可变色的 acitivy, 加入图片全屏 + 变色StatusBar 的 fragment/或 StatusBar 联动的 fragment 也就是当 StatusBar 和 fragment 一体, 建议�此 fragment 替换为 activity, 虽然可以�实现, 但是需要页面绘制两遍不说, 二是 StatusBar 是在页面出现后加入的. 如果项目一开始就有这个需求, 那么在全部fragment�的xml中加状态栏高的view

fragment中的沉浸式

思路:
如果需要 StatusBar 和 fragment 一起联动, 需要多两步

  1. 在fragment的xml中添加一个view(StatusBar_view_height).
  2. xml中设置StatusBar_view_height的值
 - <dimen name="StatusBar_view_height">0dp</dimen>
v19 - <dimen name="StatusBar_view_height">25dp</dimen>
vw820dp - <dimen name="activity_horizontal_margin">64dp</dimen>

抽屉

和activity一个处理思路

实现

Tips:
自定义Theme 运行时是先找自己版本号对应的styles, 如果没有那就去找无版本号的styles里的. 所以一定要在无版本号的styles里写上自定义Theme, 哪怕里面没有东西, 不然直接崩
推荐通过代码修改, 单纯的依靠theme也可以, 但是不如代码直观, 也不便于控制

1. theme中需要做的铺垫

a. 通过代码里设置

  1. 去掉自带actionBar
    <item name="WindowActionBar">false</item>
    <item name="android:WindowActionBar">false</item>
    <item name="WindowNoTitle">true</item>
    
  2. 去掉打开时先加载一闪而过的 空白背景+默认StatusBar 的默认背景
    <item name="android:WindowIsTranslucent">true</item>
    <item name="android:WindowBackground">@android:color/transparent</item>
    

2. 代码:

https://github.com/laobie/StatusBarUtil

踩坑

  • fitsSystemWindows
    到底在哪儿设置
    • 在 theme 中设置是对整个 Window, 导致Toast文字内容 上浮, 建议在代码里设置
    • 当前布局的最外层和 SystemWindow 接触, 所以给最外层的 view 设置 fitsSystemWindows 才能有效果
  • WindowTranslucentStatus
    到底设置true还是false
    <item name="android:WindowTranslucentStatus">true</item>
    <item name="android:WindowTranslucentNavigation">true</item>
    <!--Android 5.x开始需要把颜色设置透明,否则导航栏会呈现系统默认的浅灰色-->
    <item name="android:StatusBarColor">@android:color/transparent</item>
    
    • 华为7.0在theme被设置成这样时, StatusBar被摸过后就半透明的挂在头上了, 模拟器则是能直接看到半透明的StatusBar
    <item name="android:WindowTranslucentStatus">false</item>
    <item name="android:WindowTranslucentNavigation">true</item>
    <!--Android 5.x开始需要把颜色设置透明,否则导航栏会呈现系统默认的浅灰色-->
    <item name="android:StatusBarColor">@android:color/transparent</item>
    
    • 华为7.0在theme被设置成这样时, StatusBar怎么摸都没事儿, 模拟器也是看不见StatusBar的

TODO

参考

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

推荐阅读更多精彩内容