Android下多彩的StatusView的实现

概述

文章原文出自Android下多彩的StatusView的实现
作者:Cyning

本文以学习、研究和分享为主,欢迎转载,但必须在文章页面明显位置给出原文连接。愿与志同道合的朋友一起成长

在上一个博文 Anroid沉浸式状态栏中提到了,画了一个图,这个图简单将我们的状态栏分为不同的2个维度来看状态栏。其中涉及的概念我不在赘诉,请返到Anroid沉浸式状态栏再去认识下这几个概念。下文中提到的上节就是Anroid沉浸式状态栏

图1

实现

由于上一讲提到了基本的实现方法和一些可能会用到的方法,但是没有实际操作和演示,那我们现在就来一步步来去实现我们提到的三种状态栏的实现过程。

全屏模式下的透明状态栏

全屏模式下的透明状态栏,实现的app其实我们肯定见过,如我们的启动页很多情况下就是全屏模式,但是这个还是和我们说的不太一样,不过今天我们介绍的这个是状态栏透明,但是仍然存在。

网易新闻这种才是真正的浸入式状态栏:

但是不是我们需要的效果,这种是全屏模式时,当前页面获取焦点就显示一个有一定透明度的暗色状态栏。


我们希望的是小米天气的这种:

内容部分可以延伸到状态栏,且状态栏是透明的,无背景色,也就是我们的全屏模式。

按照我们上节拿来实践下。

public static  void setFullSreen(Activity activity){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            // 设置透明状态栏,这样才能让 ContentView 向上
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

        }
}

我将一个图片铺满contentView。

这个截图是在4.4上完成的。

但是在6.0上的效果还差强人意:

这个是在我的N5手机上跑的,上面有灰色的阴影。不是完全透明,和我们的小气天气不太一样,好了还是用到上节的方法:

public static  void setFullSreen(Activity activity){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Window window = activity.getWindow();
            window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
                    | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
            window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN| View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            window.setStatusBarColor(Color.TRANSPARENT);
        }else
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            // 设置透明状态栏,这样才能让 ContentView 向上
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);

        }
    }

这样就可以使得状态栏也透明了。

彩色状态栏

可能有些人会迷惑,为什么我们要设置彩色状态栏,在5.0可以直接设置主题来设置的,我要告诉你的是我们希望4.4上也有彩色的状态栏。上节我们提到了彩色状态栏的实现方法:就是先设置为屏幕模式下的透明状态栏,再在透明状态栏的垂直下方放置一个和状态栏同样高宽的view,我们操作他这个空白view的颜色,即可实现彩色状态栏。

好了我们贴出来我们的代码逻辑吧:

     /**
     *设置彩色的状态栏
     *
     * @param activity
     * @param color 状态栏需要设置的背景颜色
     * @param statusBarAlpha 状态栏需要设置的背景颜色的透明度
     */
    public static void setColor(Activity activity, @ColorInt int color, int statusBarAlpha){

        //先设置的全屏模式
        setFullSreen(activity);
        //在透明状态栏的垂直下方放置一个和状态栏同样高宽的view
        addStatusBarBehind(activity,color,statusBarAlpha);


    }
    /**
     * 添加了一个状态栏(实际上是个view),放在了状态栏的垂直下方
         */
    public static void addStatusBarBehind(Activity activity, @ColorInt int color, int statusBarAlpha) {
        //获取windowphone下的decorView
        ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
        int       count     = decorView.getChildCount();
        //判断是否已经添加了statusBarView
        if (count > 0 && decorView.getChildAt(count - 1) instanceof StatusBarView) {
            decorView.getChildAt(count - 1).setBackgroundColor(calculateStatusColor(color, statusBarAlpha));
        } else {
            //新建一个和状态栏高宽的view
            StatusBarView statusView = createStatusBarView(activity, color, statusBarAlpha);
            decorView.addView(statusView);
        }
        setRootView(activity);
    }

   /**
     * 设置根布局参数
     */
    private static void setRootView(Activity activity) {
        ViewGroup rootView = (ViewGroup) ((ViewGroup) activity.findViewById(android.R.id.content)).getChildAt(0);
        //rootview不会为状态栏流出状态栏空间
        ViewCompat.setFitsSystemWindows(rootView,false);
        rootView.setClipToPadding(true);
    }


    private static StatusBarView createStatusBarView(Activity activity, int color, int alpha) {
        // 绘制一个和状态栏一样高的矩形
        StatusBarView statusBarView = new StatusBarView(activity);
        LinearLayout.LayoutParams params =
                new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(activity));
        statusBarView.setLayoutParams(params);
        statusBarView.setBackgroundColor(calculateStatusColor(color, alpha));
        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);
    }
    /**
     * 计算状态栏颜色
     *
     * @param color color值
     * @param alpha alpha值
     * @return 最终的状态栏颜色
     */
    private static int calculateStatusColor(int color, int alpha) {
        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,贴出来的这个类吧:


public class StatusBarView extends View {


    public StatusBarView(Context context, AttributeSet attrs,int style) {
        super(context, attrs,style);
    }    

    public StatusBarView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public StatusBarView(Context context) {
        super(context);
    }

}

搞定,我们就可以来动态改变状态栏的颜色了。

calculateStatusColor 方法中的alpha是0-255的,0的时候其实是不透明的,当设置255相当于statusview背景透明,即为默认色黑色。

可用的函数是public static void setColor(Activity activity, @ColorInt int color, int statusBarAlpha)setFullSreen

小结

Now现在这个工具类就算是OK,对于代码的侵入基本上为零,直接拿来当工具类,不用改主题,简单易容用。也为大家提供一个思路,这个只是实现的基本功能,一些复杂的定制的情况,可以随机应变,自由组合使用。

实现状态栏,无非是将4.4-5.0 和5.0+的分别实现,当然配合decorview和 ViewCompat.setFitsSystemWindows(view,boolean)使用效果更佳。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值