沉浸式状态栏

来源:互联网 发布:数据库系统的简易设计 编辑:程序博客网 时间:2024/06/08 10:47


Jianqiu's blog

Learn More

Android-transulcent-status-bar

透明状态栏适配.主要适用场景为一个Activity多个tab在不同状态栏模式下切换.

Github Demo 链接: StatusBarCompat

参考文章:

  1. 由沉浸式状态栏引发的血案
  2. Translucent System Bar 的最佳实践
  3. 该使用 fitsSystemWindows 了!
  4. Android 透明状态栏实现方案
  5. 更简单更全的material design状态栏

首先强调,对于状态栏的处理有两种不同的方式, 这里从Translucent System Bar 的最佳实践直接盗了两张图做对比~.

全屏( ContentView 可以进入状态栏)非全屏 ( ContentView 与状态栏分离, 状态栏直接着色)

先定义几个名词:

  1. 全屏模式: 左边图所示.
  2. 着色模式: 右边图所示.
  3. ContentViewactivity.findViewById(Window.ID_ANDROID_CONTENT) 获取的 View , 即 setContentView 方法所设置的 View, 实质为 FrameLayout.
  4. ContentParentContentView 的 parent , 实质为 LinearLayout.
  5. ChildViewContentView 的第一个子 View ,即布局文件中的 root layout .

再介绍一下相关的函数:

  1. fitsSystemWindows, 该属性可以设置是否为系统 View 预留出空间, 当设置为 true 时,会预留出状态栏的空间.
  2. ContentView, 实质为 ContentFrameLayout, 但是重写了 dispatchFitSystemWindows 方法, 所以对其设置 fitsSystemWindows 无效.
  3. ContentParent, 实质为 FitWindowsLinearLayout, 里面第一个 View 是 ViewStubCompat, 如果主题没有设置 title ,它就不会 inflate .第二个 View 就是 ContentView.
  4. requestApplyInsets(), 当窗口(Window)大小改变了,通知 View 去消费窗口的改变.
  5. FLAG_TRANSLUCENT_STATUS, 设置全屏的标志位, 此时界面可以延伸到状态栏.

5.0以上的处理:

自5.0引入 Material Design ,状态栏对开发者更加直接,可以直接调用 setStatusBarColor 来设置状态栏的颜色.

着色模式:

通过查看 setStatusBarColor() 方法的文档,发现在调用该方法时需要设置以下属性:

  1. 添加 FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS Flag(绘制系统栏).
  2. 清除 FLAG_TRANSLUCENT_STATUS Flag(透明状态栏).
  3. 调用 setStatusBarColor() 设置状态栏颜色.

全屏模式:

由于 5.0 以上为状态栏添加了一个阴影, 所以为全屏模式添加了是否隐藏状态栏阴影的方法.

  • 隐藏阴影

    1. 像着色模式一样添加 flag ,然后通过 setStatusBarColor() 设置颜色为透明.
    2. 通过 setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) 隐藏状态栏颜色.
  • 显示阴影

    1. 设置 FLAG_TRANSLUCENT_STATUS 来隐藏状态栏.
    2. 通过 setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE) 来恢复默认状态栏样式.

4.4-5.0的处理:

4.4-5.0因为没有直接的 API 可以调用,需要自己兼容处理.参考了网上的解决方法及结合我自己遇到的坑,最后想出的解决办法如下:

着色模式

  1. 向 DecorView 中添加一个 View, 高度为状态栏的高度(反射获取).
  2. 将 ChildView 的 marginTop 加上状态栏的高度,以此来模拟 fitsSystemWindows.
  3. 设置 ChildView 的 fitsSystemWindow 为 false, 不预留系统栏位置.
  4. 为 DecorView 设置一个 tag, 防止重复添加 View.

这里与其他地方不同的是:

  1. 向 ContentView 添加 View 在部分机型(华为)上没有效果.
  2. 向 ContentParent 上添加 View 会有一条黑线.
  3. 使用 marginTop 而不是 fitsSystemWindows 是因为无法在不重启 Activity 的情况下切换 root layout 的fitsSystemWindows属性, 即直接设置不会生效, 所以用 marginTop 来模拟.

全屏模式

  1. 设置 ChildView 的 fitsSystemWindow 为 false, 不预留系统栏位置.
  2. 如果在 ChildView 的 marginTop 中添加了状态栏的高度, 则移除.
  3. 设置 tag, 防止重复移除.

CollaspingToolbarLayout 
这个 support 包中的控件, 由于重写了 onApplySystemInsets() 方法, 按照我所理解的状态栏模式, 它在滑动时在两种模式中切换, 对此我的兼容方法就是让其处于 着色模式 下,在滑动时保持状态栏颜色不变. 当然有更好的解决办法, 但我这里为了方便调用(只需要传递 Activity 对象), 就用了比较简单的处理方法.

CollapsingToolbarLayout

support 包中提供的 CollapsingToolbarLayout, 在使用的时候大概的布局是这样的(参考 CheeseSquare ):

<CoordinatorLayout    android:fitsSystemWindows="true">    <AppBarLayout        android:fitsSystemWindows="true">        <CollapsingToolbarLayout            android:fitsSystemWindows="true">            <View                android:fitsSystemWindows="true"                 app:layout_collapseMode="parallax"/>          <ToolBar              app:layout_collapseMode="pin"/>       </CollapsingToolbarLayout>   <AppBarLayout/>   <View           app:layout_behavior="@string/appbar_scrolling_view_behavior"/></CoordinatorLayout>

在适配的时候主要遇到以下几个问题:

  1. 如果按照我上面介绍的方式来说, 它在显示图片的时候是 全屏模式 , 在显示 Toolbar 的时候是 着色模式.
  2. CollapsingToolbarLayout 的内部在 5.0 及以上的版本中通过 OnApplyWindowInsetsListener() 中获取的 Insets 对象, 在 Layout 的过程中将 View 向下偏移了, 所以它在 5.0 及以上系统中可以占据状态栏, 在 4.4 系统上则不能.
  3. 仿照 CheeseSquare 这个库中的写法, CollapsingToolbarLayout 需要设置 FitsSystemWindow 为 true, 而我在前面兼容 全屏模式和 着色模式 的时候, 都是设置 FitsSystemWindow 为 false. 同时目前我没找到方法在不重启 Activity 的情况下切换 FitsSystemWindow.

在参考了网上的文章后,最后决定通过以下方法来处理.

  • 4.4版本:

    1. 变为全屏模式,设置 View 的 fitsSystemWindow 为 false, 这一步可以使 CollapsingToolbarLayout 占据状态栏, Toolbar 也是.
    2. 改变 Toolbar 的高度, 加上状态栏的高度, 让 Toolbar 挡住状态栏位置, 同时为 Toolbar 添加 paddingTop , 这样就可以让 title 正常显示.
    3. 添加假的 StatusView 模拟状态栏颜色, 通过 AppBarLayout 的 OnOffsetChangedListener() 监听 AppBarLayout 的滑动, 使 StatusView 跟随 CollapsingToolbarLayout 的显示隐藏.
  • 5.0及以上版本:

    1. 变为全屏模式,设置 View 的 fitsSystemWindow 为 false, 这一步可以使 CollapsingToolbarLayout 占据状态栏, Toolbar 也是.
    2. 改变 Toolbar 的高度, 加上状态栏的高度, 让 Toolbar 挡住状态栏位置, 同时为 Toolbar 添加 paddingTop , 这样就可以让 title 正常显示. 这都和 4.4 一样.
    3. 为 CollapsingToolbarLayout 设置 OnApplyWindowInsetsListener() 使其正常 Layout ,因为此时 CollapsingToolbarLayout已经显示到状态栏了, 不需要在 Layout 过程中向下偏移, 但是此时collapsingToolbarLayout.setStatusBarScrimColor()也就无效了.
    4. 通过 AppBarLayout 的 OnOffsetChangedListener() 监听 AppBarLayout 的滑动, 利用 setStatusBarColor() 设置状态栏颜色即可.

关于博客和库

博客主要提供思路解析,因为博客的通知不及时,大家有问题有想法想交流时还请在 Github issues 页联系.

Android使用Fragment切换tab
Android Java代码实现滤镜
Jianqiu's blog

Learn More

Android-transulcent-status-bar

透明状态栏适配.主要适用场景为一个Activity多个tab在不同状态栏模式下切换.

Github Demo 链接: StatusBarCompat

参考文章:

  1. 由沉浸式状态栏引发的血案
  2. Translucent System Bar 的最佳实践
  3. 该使用 fitsSystemWindows 了!
  4. Android 透明状态栏实现方案
  5. 更简单更全的material design状态栏

首先强调,对于状态栏的处理有两种不同的方式, 这里从Translucent System Bar 的最佳实践直接盗了两张图做对比~.

全屏( ContentView 可以进入状态栏)非全屏 ( ContentView 与状态栏分离, 状态栏直接着色)

先定义几个名词:

  1. 全屏模式: 左边图所示.
  2. 着色模式: 右边图所示.
  3. ContentViewactivity.findViewById(Window.ID_ANDROID_CONTENT) 获取的 View , 即 setContentView 方法所设置的 View, 实质为 FrameLayout.
  4. ContentParentContentView 的 parent , 实质为 LinearLayout.
  5. ChildViewContentView 的第一个子 View ,即布局文件中的 root layout .

再介绍一下相关的函数:

  1. fitsSystemWindows, 该属性可以设置是否为系统 View 预留出空间, 当设置为 true 时,会预留出状态栏的空间.
  2. ContentView, 实质为 ContentFrameLayout, 但是重写了 dispatchFitSystemWindows 方法, 所以对其设置 fitsSystemWindows 无效.
  3. ContentParent, 实质为 FitWindowsLinearLayout, 里面第一个 View 是 ViewStubCompat, 如果主题没有设置 title ,它就不会 inflate .第二个 View 就是 ContentView.
  4. requestApplyInsets(), 当窗口(Window)大小改变了,通知 View 去消费窗口的改变.
  5. FLAG_TRANSLUCENT_STATUS, 设置全屏的标志位, 此时界面可以延伸到状态栏.

5.0以上的处理:

自5.0引入 Material Design ,状态栏对开发者更加直接,可以直接调用 setStatusBarColor 来设置状态栏的颜色.

着色模式:

通过查看 setStatusBarColor() 方法的文档,发现在调用该方法时需要设置以下属性:

  1. 添加 FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS Flag(绘制系统栏).
  2. 清除 FLAG_TRANSLUCENT_STATUS Flag(透明状态栏).
  3. 调用 setStatusBarColor() 设置状态栏颜色.

全屏模式:

由于 5.0 以上为状态栏添加了一个阴影, 所以为全屏模式添加了是否隐藏状态栏阴影的方法.

  • 隐藏阴影

    1. 像着色模式一样添加 flag ,然后通过 setStatusBarColor() 设置颜色为透明.
    2. 通过 setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) 隐藏状态栏颜色.
  • 显示阴影

    1. 设置 FLAG_TRANSLUCENT_STATUS 来隐藏状态栏.
    2. 通过 setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE) 来恢复默认状态栏样式.

4.4-5.0的处理:

4.4-5.0因为没有直接的 API 可以调用,需要自己兼容处理.参考了网上的解决方法及结合我自己遇到的坑,最后想出的解决办法如下:

着色模式

  1. 向 DecorView 中添加一个 View, 高度为状态栏的高度(反射获取).
  2. 将 ChildView 的 marginTop 加上状态栏的高度,以此来模拟 fitsSystemWindows.
  3. 设置 ChildView 的 fitsSystemWindow 为 false, 不预留系统栏位置.
  4. 为 DecorView 设置一个 tag, 防止重复添加 View.

这里与其他地方不同的是:

  1. 向 ContentView 添加 View 在部分机型(华为)上没有效果.
  2. 向 ContentParent 上添加 View 会有一条黑线.
  3. 使用 marginTop 而不是 fitsSystemWindows 是因为无法在不重启 Activity 的情况下切换 root layout 的fitsSystemWindows属性, 即直接设置不会生效, 所以用 marginTop 来模拟.

全屏模式

  1. 设置 ChildView 的 fitsSystemWindow 为 false, 不预留系统栏位置.
  2. 如果在 ChildView 的 marginTop 中添加了状态栏的高度, 则移除.
  3. 设置 tag, 防止重复移除.

CollaspingToolbarLayout 
这个 support 包中的控件, 由于重写了 onApplySystemInsets() 方法, 按照我所理解的状态栏模式, 它在滑动时在两种模式中切换, 对此我的兼容方法就是让其处于 着色模式 下,在滑动时保持状态栏颜色不变. 当然有更好的解决办法, 但我这里为了方便调用(只需要传递 Activity 对象), 就用了比较简单的处理方法.

CollapsingToolbarLayout

support 包中提供的 CollapsingToolbarLayout, 在使用的时候大概的布局是这样的(参考 CheeseSquare ):

<CoordinatorLayout    android:fitsSystemWindows="true">    <AppBarLayout        android:fitsSystemWindows="true">        <CollapsingToolbarLayout            android:fitsSystemWindows="true">            <View                android:fitsSystemWindows="true"                 app:layout_collapseMode="parallax"/>          <ToolBar              app:layout_collapseMode="pin"/>       </CollapsingToolbarLayout>   <AppBarLayout/>   <View           app:layout_behavior="@string/appbar_scrolling_view_behavior"/></CoordinatorLayout>

在适配的时候主要遇到以下几个问题:

  1. 如果按照我上面介绍的方式来说, 它在显示图片的时候是 全屏模式 , 在显示 Toolbar 的时候是 着色模式.
  2. CollapsingToolbarLayout 的内部在 5.0 及以上的版本中通过 OnApplyWindowInsetsListener() 中获取的 Insets 对象, 在 Layout 的过程中将 View 向下偏移了, 所以它在 5.0 及以上系统中可以占据状态栏, 在 4.4 系统上则不能.
  3. 仿照 CheeseSquare 这个库中的写法, CollapsingToolbarLayout 需要设置 FitsSystemWindow 为 true, 而我在前面兼容 全屏模式和 着色模式 的时候, 都是设置 FitsSystemWindow 为 false. 同时目前我没找到方法在不重启 Activity 的情况下切换 FitsSystemWindow.

在参考了网上的文章后,最后决定通过以下方法来处理.

  • 4.4版本:

    1. 变为全屏模式,设置 View 的 fitsSystemWindow 为 false, 这一步可以使 CollapsingToolbarLayout 占据状态栏, Toolbar 也是.
    2. 改变 Toolbar 的高度, 加上状态栏的高度, 让 Toolbar 挡住状态栏位置, 同时为 Toolbar 添加 paddingTop , 这样就可以让 title 正常显示.
    3. 添加假的 StatusView 模拟状态栏颜色, 通过 AppBarLayout 的 OnOffsetChangedListener() 监听 AppBarLayout 的滑动, 使 StatusView 跟随 CollapsingToolbarLayout 的显示隐藏.
  • 5.0及以上版本:

    1. 变为全屏模式,设置 View 的 fitsSystemWindow 为 false, 这一步可以使 CollapsingToolbarLayout 占据状态栏, Toolbar 也是.
    2. 改变 Toolbar 的高度, 加上状态栏的高度, 让 Toolbar 挡住状态栏位置, 同时为 Toolbar 添加 paddingTop , 这样就可以让 title 正常显示. 这都和 4.4 一样.
    3. 为 CollapsingToolbarLayout 设置 OnApplyWindowInsetsListener() 使其正常 Layout ,因为此时 CollapsingToolbarLayout已经显示到状态栏了, 不需要在 Layout 过程中向下偏移, 但是此时collapsingToolbarLayout.setStatusBarScrimColor()也就无效了.
    4. 通过 AppBarLayout 的 OnOffsetChangedListener() 监听 AppBarLayout 的滑动, 利用 setStatusBarColor() 设置状态栏颜色即可.

关于博客和库

博客主要提供思路解析,因为博客的通知不及时,大家有问题有想法想交流时还请在 Github issues 页联系.

Android使用Fragment切换tab
Android Java代码实现滤镜
阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 stm32Time stm32Time stm32time stm32time 通用time stm32time定时器 stm32定时器 谁特么2time stm32time STM32通用定时器 stm32time time定时器 STM32TIM STM32time stm32time Provisioning osProvisioning 通用定时器time 爆炎 pwm timepwm stm32pwm 删除索引的命令 查看视图创建语句 贪吃蛇代码 智能选择系统 智能选择系统 C++ C语言程序设计 二叉树叶子节点个数的递归算法 直接插入排序 直接插入排序的算法 贪吃蛇 使用ArrayList集合,对其添加10个不同的元素:1.使用add()方法将元素添加到ArrayL 万年历 万年历代码 简易通讯录 万年历c语言 淘宝 axure