您好,欢迎来到源码搜藏网!分享精神,快乐你我!
[加入VIP] 设为首页 | 收藏本站 | 网站地图 | Sitemap | TAG标签
  • 首 页
  • 在线工具
  • jquery手册
  • 当前位置:首页 > 安卓源码 > 技术博客 >

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

    时间:2019-01-20 12:52 来源:互联网 作者:源码搜藏 浏览:收藏 挑错 推荐 打印

    最近在开发中遇到一种个性化的需求,类似于QQ顶部的渐变状态栏的实现,如下图 首先我们要了解在Android5.0以后,系统API提供直接设置StatusBar来改变状态栏的颜色,然而在4.4上StatusBar变色的基本原理就是将StatusBar本身设置为透明,然后在StatusBar的位置

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

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

    首先我们要了解在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;
        }

    自定义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的Id
            statusBarView.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));

    渐变色兼容状态栏

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

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

    代码如下

      /**
         * 为界面设置自定义透明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 &amp;&amp; (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);
            }
     
        }

    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);//系统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传入,调用如下

    //设置渐变颜色状态栏
    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>

    至此,渐变色状态栏的配置已经介绍完全了,说实话刚开始做的时候,还真的没想到用自定义View延伸到状态栏中显示,但细想下纯色状态栏中的实现也有类似的操作,再结合一下就实现了兼容上下版本的效果

    Android开发 沉浸式状态栏 渐变颜色的实现转载http://www.codesocang.com/appboke/39412.html
    标签:网站源码