Android沉浸式状态栏(变色状态栏、透明状态栏)的实现

背景

         在Android4.4之前,状态栏都是单调的黑色条状,4.4之后Android开始支持状态栏的个性定制,如:变色半透明和全透明。国内很多将这种变色或透明状态栏称为“沉浸式状态栏”,其实官方并无此叫法,国内最先叫起这高大上的名称,应该“功劳”归于这里:MIUI 6 沉浸式状态栏调用方法,后来估计是时间长了,叫的人也多了后,大家便都习惯了、默认就这种叫了。

效果

         首先来了看看Android5.0和4.4在效果上的区别:

 

         如上图,5.0系统的状态栏是单纯颜色,而4.4系统中,无论设置了变色、半透明或全透明,都会自带一个黑色渐变效果。

实现的原理

除了效果有所区别,在实现原理方面,它们也有所不同,5.0系统实现变色比较简单,因为Window类里已经提供了一个叫setStatusBarColor(int color)的方法,直接调用即可,要注意的是,setStatusBarColor方法设置的状态栏颜色其实是在默认黑色状态栏的上面加上一层,所以color参数的alpha值无论怎样设置都只是上层颜色的透明,即并不能做到整个状态栏透明或半透明;4.4系统因为本身没有提供现成的方法,所以需要用些小手段,这种小手段可以实现全透明、半透明以及颜色状态栏,步骤大概是这样:设置Window的Flags带FLAG_TRANSLUCENT_STATUS,然后根布局的fitsSystemWindows和clipToPadding参数为true,使其可以布局基于系统状态栏和使控件的绘制区域不在padding里面。如果只是做全透明状态栏,到了这步已经可以看到效果了。但想做成带颜色或半透明的话,还需进一步的处理。因为此时状态栏已经处理透明,那么手动在顶级View上添加一个跟状态栏大小一样的View,那样看上去,便是状态栏变颜色,如果添加的View做成半透明,那么便是半透明状态栏了。

到这,我们来想想,因为5.0系统里的setStatusBarColor(intcolor)方法不能直接做成半透明状态栏,如果在实现全透明状态栏步骤中,系统刚好是5.0呢,能不能不用手动生成状态栏大小的View,而是直接用setStatusBarColor(int color)方法并使color参数的alpha值带透明,那样能否实现状态栏的半透明的效果的呢?答案是确定的。

实现的代码

         接下来看看完整的代码的实现:

 

    /**
     * 设置状态栏颜色
     *
     * @param activity       需要设置的activity
     * @param color          状态栏颜色值
     */
    public static void setColor(Activity activity, int color) {
        int alpha = Color.alpha(color);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && alpha == 255) {    // 安卓5.0及以上而且非带透明,可以直接使用setStatusBarColor处理
            setLollipopStatusBarColor(activity, color);
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {               // 安卓4.4,需要此小手段
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

            // 获取根布局View并设置相应参数
            ViewGroup rootView = (ViewGroup)((ViewGroup) activity.findViewById(android.R.id.content)).getChildAt(0);
            rootView.setFitsSystemWindows(true);
            rootView.setClipToPadding(true);

            // 非全透明情况下
            if (alpha != 0) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                    // 5.0系统直接设置状态栏颜色
                    activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
                    setLollipopStatusBarColor(activity, color);
                } else {
                    // 4.4系统生成一个跟状态栏一样高的矩形View 添加到顶层View
                    View statusView = createStatusBarView(activity, color);
                    ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
                    decorView.addView(statusView);
                }
            }
        }
    }

    /**
     * 安卓5.0及以上设置状态栏颜色
     *
     * @param activity 需要设置的activity
     * @param color    状态栏颜色值
     */
    private static void setLollipopStatusBarColor(Activity activity, int color) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);    //需要设置 FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS 才能调用 setStatusBarColor 来设置状态栏颜色
            activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            activity.getWindow().setStatusBarColor(color);
        }
    }

    /**
     * 生成一个和状态栏大小相同的矩形View
     *
     * @param activity 需要设置的activity
     * @param color    状态栏颜色值
     * @return 状态栏矩形条
     */
    private static View createStatusBarView(Activity activity, int color) {
        View statusBarView = new View(activity);
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity));
        statusBarView.setLayoutParams(params);
        statusBarView.setBackgroundColor(color);
        return statusBarView;
    }

    /**
     * 获取状态栏高度
     *
     * @param context context
     * @return 状态栏高度
     */
    private static int getStatusBarHeight(Context context) {
        // 获得状态栏高度
        int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
        return context.getResources().getDimensionPixelSize(resourceId);
    }


调用很简单,假如我们把这封装到一个叫StatusBarUtil名的类,那么要置纯色或带透明颜色的状态栏,代码可以这样:

 

    StatusBarUtil.setColor(this, getResources().getColor(R.color.color));

为了方便外边的调用全透明情况,在StatusBarUtil类里,可以封装一个setTransparent方法:

 

    /**
     * 设置状态栏透明
     * 适用于图片作为背景的界面,此时需要图片填充到状态栏
     * @param activity 需要设置的activity
     */
    public static void setTransparent(Activity activity) {
        setColor(activity, Color.argb(0, 0, 0, 0));
    }

此时,如果需要设置一个全透明的状态栏,调用代可以这样:

 

    StatusBarUtil.setTransparent(this);

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值