1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > Android 沉浸式状态栏 渐变颜色的实现

Android 沉浸式状态栏 渐变颜色的实现

时间:2024-02-13 21:13:49

相关推荐

Android 沉浸式状态栏 渐变颜色的实现

Android 沉浸式状态栏 渐变颜色的实现

最近在开发中遇到一种个性化的需求,类似于QQ顶部的渐变状态栏的实现,如下图

首先我们要了解在Android5.0以后,系统API提供直接设置StatusBar来改变状态栏的颜色,然而在4.4上StatusBar变色的基本原理就是将StatusBar本身设置为透明,然后在StatusBar的位置添加一个相同大小的View并上色。没办法,我们要做的渐变颜色状态栏就是要兼容上下版本的差异

更多关于沉浸式状态栏的了解可参考洪洋大神的文章

Android 沉浸式状态栏攻略 让你的状态栏变色吧

纯色兼容状态栏

/*** 设置状态栏颜色** @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);}}

calculateStatusColor(计算状态栏颜色)

/*** 计算状态栏颜色** @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;}

getStatusBarHeight(获取状态栏高度)

/*** 获取状态栏高度** @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);}

自定义View状态栏

/*** 自定义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的IdstatusBarView.setId(FAKE_STATUS_BAR_VIEW_ID);return statusBarView;}

最后重新规划布局

setRootView(重新设置根布局)

/*** 设置根布局参数*/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中调用即可,

//设置纯色状态栏StatusBarUtil.setColor(this, AppUtils.getColor(R.color.colorPrimary));

渐变色兼容状态栏

关于渐变颜色的状态栏,实现方法有很多种,比如(反射拿到StatusBar并设置setBackgroundResource将shape渐变颜色添加进来即可,创建View填充状态栏),这里我们介绍的是第二种方法,创建View填充状态栏(有没有方法跟上面的方法很类似)

代码如下

/*** 为界面设置自定义透明View** @param activity 需要设置的activity* @param statusBarAlpha 状态栏透明度* @param needOffsetView 需要向下偏移的 Viewpublic 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,自定义idView 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);}}

getStatusBarHeight(获取状态栏高度)

/*** 获取状态栏高度** @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);}

setTransparentForWindow(设置状态栏透明)

/*** 设置透明*/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);}}

addTranslucentView(添加半透明矩形)

/*** 添加半透明矩形条** @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);//系统IdView 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传入,调用如下

//设置渐变颜色状态栏(调用方法)StatusBarUtil.setTransparentForWindow(this, mToolbar);//布局如下<?xml version="1.0" encoding="utf-8"?><LinearLayoutxmlns:android="/apk/res/android"xmlns:app="/apk/res-auto"android:layout_width="match_parent"android:layout_height="wrap_content"><android.support.design.widget.AppBarLayoutandroid: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.Toolbarandroid: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>

Demo Link

至此,渐变色状态栏的配置已经介绍完全了,细想下纯色状态栏中的实现也有类似的操作,再结合一下就实现了兼容上下版本的效果

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。