零、摘要

Android全屏透明状态栏的文章已经有不少了,也有开源的库甚至,本文着重讲具体实施背后遇到的那些坑。

一、为什么

现有很多app在Android机器上状态栏的体验并不好,有一道灰色的条。比如手机QQ在7.0 vivo上的效果:


图1.1

我们期望的效果是:

  1. 全屏,app界面的布局延伸到状态栏
  2. 没有顶部的阴影
  3. 状态栏背景色为透明或者跟随app界面颜色
  4. 状态栏字体和icon颜色可以根据界面颜色深浅设置为浅或深,以避免都为浅色或深色而看不见状态栏字体和icon。
    如下图所示效果:


    图1.2

    图中左边状态栏背景是透明,字体是浅色,右边状态栏背景是白色,字体是深色。

二、怎么做

为了达到一中所说的1,2,3和4的效果,先看下Android在api上的支持。

2.1 Android4.4

可以实现状态栏背景色透明或其它颜色,但是做不到效果中的4。
实现步骤:

  1. 通过配置values-19文件夹下的style属性
true

或者activity里设置

getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
  1. 状态栏透明后,可以再自己定义一个状态栏高度的view,设置其颜色就相当于设置状态栏背景色了。可以参考其它状态栏的文章,不再赘述。
    这样得到的效果:


    图2.1

然而,试了几款机器,发现并不是所有机型都能达到这个效果,比如vivo的机器上就不行,没有全屏:


图2.2

看效果是全屏的flag没起作用,因为官方文档说,设置了WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS flag后,会自动设置另外两个属性:

When this flag is enabled for a window, it automatically sets the system UI visibility flags SYSTEM_UI_FLAG_LAYOUT_STABLE and SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN.

手动把这两个属性设置后,布局倒是延伸到状态栏了,不过状态栏也不见直接隐藏了,有兴趣的可以研究下vivo的4.4机器上能不能做到。

再比如三星机器上,系统会默认给系统状态栏加点阴影:


图2.3

再比如oppo r7的coloros 2.1系统上能达到理想效果,也有oppo r7效果不行,状态栏是黑色,可能和coloros的版本有关系吧。

注:如果在android高版本设置了4.4的这个属性,通常会是开篇说的手q那种效果。

2.2 Android5.0和Android5.1

可以直接实现状态栏背景颜色,不用像4.4上需要自己去搞自定义view,当然也可以给状态栏设置一个透明颜色,然后继续用自定义view的方案也是没问题的。但是和4.4一样,没法改变状态栏字体和icon颜色。
按照官方文档:

Sets the color of the status bar to color. For this to take effect, the window must be drawing the system bar backgrounds with FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS and FLAG_TRANSLUCENT_STATUS must not be set.If color is not opaque, consider setting SYSTEM_UI_FLAG_LAYOUT_STABLE and SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN.

代码如下:

getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);getWindow().setStatusBarColor(getResources().getColor(android.R.color.holo_red_light));

如果不是不透明,也就是有透明度的,把这两个也设置上:

getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);

具体效果和机型适配不再测试。。。

2.3 Android6.0及以上

到了这里,终于可以完全实现我们要的效果了。因为Api23增加了一个属性SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,可以设置状态栏字体和icon是深颜色还是浅颜色。设置状态栏背景色的api还是和Android5.0上一样。代码差不多就这样:

if(Build.VERSION.SDK_INT >= LOLLIPOP) {            int uiFlags = View.SYSTEM_UI_FLAG_LAYOUT_STABLE;            uiFlags |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);            getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);             getWindow().setStatusBarColor(Color.TRANSPARENT);             if(Build.VERSION.SDK_INT >= M) {                uiFlags = setStatusBarDarkFont(uiFlags);            }             getWindow().getDecorView().setSystemUiVisibility(uiFlags);        }private int setStatusBarDarkFont(int uiFlags) {        if (isSystemSetDarkFontSupport() && mFontDarkMode) {            return uiFlags | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;        } else {            return uiFlags;        }    }

这样设置后我们的app界面就从状态栏顶部开始布局了,根据需要有些界面可以直接在状态栏的位置就显示,有些可能需要从状态栏下沿才开始显示,具体效果可参见图1.2中的左和右,针对后者,我们还可以像4.4一样,自己搞一个假的view占位,也可以用其它不少的方法,具体可参见这篇文章:
http://www.jianshu.com/p/2a884e211a62
本文建议还是自己搞一个假的view占位,原因后面会说。
这样就万事大吉了?如果是的话那就不叫Android了,接下来说说那些坑吧,主要针对Android6.0及以上的系统。

三、坑

3.1 闪的问题

通过2.3中的api设置后,发现很多机器在切换activity时,状态栏会闪一下,解决方案,需要在Activity的style属性里添加:

        true

可以在values-v23文件夹下加。不过加了这个会有些影响:

  1. 对activity生命周期的影响,Activity A上启动了一个加上此属性的Activity B,A不会走onStop,当B销毁时,A不会走onStart。如果基类Activity或某些Activity在onStart里有些特殊逻辑处理需要注意下。
  2. 对transition动画可能会有影响,比如我遇到的是通过ActivityOptionsCompat.makeSceneTransitionAnimation做动画的界面,在onBackPressed activity时会黑屏一下,我是在onBackPressed直接finish掉不做动画,不调super.onBackPressed。

3.2 DialogFragment问题

全屏DialogFragment时,发现状态栏顶部还是和开篇说的QQ那样的效果,代码里怎么调都还是那结果,差点放弃。。最后发现,在布局里调用就好了,原因就懒得去找了。

false        @color/thirtyalphablack        true

再特别提一句,meizu flyme上不要通过这种方式,否则状态栏和布局之间会有一条灰线,不过魅族不加这些参数全屏DialogFragment也显示正常。

3.3 左右滑动问题

2.3中说到,尽量自己搞个占位的view来让需要的界面从状态栏下面开始展示,这样一方面是好控制,另一方面是遇到,如果是通过setStatusBarColor或者设置ContentView的padding来的话,左右滑动时,状态栏不会跟着走,这样的效果:


1513524906862.jpg

这个问题如果不通过占位方式的话,感觉应该也可以解决,有兴趣的可以研究下。

3.4 特例品牌魅族

魅族从FlymeOS4就开始提供了设置状态字体深色或浅色的api了,这里建议判断下是否大于等于Flyme OS4,是的话使用其自己的api,使用系统的反而有问题,好像会导致切换字体颜色时闪。

3.5 特例品牌小米

小米也一样,很早就搞了自己的私有API来设置状态栏字体颜色深浅,不过在其开发版7.7.13后又恢复到原生api了,私有API没有了效果。但是miui的开发版和发布版并没有明确的对应关系,所以系统的和小米的都得调,不过根据MIUI9的发布日志,可以推测MIUI9以后都是开发版7.7.13之后了,所以可以判断下如果是大于等于miui6小于miui9之间,两种api都调,大于等于miui9的话则只需调用系统的。参考链接:
http://www.miui.com/thread-8946673-1-1.html
摘要:

大家好,在本周开发版公测后,MIUI 对状态栏字符颜色的逻辑做了一次调整:1. 在 Android 6.0 以前,Android 没有方法可以实现「状态栏黑色字符」效果,因此 MIUI 自己做了一个接口;2. 在 Android 6.0 及以上版本,Android 提供了标准的方法实现「状态栏黑色字符」效果,但这个方法和 MIUI 的方法产生了冲突,所以当开发者使用 Android 标准方法时,没有出现预期的效果,这给很多开发者都造成了困扰,尤其是海外开发者。基于以上背景,我们决定兼容 Android 的方法,舍弃 MIUI 的自己的实现方法。这个改动将会在 7.7.13 公测开发版开始生效(内测版本已生效),之后随稳定版外发。非常抱歉给各位带来麻烦,但长远来看,兼容 Android 的标准,减少了开发者的适配成本,对整个 Android 生态也更为有利。

http://www.miui.com/thread-8944996-1-1.html
摘要

MIUI 9 第一个内测版本已于7月27日上午10:00进行推送。首批适配机型:小米手机6、红米Note 4X-高通版(其他机型将分批陆续进行内测)。已申请 MIUI 9 内测报名并通过审核的米粉,请注意阅读以下升级方式: 1. 小米手机6:7.7.20开发版/体验版米粉,可通过 OTA 更新增量包方式,升级至 MIUI 9。 2. 红米Note 4X-高通版:7.7.13开发版、7.7.22体验版,可通过 OTA 更新增量包方式,升级至 MIUI 9。

3.6 全屏切换问题
切换到全屏时,如果隐藏状态栏了,那么这种情况下就不要调用上述函数。

四、总结

  1. 上述实现可以放基类Activity的onResume里,然后添加些可以被子类重写的函数,比如状态栏字体颜色深浅,界面展示是可以和状态栏重合还是得从状态栏下沿开始等。
  2. Android真是坑,API好难用!

五、感谢

最感谢的是这篇文章及其代码了:
http://www.jianshu.com/p/2a884e211a62

更多相关文章

  1. Android实时滤镜实现
  2. android TextView实现滚动显示效果
  3. Android时光轴实现淘宝物流信息浏览效果
  4. Android(安卓)Studio快捷键设置之实现原eclipse中ctrl+m的全屏的
  5. Android开发之ListView页眉页脚效果VS android背景渐变
  6. 风格化的 Toggle Buttons
  7. [置顶] Android(安卓)实现书籍翻页效果----升级篇
  8. android 欢迎界面翻页效果,仿微信第一次登陆介绍翻页界面
  9. Android监听ScrollView的滚动事件

随机推荐

  1. 百度广告外推代发找谁
  2. 找高手百度广告外推收录代发
  3. 外推代发首页
  4. 微博代发外推
  5. 手撸golang GO与微服务 Saga模式之2
  6. leetcode331 验证二叉树的前序序列化 gol
  7. GoCenter 助力 Golang 全速前进
  8. 初探Kubernetes Pod
  9. 李智桦谈《 DevOps 三十六计》| 有福利
  10. Jenkinfile入门:Pipeline as code