2.2 沉浸式交互组件
准确地说,“沉浸式状态栏”应该叫“透明栏”,英文名是“Translucent Bars”,它是Android 4.4开始定义的设计规范。简单来说,就是在打开软件的时候通知栏和软件顶部颜色融为一体,这样可以使软件与系统更加融合。
但现在一提到沉浸式状态栏,第一个浮现在脑海里的词就是“碎片化”(Android平台的诞生为手机智能化的普及立下汗马功劳,但Android因开源、设备繁多、品牌众多、版本割裂和分辨率不统一等导致了Android的碎片化,这些都逐渐成为Android系统发展的障碍,碎片化严重不仅造成Android系统混乱,也导致Android应用的隐性开发成本提高)。碎片化是让Android开发者很头疼的问题,相信没有哪位开发者会不喜欢“write once, run anywhere”的感觉,碎片化让大家不得不耗费精力去校验代码在各个系统版本、各个机型上是否有效。
2.2.1 碎片化导致沉浸式适配困难
众所周知,Android原生系统由于本地化支持以及一些组件服务合规等原因,并没有得到推广使用,反而像MIUI、EMUI等基于Android原生系统进行了二次开发的国产ROM,因加入了对中国用户使用习惯等的支持而得到了广泛应用。因此,各个手机厂商统统通过修改Android原生系统,推出了自己的UI ROM。然而,由于UI的制定标准不同、API不同,这给国内的应用开发者造成了很大的伤害,尤其是沉浸式体验这一块。各家UI的制定标准都超出了同期Android原生系统的API标准,因此开发者在适配沉浸式时,需要一个一个系统、一个一个版本地做兼容性适配,工作量较大,难度也比较大。
2.2.2 Android官方沉浸式状态栏方式
在Android系统中,针对StatusBar(状态栏)的操作,一直都在不断改善,并且表现越来越好。在Android 4.4版本以下,我们可以对StatusBar和NavigationBar进行显示和隐藏操作,但是直到Android 4.4版本,我们才实现了真正意义上的沉浸式状态栏。
从Android 4.4到Android 7.1,关于沉浸式大概可以分成如下3个阶段。
Android 4.4(API 19)~Android 5.0(API 21):这个阶段可以实现沉浸式,但是表现得不是很好,实现方式为:通过FLAG_TRANSLUCENT_STATUS设置状态栏为透明和全屏模式,然后添加一个与StatusBar一样大小的View,并将View的background设置为我们想要的颜色,从而实现了沉浸式。
具体方法如下:
1. Window win = activity.getWindow(); 2. WindowManager.LayoutParams winParams = win.getAttributes(); 3. final int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; 4. winParams.flags |= bits; 5. win.setAttributes(winParams);
Android 5.0(API 21)以上的版本:在Android 5.0中,新加入了一个重要的属性android:statusBarColor(对应的方法为setStatusBarColor),通过这个方法我们就可以轻松地实现沉浸式。也就是说,从Android 5.0开始,系统才真正地支持了沉浸式。
具体方法如下:
1. Window window = activity.getWindow(); 2. window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS 3. | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); 4. int vis = window.getDecorView().getSystemUiVisibility(); 5. vis |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; 6. vis |= View.SYSTEM_UI_FLAG_LAYOUT_STABLE; 7. window.getDecorView().setSystemUiVisibility(vis); 8. window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_ BACKGROUNDS); 9. window.setStatusBarColor("yourColor");
Android 6.0(API 23)以上版本:其实Android 6.0以上版本的实现方式和Android 5.0以上版本的实现方式是一样的,这个阶段可以改变状态栏的绘制模式,可以显示白色或浅黑色的内容和图标。
设置方法同Android 5.0,但是可以设置状态栏文字颜色:
1. View decorView = activity.getWindow().getDecorView(); 2. if(decorView != null){ 3. int vis = decorView.getSystemUiVisibility(); 4. if(mode == DARK_MODE){ 5. vis |= SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 6. } else { 7. vis &= ~SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 8. } 9. decorView.setSystemUiVisibility(vis); 10. }
2.2.3 主流厂商的沉浸式方式简介
由于普遍国内厂商的UI对Android系统进行了大量定制,因此Android原生API设置系统沉浸式的方法在这些UI上无效。如果需要适配这些UI,则需要对这些系统的UI进行深入分析,找出系统的沉浸式设置方法,然后进行沉浸式适配。
下面是国内主流厂商的沉浸式适配方法,通过这些设置方法,可以对国内主流厂商ROM进行沉浸式状态适配。
1.MIUI适配
MIUI在V9版本或者Android 6.0版本之后,使用的是系统方法。然而在V9之前,使用的是MIUI自定义的方法,需要通过反射方式对状态栏的颜色进行设置:
1. Window window = activity.getWindow(); 2. try { 3. int darkModeFlag = Reflector.on("android.view.MiuiWindowManager $LayoutParams") 4. .field("EXTRA_FLAG_STATUS_BAR_DARK_MODE") 5. .get(); 6. boolean isDark = mode == DARK_MODE; 7. int colorMode = isDark ? darkModeFlag : 0; 8. Reflector.on(window).call("setExtraFlags", colorMode, darkModeFlag); 9. } catch(Exception e){ 10. e.printStackTrace(); 11. }
2.OPPO适配
OPPO在Android 5.0以前使用的是系统方法,而在Android 5.0之后的Color OS中,则是通过以下方法设置状态栏颜色的:
1. Window window = activity.getWindow(); 2. if(window != null){ 3. try { 4. Class buildClass = Class.forName("com.color.os.ColorBuild"); 5. if(buildClass == null){ 6. return; 7. } 8. Method method = buildClass.getDeclaredMethod("getColor OSVERSION"); 9. if(method == null){ 10. return; 11. } 12. method.setAccessible(true); 13. int i =(Integer)method.invoke(null); 14. if(i < 6){ 15. return; 16. } 17. Class statusBar = Class.forName("com.color.view. ColorStatusbarTintUtil"); 18. Field field = statusBar.getDeclaredField("SYSTEM_UI_FLAG_ OP_STATUS_BAR_TINT"); 19. field.setAccessible(true); 20. int values = field.getInt(null); 21. int vi; 22. if(mode != DARK_MODE){ 23. vi = ~values & window.getDecorView().getSystemUiVisibility(); 24. } else { 25. vi = values | window.getDecorView().getSystemUiVisibility(); 26. } 27. window.getDecorView().setSystemUiVisibility(vi); 28. 29. } catch(Exception e){ 30. e.printStackTrace(); 31. } 32. }
3.魅族适配
魅族在Android 6.0以后使用系统方法进行沉浸式文字颜色的设置,但是在Android 6.0之前,则需要通过以下方法进行设置:
1. Window window = activity.getWindow(); 2. if(window != null){ 3. try { 4. WindowManager.LayoutParams e = window.getAttributes(); 5. Field darkFlag = WindowManager.LayoutParams.class. getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON"); 6. Field meizuFlags = WindowManager.LayoutParams.class. getDeclaredField("meizuFlags"); 7. darkFlag.setAccessible(true); 8. meizuFlags.setAccessible(true); 9. int bit = darkFlag.getInt(null); 10. int value = meizuFlags.getInt(e); 11. if(mode == DARK_MODE){ 12. value |= bit; 13. } else { 14. value &= ~bit; 15. } 16. meizuFlags.setInt(e, value); 17. window.setAttributes(e); 18. } catch(Exception e){ 19. e.printStackTrace(); 20. } 21. }