在Android 4.4之前,我们的应用没发改变手机的状态栏的颜色,当我们打开应用的时候,在屏幕的顶部有一天黑色的状态栏,和应用的风格非常不协调,为提供更好的界面交互,google在Android 4.4以后提供了设置沉浸式状态栏的方法,对于沉浸式状态栏的这个面工资存在争议,实际的效果其实是透明的状态栏,然后再状态栏的位置显示我们的自定义的颜色,通常为应用的actionabar的颜色。或者是将应用的整体的一张图片也占据到状态栏中,类似qq一样。
接下来我们来看看实现都需要那些配置
1. 首先需要再values的style中加入如下代码
<!-- Base application theme. --> <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> </style> <style name="NoActionBarTheme" parent="Theme.AppCompat.Light.NoActionBar"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> </style>
AppTheme.Main是我们要设置给activity的主题,它应该继承于AppTheme.NoActionBar,然后
我们在values-v19加入配置 如下
<style name="TranslucentTheme" parent="Theme.AppCompat.Light.NoActionBar"> <item name="android:windowTranslucentStatus">true</item> <item name="android:windowTranslucentNavigation">true</item> </style>
AppTheme.Main是我们要设置给activity的主题,它应该继承于AppTheme.NoActionBar,然后
我们在values-v21加入配置 如下
<style name="TranslucentTheme" parent="Theme.AppCompat.Light.NoActionBar"> <item name="android:windowTranslucentStatus">false</item> <item name="android:windowTranslucentNavigation">true</item> <!--Android 5.x开始需要把颜色设置透明,否则导航栏会呈现系统默认的浅灰色--> <item name="android:statusBarColor">@android:color/transparent</item> </style>配置文件写好了 那么我们需要开始撸代码了 首先我们写一个封装好工具类文件 代码如下
public class StatusBarUtils { private Activity mActivity; //状态栏颜色 private int mColor = -1; //状态栏drawble private Drawable mDrawable; //是否是最外层布局是 DrawerLayout 的侧滑菜单 private boolean mIsDrawerLayout; //是否包含 ActionBar private boolean mIsActionBar; //侧滑菜单页面的内容视图 private int mContentResourseIdInDrawer; public StatusBarUtils(Activity activity) { mActivity = activity; } public static StatusBarUtils with(Activity activity) { return new StatusBarUtils(activity); } public int getColor() { return mColor; } public StatusBarUtils setColor(int color) { mColor = color; return this; } public Drawable getDrawable() { return mDrawable; } public StatusBarUtils setDrawable(Drawable drawable) { mDrawable = drawable; return this; } public boolean isDrawerLayout() { return mIsDrawerLayout; } public boolean isActionBar() { return mIsActionBar; } public StatusBarUtils setIsActionBar(boolean actionBar) { mIsActionBar = actionBar; return this; } /** * 是否是最外层布局为 DrawerLayout 的侧滑菜单 * * @param drawerLayout 是否最外层布局为 DrawerLayout * @param contentId 内容视图的 id * @return */ public StatusBarUtils setDrawerLayoutContentId(boolean drawerLayout, int contentId) { mIsDrawerLayout = drawerLayout; mContentResourseIdInDrawer = contentId; return this; } public void init() { fullScreen(mActivity); if (mColor != -1) { //设置了状态栏颜色 addStatusViewWithColor(mActivity, mColor); } if (mDrawable != null) { //设置了状态栏 drawble,例如渐变色 addStatusViewWithDrawble(mActivity, mDrawable); } if (isDrawerLayout()) { //未设置 fitsSystemWindows 且是侧滑菜单,需要设置 fitsSystemWindows 以解决 4.4 上侧滑菜单上方白条问题 fitsSystemWindows(mActivity); } if (isActionBar()) { //要增加内容视图的 paddingTop,否则内容被 ActionBar 遮盖 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { ViewGroup rootView = (ViewGroup) mActivity.getWindow().getDecorView().findViewById(android.R.id.content); rootView.setPadding(0, getStatusBarHeight(mActivity) + getActionBarHeight(mActivity), 0, 0); } } } /** * 去除 ActionBar 阴影 */ public StatusBarUtils clearActionBarShadow() { if (Build.VERSION.SDK_INT >= 21) { ActionBar supportActionBar = ((AppCompatActivity) mActivity).getSupportActionBar(); if (supportActionBar != null) { supportActionBar.setElevation(0); } } return this; } /** * 设置页面最外层布局 FitsSystemWindows 属性 * * @param activity */ private void fitsSystemWindows(Activity activity) { ViewGroup contentFrameLayout = (ViewGroup) activity.findViewById(android.R.id.content); View parentView = contentFrameLayout.getChildAt(0); if (parentView != null && Build.VERSION.SDK_INT >= 14) { parentView.setFitsSystemWindows(true); //布局预留状态栏高度的 padding if (parentView instanceof DrawerLayout) { DrawerLayout drawer = (DrawerLayout) parentView; //将主页面顶部延伸至status bar;虽默认为false,但经测试,DrawerLayout需显示设置 drawer.setClipToPadding(false); } } } /** * 利用反射获取状态栏高度 * * @return */ public static int getStatusBarHeight(Activity activity) { int result = 0; //获取状态栏高度的资源id int resourceId = activity.getResources().getIdentifier("status_bar_height", "dimen", "android"); if (resourceId > 0) { result = activity.getResources().getDimensionPixelSize(resourceId); } Log.e("getStatusBarHeight", result + ""); return result; } /** * 获得 ActionBar 的高度 * * @param context * @return */ public static int getActionBarHeight(Context context) { int result = 0; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { TypedValue tv = new TypedValue(); context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true); result = TypedValue.complexToDimensionPixelSize(tv.data, context.getResources().getDisplayMetrics()); } return result; } /** * 添加状态栏占位视图 * * @param activity */ private void addStatusViewWithColor(Activity activity, int color) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { if (isDrawerLayout()) { //要在内容布局增加状态栏,否则会盖在侧滑菜单上 ViewGroup rootView = (ViewGroup) activity.findViewById(android.R.id.content); //DrawerLayout 则需要在第一个子视图即内容试图中添加padding View parentView = rootView.getChildAt(0); LinearLayout linearLayout = new LinearLayout(activity); linearLayout.setOrientation(LinearLayout.VERTICAL); View statusBarView = new View(activity); ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity)); statusBarView.setBackgroundColor(color); //添加占位状态栏到线性布局中 linearLayout.addView(statusBarView, lp); //侧滑菜单 DrawerLayout drawer = (DrawerLayout) parentView; //内容视图 View content = activity.findViewById(mContentResourseIdInDrawer); //将内容视图从 DrawerLayout 中移除 drawer.removeView(content); //添加内容视图 linearLayout.addView(content, content.getLayoutParams()); //将带有占位状态栏的新的内容视图设置给 DrawerLayout drawer.addView(linearLayout, 0); } else { //设置 paddingTop ViewGroup rootView = (ViewGroup) mActivity.getWindow().getDecorView().findViewById(android.R.id.content); rootView.setPadding(0, getStatusBarHeight(mActivity), 0, 0); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { //直接设置状态栏颜色 activity.getWindow().setStatusBarColor(color); } else { //增加占位状态栏 ViewGroup decorView = (ViewGroup) mActivity.getWindow().getDecorView(); View statusBarView = new View(activity); ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity)); statusBarView.setBackgroundColor(color); decorView.addView(statusBarView, lp); } } } } /** * 添加状态栏占位视图 * * @param activity */ private void addStatusViewWithDrawble(Activity activity, Drawable drawable) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { //占位状态栏 View statusBarView = new View(activity); ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity)); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { statusBarView.setBackground(drawable); } else { statusBarView.setBackgroundDrawable(drawable); } if (isDrawerLayout()) { //要在内容布局增加状态栏,否则会盖在侧滑菜单上 ViewGroup rootView = (ViewGroup) activity.findViewById(android.R.id.content); //DrawerLayout 则需要在第一个子视图即内容试图中添加padding View parentView = rootView.getChildAt(0); LinearLayout linearLayout = new LinearLayout(activity); linearLayout.setOrientation(LinearLayout.VERTICAL); //添加占位状态栏到线性布局中 linearLayout.addView(statusBarView, lp); //侧滑菜单 DrawerLayout drawer = (DrawerLayout) parentView; //内容视图 View content = activity.findViewById(mContentResourseIdInDrawer); //将内容视图从 DrawerLayout 中移除 drawer.removeView(content); //添加内容视图 linearLayout.addView(content, content.getLayoutParams()); //将带有占位状态栏的新的内容视图设置给 DrawerLayout drawer.addView(linearLayout, 0); } else { //增加占位状态栏,并增加状态栏高度的 paddingTop ViewGroup decorView = (ViewGroup) mActivity.getWindow().getDecorView(); decorView.addView(statusBarView, lp); //设置 paddingTop ViewGroup rootView = (ViewGroup) mActivity.getWindow().getDecorView().findViewById(android.R.id.content); rootView.setPadding(0, getStatusBarHeight(mActivity), 0, 0); } } } /** * 通过设置全屏,设置状态栏透明 * * @param activity */ private void fullScreen(Activity activity) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { //5.x开始需要把颜色设置透明,否则导航栏会呈现系统默认的浅灰色 Window window = activity.getWindow(); View decorView = window.getDecorView(); //两个 flag 要结合使用,表示让应用的主体内容占用系统状态栏的空间 int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE; window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); decorView.setSystemUiVisibility(option); window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); window.setStatusBarColor(Color.TRANSPARENT); //导航栏颜色也可以正常设置 // window.setNavigationBarColor(Color.TRANSPARENT); } else { Window window = activity.getWindow(); WindowManager.LayoutParams attributes = window.getAttributes(); int flagTranslucentStatus = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; int flagTranslucentNavigation = WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION; attributes.flags |= flagTranslucentStatus; // attributes.flags |= flagTranslucentNavigation; window.setAttributes(attributes); } } } /** * 通过设置全屏,设置状态栏透明 导航栏黑色 * * @param activity */ public static void setStatusTransparent(Activity activity) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { Window window = activity.getWindow(); WindowManager.LayoutParams attributes = window.getAttributes(); int flagTranslucentStatus = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; int flagTranslucentNavigation = WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION; // attributes.flags |= flagTranslucentStatus; attributes.flags |= flagTranslucentNavigation; window.setAttributes(attributes); window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); window.setStatusBarColor(Color.TRANSPARENT); window.setNavigationBarColor(Color.TRANSPARENT); } else { Window window = activity.getWindow(); WindowManager.LayoutParams attributes = window.getAttributes(); int flagTranslucentStatus = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; int flagTranslucentNavigation = WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION; attributes.flags |= flagTranslucentStatus; attributes.flags |= flagTranslucentNavigation; window.setAttributes(attributes); } } } }
工具类写好了 下面来看看具体如何使用
当然我们还是需要设置在manifest文件加一些内容
<activity
android:name=".MainActivity1"
android:theme="@style/NoActionBarTheme">
</activity>
当设置程一张图片占据状态栏的时候 我们可以这样配置
布局文件很简单
<ImageView android:layout_width="match_parent" android:layout_height="180dp" android:src="@mipmap/bg" android:scaleType="fitXY" />
这样就实现了图片占据状态栏的 样式
接下来看改变状态栏的颜色
这个大体上和图片那个差不多 只需要改变相应的方法就行
StatusBarUtils.with(this).setColor(getResources().getColor(R.color.colorPrimary)).init();
这个颜色就是你想设置的颜色
这样基本这种都没什么问题了