android view设置按钮颜色_Android关于StatusBar(状态栏)总结

bfe39236a60ad25031551374242e6a8b.png

从事Android开发的同学了解,对于StatusBar的控制,并没有ios那样好,需要对Android不同的系统版本进行适配,同时也需要对小米,魅族等国产手机单独适配,想要如ios那般好的体验,并没有那么简单。

随着Google 对Android系统不断的支持,关于对StatusBar(状态栏)的操作,一直不断改善,并且表现越来越好,在Android4.4 以下,我们可以对StatusBar和 NavigationBar进行显示和隐藏操作。但是直到Android4.4,我们才能真正意义上的实现沉浸式状态栏。从Android4.4 到现在(Android 9),关于沉浸式大概可以分成三个阶段:

(1) Android4.4(API 19) - Android 5.0(API 21): 这个阶段可以实现沉浸式,但是表现得还不是很好,实现方式为: 通过FLAGTRANSLUCENTSTATUS设置状态栏为透明并且为全屏模式,然后通过添加一个与StatusBar 一样大小的View,将View 的 background 设置为我们想要的颜色,从而来实现沉浸式。

(2) Android 5.0(API 21)以上版本: 在Android 5.0的时候,加入了一个重要的属性和方法 android:statusBarColor (对应方法为 setStatusBarColor),通过这个方法我们就可以轻松实现沉浸式。也就是说,从Android5.0开始,系统才真正的支持沉浸式。

(3) Android 6.0(API 23)以上版本:其实Android6.0以上的实现方式和Android 5.0 +是一样,为什么要将它归为一个单独重要的阶段呢?是因为从Android 6.0(API 23)开始,我们可以改状态栏的绘制模式,可以显示白色或浅黑色的内容和图标(除了魅族手机,魅族自家有做源码更改,6.0以下就能实现)。

这三个阶段的Android上API版本混乱,各种Flag林立。再加上各大厂商的定制化可谓是火上浇油,让安卓开发者异常头疼。

1.沉浸式三个阶段使用

1.1 Android4.0-Android5.0设置沉浸体验

在android4.4及以上版本中为setSystemUiVisibility()方法引入了一个新的flag:SYSTEMUIFLAGIMMERSIVE,它可以使你的app实现真正意义上的全屏体验。当SYSTEMUIFLAGIMMERSIVE、SYSTEMUIFLAGHIDENAVIGATION 和SYSTEMUIFLAG_FULLSCREEN三个flag一起使用的时候,可以隐藏状态栏与导航栏,同时让你的app可以捕捉到用户的所有触摸屏事件。从Android4.4以上版本才是真正的可以设置沉浸式体验,但也仅仅是操作状态栏和导航栏的显示与隐藏。

1.1.1 FLAGTRANSLUCENTSTATUS

当沉浸式全屏模式启用的时候,你的activity会继续接受各类的触摸事件。用户可以通过在状态栏与导航栏原来区域的边缘向内滑动让系统栏重新显示。这个操作清空了SYSTEMUIFLAGHIDENAVIGATION和SYSTEMUIFLAGFULLSCREEN,如果没有两个标志的话,系统栏重新变得可见。如果设置了两个标签的话,这个操作同时也触发了View.OnSystemUiVisibilityChangeListener。然而, 如果你想让系统栏在一段时间后自动隐藏的话,你应该使用SYSTEMUIFLAGIMMERSIVE_STICKY标签。

6fc10a8fa02b074c104a5b2cc4f4cb64.png

在上图中:

  • 非沉浸模式 —— 展示了应用进入沉浸模式之前的状态。也展示了设置IMMERSIVE标签后用户滑动展示系统栏的状态。用户滑动后,SYSTEMUIFLAGHIDENAVIGATIONSYSTEMUIFLAG_FULLSCREEN就会被清除,系统栏就会重新显示并保持可见。请注意,最好的方式就是让所有的UI控件与系统栏的显示隐藏保持同步,这样可以减少屏幕显示所处的状态,同时提供了更无缝平滑的用户体验。因此所有的UI控件跟随系统栏一同显示。一旦应用进入了沉浸模式,UI控件也跟随着系统栏一同隐藏。为了确保UI的可见性与系统栏保持一致,我们需要一个监听器View.OnSystemUiVisibilityChangeListener来监听系统栏的变化。这在下一节中将详细讲解。
  • 提示气泡——第一次进入沉浸模式时,系统将会显示一个提示气泡,提示用户如何再让系统栏显示出来。请注意,如果为了测试你想强制显示提示气泡,你可以先将应用设为沉浸模式,然后按下电源键进入锁屏模式,并在5秒中之后打开屏幕。
  • 沉浸模式—— 这张图展示了隐藏了系统栏和其他UI控件的状态。你可以设置IMMERSIVE和IMMERSIVE_STICKY来进入这个状态。
  • 粘性标签——这就是你设置了IMMERSIVE_STICKY标签时的UI状态,用户会向内滑动以展示系统栏。半透明的系统栏会临时的进行显示,一段时间后自动隐藏。滑动的操作并不会清空任何标签,也不会触发系统UI可见性的监听器,因为暂时显示的导航栏并不被认为是一种可见的状态。

注意,immersive类的标签只有在与SYSTEMUIFLAGHIDENAVIGATION,SYSTEMUIFLAG_FULLSCREEN中一个或两个一起使用的时候才会生效。你可以只使用其中的一个,但是一般情况下你需要同时隐藏状态栏和导航栏以达到沉浸的效果。

1.1.2 两种使用这个属性的方式:

在使用时候,我们通常需要考虑的是状态栏一值显示在顶部而不会隐藏或者被遮挡(其他app情况如:读书app或者是游戏app则需要隐藏顶部状态栏),所以只需要通过代码设置FLAGTRANSLUCENTSTATU

activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

通过主题theme设置属性windowTranslucentStatus:

<style name="Theme" parent="Theme.Design.Light.NoActionBar">
        <item name="android:windowTranslucentStatus">true</item>
</style>

有个问题,我们的标题栏和状态栏重叠了,相当于整个布局上移了StatusBar 的高度。

为了让标题栏回到原来的位置并且适应标题栏的颜色,我们在标题栏的上方添加一个大小和StatusBar大小一样假的状态栏View,View 的BackgroundColor 可以自己设置成标题栏一样的颜色也可以是其他颜色,这个View起到一个占位的作用。这个时候,标题栏就会下移StatusBar的高度,回到正常的位置。

通过设置paddingTop重新绘制标题栏高度代码如下:

View statusBarView = mDecorView.findViewById(IMMERSION_STATUS_BAR_VIEW);
        if (statusBarView == null) {
            statusBarView = new View(mActivity);
            FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
                    mBarConfig.getStatusBarHeight());
            params.gravity = Gravity.TOP;
            statusBarView.setLayoutParams(params);
            statusBarView.setVisibility(View.VISIBLE);
            statusBarView.setId(IMMERSION_STATUS_BAR_VIEW);
            mDecorView.addView(statusBarView);
        }
        if (mBarParams.statusBarColorEnabled) {
            statusBarView.setBackgroundColor(ColorUtils.blendARGB(mBarParams.statusBarColor,
                    mBarParams.statusBarColorTransform, mBarParams.statusBarAlpha));
        } else {
            statusBarView.setBackgroundColor(ColorUtils.blendARGB(mBarParams.statusBarColor,
                    Color.TRANSPARENT, mBarParams.statusBarAlpha));
        }

通过以上就可以实现Android 4.4 上的沉浸式状态栏。

总结:Android4.4-Android5.0的步骤就是为window添加FLAGTRANSLUCENTSTATUS的Flag,然后添加一个假的状态栏,通过上述方法设置的沉浸式在Android4.4-Android5.0之间的效果,状态栏顶部是有一个黑色阴影渐变,在5.0版本版本以上被修复了。 如果是一张图片沉浸到状态栏则不需要设置这个假的状态栏,只需要设置,FLAGTRANSLUCENTSTATUS就OK。并且在Android4.4-Android5.0是没有提供改变状态颜色的属性,所以只能通过新增加一个假的状态栏方式改变背景颜色。

1.2 Android5.0以上设置状态栏背景颜色

从Android 5.0开始,Google 推出了全新的设计规范 Material Design,并且原生控件就可以实现一些炫酷的UI动效。从这个版本开始,google 加入了一个比较重要的方法setStatusBarColor (对应属性:android:statusBarColor),通过这个方法,可以很轻松地实现沉浸式状态栏。方法如下

/**
     * Sets the color of the status bar to {@code color}.
     *
     * For this to take effect,
     * the window must be drawing the system bar backgrounds with
     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} and
     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS} must not be set.
     *
     * If {@code color} is not opaque, consider setting
     * {@link android.view.View#SYSTEM_UI_FLAG_LAYOUT_STABLE} and
     * {@link android.view.View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}.
     * <p>
     * The transitionName for the view background will be "android:status:background".
     * </p>
     */
public abstract void setStatusBarColor(@ColorInt int color);  

注释,想要这个方法生效,必须还要配合一个Flag一起使用,必须设置FLAGDRAWSSYSTEMBARBACKGROUNDS,并且不能设置FLAGTRANSLUCENTSTATUS(Android 4.4才用这个),所以和4.4互斥不能共用。所以Android5.0以上可以设置状态栏和导航栏背景颜色,但还不能改变状态栏和导航栏图标和字色

1.2.1 FLAGDRAWSSYSTEMBARBACKGROUNDS属性

解释:设置了FLAGDRAWSSYSTEMBARBACKGROUNDS,表明Window会负责系统bar的background 绘制,绘制透明背景的系统bar(状态栏和导航栏),然后用getStatusBarColor()和getNavigationBarColor()的颜色填充相应的区域。这就是Android 5.0 以上实现沉浸式导航栏的原理。

getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
    //注意要清除 FLAG_TRANSLUCENT_STATUS flag
    getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
    getWindow().setStatusBarColor(getResources().getColor(android.R.color.holo_red_light));

如果在开发的时候是通过设置主题的方式设置,则需要在values-v21文件夹下添加如下主题,达到兼容目的

<style name="Theme" parent="Theme.Design.Light.NoActionBar">  
        <item name="android:windowTranslucentStatus">false</item>
        <item name="android:windowDrawsSystemBarBackgrounds">true</item>
        <item name="android:statusBarColor">@android:color/holo_red_light</item>
</style>

1.2.2 图片延伸到状态栏

在Android 5.0 使图片延伸到状态栏,只需设置windowTranslucentStatus,将 statusBarColor 设置为透明即可。 主题方式设置如下:

<style name="ImageTranslucentTheme" parent="Theme.AppCompat.DayNight.NoActionBar">  
        <item name="android:windowTranslucentNavigation">true</item>
        <item name="android:windowTranslucentStatus">true</item>
        <!-- 设置statusBarColor 为透明-->
        <item name="android:statusBarColor">@android:color/transparent</item>
</style>

注意的是:在开发过程中,使用代码设置windowTranslucentStatus需要通过版本号的判断兼容 Android5.0以下和Android 5.0以上。

1.3 Android 6.0 +实现状态栏字色和图标浅黑色

使用Android6.0以下版本沉浸式的时候会遇到一个问题,那就是Android 系统状态栏的字色和图标颜色为白色,当状态栏颜色接近浅色的时候,状态栏上的内容就看不清了。Android 6.0 新添加了一个属性来解决这个问题,属性是SYSTEMUIFLAGLIGHTSTATUS_BAR,可以设置状态栏字色和图标浅黑色。

1.3.1 SYSTEMUIFLAGLIGHTSTATUS_BAR

为setSystemUiVisibility(int)方法添加的Flag,请求status bar 绘制模式,它可以兼容亮色背景的status bar 。要在设置了FLAGDRAWSSYSTEMBARBACKGROUNDSflag ,同时清除了FLAGTRANSLUCENTSTATUSflag 才会生效。

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {  
            getWindow().getDecorView().setSystemUiVisibility(
                    View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN|View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
}

还可以在主题中使用属性,并且该主题需要放在values-v23文件夹下相应Android6.0以上才能生效:

<style name="Theme" parent="Theme.Design.Light.NoActionBar">  
        <item name="android:windowTranslucentStatus">false</item>
        <item name="android:windowDrawsSystemBarBackgrounds">true</item>
        <item name="android:statusBarColor">@android:color/holo_red_light</item>
        <!-- Android 6.0以上 状态栏字色和图标为浅黑色-->
        <item name="android:windowLightStatusBar">true</item>
</style>

上述关于状态栏的适配以及Google 对系统配置的支持的一些总结,不当之处,多多指教。

一般来说,状态栏场景实现归纳如下:

d5ee4a1558fa7470a554d5a457568c98.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值