最近在开发中遇到一种个性化的需求,相似于QQ顶部的渐变状态栏的实现,以下图 android
首先咱们要了解在Android5.0之后,系统API提供直接设置StatusBar来改变状态栏的颜色,然而在4.4上StatusBar变色的基本原理就是将StatusBar自己设置为透明,而后在StatusBar的位置添加一个相同大小的View并上色。没办法,咱们要作的渐变颜色状态栏就是要兼容上下版本的差别git
更多关于沉浸式状态栏的了解可参考洪洋大神的文章github
Android 沉浸式状态栏攻略 让你的状态栏变色吧bash
/** * 设置状态栏颜色 * * @param activity 须要设置的activity * @param color 状态栏颜色值 * @param statusBarAlpha 状态栏透明度 */ public static void setColor(Activity activity, @ColorInt int color, @IntRange(from = 0, to = 255) int statusBarAlpha) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { //5.0以上版本 //设置FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS属性才能调用setStatusBarColor方法来设置状态栏颜色 activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); //设置FLAG_TRANSLUCENT_STATUS透明状态栏 activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); //根据输入的颜色和透明度显示 activity.getWindow().setStatusBarColor(calculateStatusColor(color, statusBarAlpha)); } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { //低版本 //添加透明状态栏 activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); //获取顶级视图 ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView(); //获取顶部的StatusBarView,自定义StatusBarView的Id(在resources中建立Id) View fakeStatusBarView = decorView.findViewById(R.id.statusbarutil_fake_status_bar_view); if (fakeStatusBarView != null) { if (fakeStatusBarView.getVisibility() == View.GONE) { fakeStatusBarView.setVisibility(View.VISIBLE); } //设置顶层颜色 fakeStatusBarView.setBackgroundColor(calculateStatusColor(color, statusBarAlpha)); } else { //上述不符合,则建立一个View添加到顶级视图中 decorView.addView(createStatusBarView(activity, color, statusBarAlpha)); } setRootView(activity); } } 复制代码
/** * 计算状态栏颜色 * * @param color color值 * @param alpha alpha值 * @return 最终的状态栏颜色 */ private static int calculateStatusColor(@ColorInt int color, int alpha) { if (alpha == 0) { return color; } float a = 1 - alpha / 255f; int red = color >> 16 & 0xff; int green = color >> 8 & 0xff; int blue = color & 0xff; red = (int) (red * a + 0.5); green = (int) (green * a + 0.5); blue = (int) (blue * a + 0.5); return 0xff << 24 | red << 16 | green << 8 | blue; } 复制代码
/** * 自定义View状态栏 * * @param activity 须要设置的activity * @param color 状态栏颜色值 * @param alpha 透明值 * @return 状态栏矩形条 */ private static View createStatusBarView(Activity activity, @ColorInt int color, int alpha) { // 绘制一个和状态栏同样高的矩形 View statusBarView = new View(activity); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity)); statusBarView.setLayoutParams(params); statusBarView.setBackgroundColor(calculateStatusColor(color, alpha)); //自定义的StatusBarView的Id statusBarView.setId(FAKE_STATUS_BAR_VIEW_ID); return statusBarView; } 复制代码
最后从新规划布局markdown
/** * 设置根布局参数 */ private static void setRootView(Activity activity) { //ViewGroup容器存放UI组件 ViewGroup parent = (ViewGroup) activity.findViewById(android.R.id.content); for (int i = 0, count = parent.getChildCount(); i < count; i++) { View childView = parent.getChildAt(i); if (childView instanceof ViewGroup) { childView.setFitsSystemWindows(true); ((ViewGroup) childView).setClipToPadding(true); } } } 复制代码
由此纯色状态栏的基本配置就能够了,只须要建立Utils工具类在Activity中调用便可,app
//设置纯色状态栏
StatusBarUtil.setColor(this, AppUtils.getColor(R.color.colorPrimary));
复制代码
代码以下工具
/** * 为界面设置自定义透明View * * @param activity 须要设置的activity * @param statusBarAlpha 状态栏透明度 * @param needOffsetView 须要向下偏移的 View public static void setTranslucentForWindow(Activity activity, @IntRange(from = 0, to = 255) int statusBarAlpha, View needOffsetView) { if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) { //5.0以上版本 setTransparentForWindow(activity); addTranslucentView(activity, statusBarAlpha); if (needOffsetView != null) { Object haveSetOffset = needOffsetView.getTag(TAG_KEY_HAVE_SET_OFFSET); if (haveSetOffset != null && (Boolean) haveSetOffset) { return; } ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) needOffsetView.getLayoutParams(); layoutParams.setMargins(layoutParams.leftMargin, layoutParams.topMargin + getStatusBarHeight(activity), layoutParams.rightMargin, layoutParams.bottomMargin); needOffsetView.setTag(TAG_KEY_HAVE_SET_OFFSET, true); } } else { //低版本 //添加透明状态栏 activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); //获取顶级视图 ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView(); //获取顶部的StatusBarView,自定义id View fakeStatusBarView = decorView.findViewById(FAKE_STATUS_BAR_VIEW_ID); if (fakeStatusBarView != null) { if (fakeStatusBarView.getVisibility() == View.GONE) { fakeStatusBarView.setVisibility(View.VISIBLE); } //设置顶层颜色 fakeStatusBarView.setBackgroundResource(R.drawable.shape_gradient); } else { //上述不符合,则建立一个View添加到顶级视图中 View statusBarView = new View(activity); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity)); statusBarView.setLayoutParams(params); fakeStatusBarView.setBackgroundResource(R.drawable.shape_gradient); statusBarView.setId(FAKE_STATUS_BAR_VIEW_ID); decorView.addView(statusBarView); } setRootView(activity); } } 复制代码
/** * 获取状态栏高度 * * @param context context * @return 状态栏高度 */ public static int getStatusBarHeight(Context context) { // 得到状态栏高度 int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android"); return context.getResources().getDimensionPixelSize(resourceId); } 复制代码
/** * 设置透明 */ public static void setTransparentForWindow(Activity activity) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { activity.getWindow().setStatusBarColor(Color.TRANSPARENT); activity.getWindow() .getDecorView() .setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { activity.getWindow() .setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); } 复制代码
/** * 添加半透明矩形条 * * @param activity 须要设置的 activity * @param statusBarAlpha 透明值 */ private static void addTranslucentView(Activity activity, @IntRange(from = 0, to = 255) int statusBarAlpha) { ViewGroup contentView = (ViewGroup) activity.findViewById(android.R.id.content);//系统Id View fakeTranslucentView = contentView.findViewById(FAKE_TRANSLUCENT_VIEW_ID); if (fakeTranslucentView != null) { if (fakeTranslucentView.getVisibility() == View.GONE) { fakeTranslucentView.setVisibility(View.VISIBLE); } fakeTranslucentView.setBackgroundColor(Color.argb(statusBarAlpha, 0, 0, 0)); } else { contentView.addView(createTranslucentStatusBarView(activity, statusBarAlpha)); } } 复制代码
由此渐变颜色的状态栏设置,只须要将toolbar做为View传入,调用以下oop
//设置渐变颜色状态栏 StatusBarUtil.setTransparentForWindow(this, mToolbar); //布局以下 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content"> <android.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/shape_gradient" android:theme="@style/AppTheme.AppBarOverlay" app:elevation="@dimen/dp0"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:popupTheme="@style/ToolbarPopupTheme" app:title="@string/main_toolbar_title_top" app:titleTextColor="@color/colorPrimary"> </android.support.v7.widget.Toolbar> </android.support.design.widget.AppBarLayout> </LinearLayout> 复制代码
至此,渐变色状态栏的配置已经介绍彻底了ui