通过代码动态切换页面的着色模式和全屏模式,兼容 Android 4.4 +
。
本文假设读者已经了解着色模式和全屏模式(沉浸模式)。
背景
公司的 APP 设计图仅有 iOS 版的,对于 Android 平台,它整体算是着色模式,但是在个人页面是全屏模式(沉浸模式),实现设计图时,我使用的是一个 Activity
+ 四个 Fragment
实现的。
下面直接上效果图:
iOS 效果图 |
Android 4.4 + |
Android 5.0 + |
|
|
|
实现
从 Android 4.4
起,Window 新增了 WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
的 Flag ,而从 Android 5.0
起,Window 又新增了 setStatusBarColor()
方法,可以直接修改状态栏的颜色。
对于 Android 4.4 + ( >= 4.4 且 < 5.0 )
这种情况下,我们启用 4.4 新增的半透明状态栏,通过修改当前 Activity 的根布局的 background
和 paddingTop
来动态切换『着色模式』和全屏模式。
实际上,这种情况下的『着色模式』是在全屏模式下模拟出来的,并不是真正意义上的着色模式。
着色模式:
android:background="@color/title_bar"
paddingTop = statusHeight
全屏模式:
对于 Android 5.0 + ( >= 5.0 )
这种情况下,我们修改Window 对应的 Flag,然后直接设置状态栏的颜色即可。
全屏模式:
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.setStatusBarColor(Color.TRANSPARENT);
着色模式:
window.setStatusBarColor(getResources().getColor(R.color.title_bar));
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
关键代码
activity_main.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/title_bar" android:orientation="vertical" >
<FrameLayout android:id="@+id/main_fl" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:background="@color/white" /> <LinearLayout android:id="@+id/main_bottom" android:layout_width="match_parent" android:layout_height="50dp" android:background="@color/white" android:clickable="false" android:orientation="horizontal" > </LinearLayout> </LinearLayout>
|
MainActivity.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
| private void setSelect(int i) { resetBg(); FragmentManager fm = getSupportFragmentManager(); FragmentTransaction ft = fm.beginTransaction(); hideFragment(ft); switch (i) { case 0: setStatusBar(false); break; case 1: setStatusBar(false); break; case 2: setStatusBar(false); break; case 3: setStatusBar(true); break; } ft.commit(); }
private void setStatusBar(boolean hideStatusBarBackground) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { Window window = getWindow(); window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); if (hideStatusBarBackground) { window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); } else { window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE); }
ViewGroup mContentView = (ViewGroup) window.findViewById(Window.ID_ANDROID_CONTENT); View mChildView = mContentView.getChildAt(0); if (mChildView != null) { if (hideStatusBarBackground) { mChildView.setPadding( mChildView.getPaddingLeft(), 0, mChildView.getPaddingRight(), mChildView.getPaddingBottom() ); } else { int statusHeight = getStatusBarHeight(this); mChildView.setPadding( mChildView.getPaddingLeft(), statusHeight, mChildView.getPaddingRight(), mChildView.getPaddingBottom() ); } } } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); if (hideStatusBarBackground) { window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); window.setStatusBarColor(Color.TRANSPARENT); window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); } else { window.setStatusBarColor(getResources().getColor(R.color.title_bar)); window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE); } } }
public static int getStatusBarHeight(Activity activity) { Rect frame = new Rect(); activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame); return frame.top; }
|
总结和回顾
对于 Android 5.0 + ( >= 5.0 ) 的情况很容易懂,毕竟可以直接设置状态栏的颜色。对于 Android 4.4 + ( >= 4.4 且 < 5.0 ) 的情况,我这里并没有使用网上一些教程:向 DecorView 中添加一个高度为状态栏的高度 View,也就没有黑线的问题,而是通过修改根布局的背景色和根布局的 PaddingTop 来模拟着色模式。
注意,本实验仅针对一个 Activity 包含多个 Fragment 且需要动态修改显示模式的情况。操作过程中页面并没有配合使用 ActionBar ,使用的主题是 Theme.AppCompat.Light.NoActionBar
,不确定是否会有意想不到的效果,请在配合 ActionBar 时先进行测试或者参考文末的相关资料。
如果有什么问题或建议,欢迎和我交流。
相关资料:
PS:你可以通过下面的方式和我联系