透明系统栏及沉浸模式的总结-创新互联

关于所谓的“沉浸式”,我有许多话要说,因为这个东西实在是折磨了我许多的时间。实现的方式有许多,兼容性问题也不少。官方文档也让我感到也有些云里雾里。那些“长得很相似”的Flag,适用情况很接近的设置方法,让我不得不一个个测试,然而却一次次推翻。模拟器上测试;真机上测试;4.4版本上的测试;5.0后版本的测试;有导航栏手机上的测试;老掉牙手机上的测试。总而言之,这个东西的探索让我深刻地体会到android系统兼容性问题的麻烦。

目前创新互联公司已为上1000家的企业提供了网站建设、域名、网页空间、网站托管、企业网站设计、牟平网站维护等服务,公司将坚持客户导向、应用为本的策略,正道将秉承"和谐、参与、激情"的文化,与客户和合作伙伴齐心协力一起成长,共同发展。

当你功能开发占据10%,而处理兼容性问题占据90%的时候。你不得不思考这样一个问题:“兼容性真的有那么重要吗?”撇开这个问题,以投入和产出的角度显然是不太划得来的,但是收获的角度:我学习了解了View的加载机制、DecorView在不同版本上的实现以及发展、养成了遇到问题第一时间查阅官方文档的习惯。

关键词

1、系统栏Systembar(包括状态栏Statusbar,导航栏Navigationbar)

2、内容主体暂且可以理解为Window中除了Systembar以外的窗口

实现原理:

1、将SystemBar透明化

2、根据不同情况决定内容主体是否需要延伸到SystemBar下方

一、将SystemBar透明化

主题中设置属性:

true

true

代码中设置Flag:

getWindow().setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);//透明状态栏

getWindow().setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION,WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);//透明导航栏

5.0后设置:

    getWindow().setStatusBarColor(Color.TRANSPARENT);

     getWindow().setNavigationBarColor(Color.TRANSPARENT);

二、根据不同情况决定内容主体是否需要延伸到SystemBar下

主题中设置属性:

   true

代码中设置Flag:

getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);

FLAG_TRANSLUCENT_STATUS单独使状态栏透明化

FLAG_TRANSLUCENT_NAVIGATION单独使导航栏透明化

4.1后更多选项的设置:

ViewdecorView = getWindow().getDecorView();

decorView.setSystemUiVisibility(Flag);

Flag的值需要了解以下几种情况:

1、SYSTEM_UI_FLAG_FULLSCREEN

2、SYSTEM_UI_FLAG_HIDE_NAVIGATION

3、SYSTEM_UI_FLAG_IMMERSIVE

4、SYSTEM_UI_FLAG_IMMERSIVE_STICKY

5、SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN

6、SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION

7、SYSTEM_UI_FLAG_LAYOUT_STABLE

8、SYSTEM_UI_FLAG_LIGHT_STATUS_BAR

SYSTEM_UI_FLAG_FULLSCREEN

隐藏状态栏,主体向上偏移,但在手动下拉会重新显示状态栏并清除该flag。

View.SYSTEM_UI_FLAG_FULLSCREEN |View.SYSTEM_UI_FLAG_LAYOUT_STABLE

限制主体位置保持不变,状态栏留白

SYSTEM_UI_FLAG_HIDE_NAVIGATION

隐藏导航栏,主体向下偏移,由于导航栏太重要了,所以只要和Activity进行任何交互都会重新显示导航栏,并清除该flag和SYSTEM_UI_FLAG_FULLSCREEN。

View.SYSTEM_UI_FLAG_HIDE_NAVIGATION| View.SYSTEM_UI_FLAG_LAYOUT_STABLE

限制主体位置保持不变,导航栏留白

SYSTEM_UI_FLAG_LAYOUT_STABLE

保持内容主体位置不变,不随着Systembar的隐藏显示而偏移

SYSTEM_UI_FLAG_IMMERSIVE

沉浸模式:只能和SYSTEM_UI_FLAG_HIDE_NAVIGATION结合使用。简单交互不会重新显示导航栏

SYSTEM_UI_FLAG_IMMERSIVE_STICKY

沉浸模式:只能和SYSTEM_UI_FLAG_FULLSCREEN或SYSTEM_UI_FLAG_HIDE_NAVIGATION结合使用。

下拉状态栏位置可以短暂显示状态栏和导航栏,然后再次隐藏。

SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN

主体占据全部屏幕,但不隐藏状态栏,这里的layout可以理解为内容主体

SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION

主体占据全部屏幕,但不隐藏导航栏,这里的layout可以理解为内容主体

SYSTEM_UI_FLAG_LAYOUT_STABLE

这个Flag确实有点难以理解,唯一读懂的是在各种flag切换的时候能保持内容主体的稳定性。如果你不想flag变换的时候内容主体上下偏移,就需要设置SYSTEM_UI_FLAG_LAYOUT_STABLE。

View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR

浅色状态栏模式:对应于图标变深色,防止浅色背景导致状态栏看不清,不设置是深色模式

实践验证过程:

View decorView =getWindow().getDecorView();

decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);

状态栏不会隐藏,仍占据着位置,但内容可以侵入状态栏下方

decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN);

View.SYSTEM_UI_FLAG_FULLSCREEN 状态栏下滑,主体布局就会下降一个状态栏的高度,很突兀

View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN状态栏下滑,主体布局位置不变化

View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN| View.SYSTEM_UI_FLAG_LAYOUT_STABLE;

这个和单独使用View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN区别在哪儿,还没发现

andriod系统提供了一些透明状态栏/导航栏的主题以供使用:

    true

    true

    @null

SYSTEM_UI_FLAG_HIDE_NAVIGATION |SYSTEM_UI_FLAG_IMMERSIVE

SYSTEM_UI_FLAG_IMMERSIVE必须与SYSTEM_UI_FLAG_HIDE_NAVIGATION 结合使用才有意义

加上SYSTEM_UI_FLAG_IMMERSIVE,则导航栏在隐藏后不会因与界面的交互而呼出。

类似于看视频时进入全屏模式。

SYSTEM_UI_FLAG_FULLSCREEN |SYSTEM_UI_FLAG_HIDE_NAVIGATION

进入全屏模式,但用户与界面进行最简单的交互都会重新显示状态栏,导航栏

View.SYSTEM_UI_FLAG_HIDE_NAVIGATION|View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_IMMERSIVE

进入全屏模式,用户交互会重新显示状态栏,导航栏,不会再隐藏

View.SYSTEM_UI_FLAG_HIDE_NAVIGATION| View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY

进入全屏模式,用户交互会短暂显示状态栏,导航栏,然后再隐藏

总结:

比较简洁的透明状态栏的做法是:

方法一:适合4.1及以上

if(Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP){

    View window =getWindow().getDecorView();

    window.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN

           |View.SYSTEM_UI_FLAG_LAYOUT_STABLE);

    getWindow().setStatusBarColor(Color.TRANSPARENT);

}

对于不需要延伸至状态栏下方的组件,使用android:fitsSystemWindows="true"将进行设置即可。本质上是添加一个状态栏高度的paddingTop属性,所以android:layout_height属性不要使用"250dp"这种固定数值,可以使用"wrap_content"结合android:minHeight="250dp"的方式。

方法二:适合4.1及以上

同方法一:

true

      true

结合android:fitsSystemWindows属性

方法三:适合4.0及以下的版本

true

     @null

或者代码中:

getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);

方法三使用android:fitsSystemWindows是无效的。所以我的做法是给需要向下偏移的组件设置一个paddingTop的值,并在v21,v19等不同版本设置不同的值做兼容(源码可知statusbar高度是25dp)。这里默认所有手机平台都是25dp。

网上的做法是选择性填充一个View,该View的Height是动态获取的statusbar的高度。这个做法兼容了不同厂商自己定制的UI使用不同于Google官方25dp的状态栏高度的情况。如红米note2是20dp,魅族note5是22dp。

另外对于setFlags方法,同样有单独设置状态栏和导航栏的方法:

    getWindow().setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION,WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);

    getWindow().setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

    对于这两个属性而言,android:fitsSystemWindows有效,但在设置了FLAG_TRANSLUCENT_NAVIGATION的时候,内容主体也会向下偏移一个导航栏的高度,可见这里的android:fitsSystemWindows指的是SystemBar,而不仅仅是StatusBar。

方法四:适合于5.0以后

结合Design Support库中的CoordinatorLayout+AppBarLayout+CollapsingToolbarLayout,并且结合使用fitsSystemWindows。这也是我第一个接触的方法。需要注意的是fitsSystemWindows属性在CoordinatorLayout中有不同的实现,fitsSystemWindows=“true”反而表示是否出现在状态栏下方。知道真相的我眼泪掉下来。

方法在Fragment中会有问题(例如在FragmentTabhost中使用),使用replace切换则正常,使用add切换的Fragment则fitSystemWindow失效,必须调用onCreate才能生效,我滴个天~~~~最后我只能放弃fitSystemWindow,使用方法三中的设置paddingTop的方法。

方法五:使用第三方框架

SystemBarTint     https://github.com/jgilfelt/SystemBarTint

StatusBarUtil        https://github.com/laobie/StatusBarUtil

备注:

使用Theme的方式相比代码中设置的优势:

1、更易于维护,并且不易出错

2、更顺畅的UI过渡,因为系统在初始化主Activity之前就已经知道了渲染UI所需要的相关信息

参考资料:

Managing the System UI

https://developer.android.com/training/system-ui/index.html

SystemBarTint

https://github.com/jgilfelt/SystemBarTint

StatusBarUtil

https://github.com/laobie/StatusBarUtil

另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。


网页名称:透明系统栏及沉浸模式的总结-创新互联
本文地址:http://hbruida.cn/article/cscesd.html