程序员人生 网站导航

Android 必知必会 - 动态切换着色模式和全屏模式

栏目:综合技术时间:2016-11-09 16:09:46

如果移动端访问不佳,欢迎使用 ==> Github 版

通过代码动态切换页面的着色模式全屏模式,兼容 Android 4.4 +

本文假定读者已了解着色模式和全屏模式(沉醉模式)。

背景

公司的 APP 设计图唯一 iOS 版的,对 Android 平台,它整体算是着色模式,但是在个人页面是全屏模式(沉醉模式),实现设计图时,我使用的是1个 Activity + 4个 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 的根布局backgroundpaddingTop 来动态切换『着色模式』和全屏模式。

实际上,这类情况下的『着色模式』是在全屏模式下摹拟出来的,其实不是真正意义上的着色模式。

着色模式:

  • android:background="@color/title_bar"
  • paddingTop = statusHeight

全屏模式:

  • paddingTop = 0

对 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

<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" > <!-- ...... 4个 ImageView --> </LinearLayout> </LinearLayout>

MainActivity.java

//响应底部对应的 ImageView 被点击的事件,i 为 0⑶ private void setSelect(int i) { resetBg();//重置背景 FragmentManager fm = getSupportFragmentManager(); FragmentTransaction ft = fm.beginTransaction(); hideFragment(ft);//隐藏已显示的 Fragment switch (i) { case 0: setStatusBar(false);//着色模式 //... 显示 Fragment_a break; case 1: setStatusBar(false);//着色模式 //... 显示 Fragment_b break; case 2: setStatusBar(false);//着色模式 //... 显示 Fragment_c break; case 3: setStatusBar(true);//全屏模式 //... 显示 Fragment_d break; } ft.commit(); } //修改当前 Activity 的显示模式,hideStatusBarBackground :true 全屏模式,false 着色模式 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); } } } //get StatusBar Height 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 ) 的情况,我这里并没有使用网上1些教程:向 DecorView 中添加1个高度为状态栏的高度 View,也就没有黑线的问题,而是通过修改根布局的背风景和根布局的 PaddingTop 来摹拟着色模式。

注意,本实验仅针对1个 Activity 包括多个 Fragment 且需要动态修改显示模式的情况。操作进程中页面并没有配合使用 ActionBar ,使用的主题是 Theme.AppCompat.Light.NoActionBar ,不肯定是不是会成心想不到的效果,请在配合 ActionBar 时先进行测试或参考文末的相干资料。

如果有甚么问题或建议,欢迎和我交换。

相干资料:

  • Android-transulcent-status-bar
  • 由沉醉式状态栏引发的血案

PS:你可以通过下面的方式和我联系

  • 微博:cafeting
  • Github: likfe
  • CSDN:他叫自己Mr.张
------分隔线----------------------------
------分隔线----------------------------

最新技术推荐