沉浸式状态栏的实现

android5.0推出了沉浸式状态栏的效果,让android状态栏可以轻松的改变颜色,大大提升app的一个视觉效果,相信android开发者们都已经早就接触并实现过该效果了,最近刚好有时间,将自己的一个实现记录下来;沉浸式效果在android5.0+上面实现起来还是比较简单,但是要在android4.4-android5.0上面实现的还是要费点事情,目前还没有看到android4.4以下实现了该效果,所以在开发中只需做android5.0+和android4.4-android5.0一个兼容;

android5.0+沉浸式效果的实现
方法一:

<!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorAccent</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

修改colorPrimaryDark的颜色就可以实现沉浸式的效果,不过需要注意的是修改colorPrimaryDark的颜色意味着所有的页面都是修改的颜色,如果某个页面想实现不一样的沉浸式效果,需要做特别处理;

方法二:
调用系统的setStatusBarColor方法;

getWindow().setStatusBarColor(getResources().getColor(R.color.colorAccent));

注意:在使用的时候会提示该方法是在api21才会有;

方法三:

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
                <!-- Customize your theme here. -->
                <item name="colorPrimary">@color/colorPrimary</item>
                <item name="colorPrimaryDark">@color/colorPrimary</item>
                <item name="colorAccent">@color/colorAccent</item>
                <item name="android:statusBarColor">@color/colorAccent</item>
        </style>

在样式里面添加android:statusBarColor,同样android:statusBarColor是在api21以后才会有,所有要建立一个values-v21的文件,并添加样式;
不管哪种方法,在android5.0+上面基本上一句代码就可以实现沉浸式的效果,但是当你把上面这些代码运行到android5.0以下的手机上的时候什么效果都不会有,所以要在上面的基础上做相应的兼容,下面就写下如果去兼容android4.4到android5.0;
对于android4.4到android5.0的思路是:首先把他弄成全屏,在状态栏的部分加一个布局

    /**
     * 设置状态栏颜色
     * @param activity  对应的activity
     * @param color  设置的颜色
     */
    public static void setStatusBarColor(Activity activity,int color){
        if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP){
            //android5.0+
            //直接调用系统提供的方法  setStatusBarColor
            activity.getWindow().setStatusBarColor(color);
        }else if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.KITKAT&&Build.VERSION.SDK_INT<Build.VERSION_CODES.LOLLIPOP){
            //android4.4-android5.0
            //设置成全屏
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            //在状态栏的部分添加一个布局
            View view=new View(activity);
            ViewGroup.LayoutParams params=new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,getStatusBarHeight(activity));
            view.setLayoutParams(params);
            view.setBackgroundColor(color);

            ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
            decorView.addView(view);

            //获取activity中setContentView布局的根布局
            ViewGroup contentView = (ViewGroup) activity.findViewById(android.R.id.content);
            View childAt = contentView.getChildAt(0);
            childAt.setFitsSystemWindows(true);
        }
    }

在获取状态栏高度的时候可以通过反射获取,也可以通过另外一种方式获取;

方式一:

    /**
     * 获取状态栏的高度
     * @param activity  对应的activity
     * @return  状态栏的高度
     */
    private static int getStatusBarHeight(Activity activity) {
        Resources resources = activity.getResources();
        int identifier = resources.getIdentifier("status_bar_height", "dimen", "android");
        return resources.getDimensionPixelOffset(identifier);
    }

方式二(反射):

    /**
     * 反射获取状态栏高度
     * @param context  上下文
     * @return  状态栏高度
     */
    private static int getStatusBarHeight(Activity context){
        // 反射手机运行的类:android.R.dimen.status_bar_height.
        int statusHeight = -1;
        try {
            Class<?> clazz = Class.forName("com.android.internal.R$dimen");
            Object object = clazz.newInstance();
            String heightStr = clazz.getField("status_bar_height").get(object).toString();
            int height = Integer.parseInt(heightStr);
            //dp--->px
            statusHeight = context.getResources().getDimensionPixelSize(height);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return statusHeight;
    }

这样子沉浸式状态栏效果就实现了:

android6.0效果:
这里写图片描述

android4.4.2效果:
这里写图片描述

底部导航栏沉浸式效果的实现和上面的实现大致是一样的;

android5.0+的实现:

方法一:
新建一个values-v21的文件,在style样式中添加android:navigationBarColor

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
                <!-- Customize your theme here. -->
                <item name="colorPrimary">@color/colorPrimary</item>
                <item name="colorPrimaryDark">@color/colorPrimary</item>
                <item name="colorAccent">@color/colorAccent</item>
                <item name="android:navigationBarColor">@color/colorAccent</item>
        </style>

方法二:
调用系统的setNavigationBarColor方法;

getWindow().setNavigationBarColor(getResources().getColor(R.color.colorAccent));

android4.4-android5.0的兼容:
在布局文件添加一个view,设置虚拟导航栏为透明,设置view的高度为底部导航栏的高度,并设置view的颜色;

    /**
     * 设置底部导航颜色
     * @param activity  上下文
     * @param color  设置的颜色
     * @param view  底部的view
     */
    public static void setNavigationColor(Activity activity,int color,View view){
        if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP){
            //android5.0+
            //直接调用系统提供的方法  setStatusBarColor
            activity.getWindow().setNavigationBarColor(color);
        }else if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.KITKAT&&Build.VERSION.SDK_INT<Build.VERSION_CODES.LOLLIPOP){
            //android4.4-android5.0
            if(view!=null){
                //设置成全屏
                activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
                //判断底部虚拟导航栏是否存在(或者开启)
                if(hasNavigationBarShow(activity.getWindowManager())){
                    ViewGroup.LayoutParams p = view.getLayoutParams();
                    p.height+=getNavigationBarHeight(activity);
                    view.setLayoutParams(p);
                    view.setBackgroundColor(color);
                }else{
                    ViewGroup.LayoutParams p = view.getLayoutParams();
                    p.height=0;
                    view.setLayoutParams(p);
                }
            }
        }
    }

这里需要注意的是要判断底部导航栏是否存在,在有些手机上是没有底部导航栏,有些手机上即使有底部导航栏,也可以设置关闭底部导航栏,在设置的时候需要判断;

    /**
     * 判断底部虚拟导航栏是否存在(打开)
     * @param windowManager
     */
    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
    private static boolean hasNavigationBarShow(WindowManager windowManager) {
        Display display = windowManager.getDefaultDisplay();
        DisplayMetrics outMetrics=new DisplayMetrics();
        //获取整个屏幕的高度
        display.getRealMetrics(outMetrics);
        int heightPixels = outMetrics.heightPixels;
        int widthPixels = outMetrics.widthPixels;
        //获取内容展示部分的高度
        outMetrics=new DisplayMetrics();
        int heightPixels1 = outMetrics.heightPixels;
        int widthPixels1 = outMetrics.widthPixels;
        int h=heightPixels-heightPixels1;
        int w=widthPixels-widthPixels1;
        return w>0||h>0;

    }

获取底部导航栏的高度和上面获取导航栏的高度差不多;

   /**
     * 获取底部导航栏高度
     * @param activity  上下文
     * @return 底部导航栏高度
     */
    private static int getNavigationBarHeight(Activity activity) {
        Resources resources = activity.getResources();
        int identifier = resources.getIdentifier("navigation_bar_height", "dimen", "android");
        return resources.getDimensionPixelOffset(identifier);
    }

这样就实现底部导航栏沉浸式效果了;

android6.0效果:
这里写图片描述

android4.4.2效果:
这里写图片描述

源码地址:
http://download.csdn.net/download/wangwo1991/9928577

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值