沉浸式状态栏实现

在android4.4以前状态栏只能是黑色,在4.4中带来了windowTranslucentStatus 这一特性,状态栏的颜色就可以感觉自己的需求改变颜色了,那为什么叫沉浸式状态栏呢?这个叫法是叫的人多人,大家都约定俗称了。废话不多说,首先上一张效果图。


此demo的布局文件如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >

    <TextView

        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:background="#FF0000"
        android:textColor="#FFFFFF"
        android:text="沉浸式状态栏"
        />

</LinearLayout>



其实实现沉浸式状态栏非常的简单,两行代码就可以实现,把下面两行代码添加到你activity的 setContentView方法之后
        //当系统版本为4.4或者4.4以上时可以使用沉浸式状态栏
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            //透明状态栏
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            //透明导航栏
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);

        }

然后你会发现,沉浸式状态栏确实是实现了,但是TextView直接和状态栏重叠了,这还没有达到我们想要的效果,效果如下图



为了解决TextView和状态栏的重叠方式有两种方式,第一种方式是给刚刚的TextView的布局文件添加android:fitsSystemWindows="true" , android:clipToPadding="true"这两个属性,第二种方式是在布局文件中放置一个隐藏的View,通过代码获取状态栏的高度,然后动态的设置view的颜色和高度,让其填充整个状态栏

第一种方式
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >

    <TextView
        android:fitsSystemWindows="true"
        android:clipToPadding="true"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:background="#FF0000"
        android:textColor="#FFFFFF"
        android:text="沉浸式状态栏"
        />

</LinearLayout>

第二种方式
第二种方式实现起来麻烦一点,但是个人推荐使用这种方式,不然让TexTView的文本进行居中显示时会很不准
先看看布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    >

    <LinearLayout
        android:id="@+id/ll_fill"
        android:layout_width="fill_parent"
        android:layout_height="1dp"
        android:orientation="vertical"
        android:background="#FF0000"
        android:visibility="gone">
    </LinearLayout>

    <TextView

        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:background="#FF0000"
        android:textColor="#FFFFFF"
        android:text="沉浸式状态栏"
        />

</LinearLayout>

再看看在Activity中的代码
 //当系统版本为4.4或者4.4以上时可以使用沉浸式状态栏
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            //透明状态栏
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            //透明导航栏
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);

            LinearLayout ll_fill = (LinearLayout) findViewById(R.id.ll_fill);
            ll_fill.setVisibility(View.VISIBLE);
            //获取到状态栏的高度
            int statusHeight = getStatusBarHeight();
            Log.e("399", "statusHeight" + statusHeight);
            //动态的设置隐藏布局的高度
            LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) ll_fill.getLayoutParams();
            params.height = statusHeight;
            ll_fill.setLayoutParams(params);
        }
状态栏的高度是通过反射的方式获取的,获取方式如下:
 /**
     * 通过反射的方式获取状态栏高度
     *
     * @return
     */
    private int getStatusBarHeight() {
        try {
            Class<?> c = Class.forName("com.android.internal.R$dimen");
            Object obj = c.newInstance();
            Field field = c.getField("status_bar_height");
            int x = Integer.parseInt(field.get(obj).toString());
            return getResources().getDimensionPixelSize(x);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

实现后的效果图:


以上是在运行android4.4.4的小米4上显示的效果,运行在android5.0及以上的效果如下:


你会发现状态栏并不是完全透明的,网上找了很久,最后在github的一个开源项目中找到了答案,解决方式如下:
在Activity的onCreate中添加
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
            getWindow().setStatusBarColor(Color.TRANSPARENT);
        }
        else {
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        }
            LinearLayout ll_fill = (LinearLayout) findViewById(R.id.ll_fill);
            ll_fill.setVisibility(View.VISIBLE);
            //获取到状态栏的高度
            int statusHeight = getStatusBarHeight();
            Log.e("399", "statusHeight" + statusHeight);
            //动态的设置隐藏布局的高度
            LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) ll_fill.getLayoutParams();
            params.height = statusHeight;
            ll_fill.setLayoutParams(params);

然后就全透明啦




最后,找到一个实现沉浸式状态栏的开源库,地址 https://github.com/laobie/StatusBarUtil

更具这个开源库简单的抽取了一个工具类StatusBarUtil,可以直接拿来用

package com.hand.gaoli.utils;

import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.os.Build;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.LinearLayout;

import com.hand.gaoli.widget.StatusBarView;

import java.lang.reflect.Field;

/**
 * Created by cool on 2017/1/10.
 */

public class StatusBarUtil {

    public static void setImmerse(Activity activity,int color){
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
            return;
        }
        initImmerse(activity);
        addStatusView(activity,color);
        setRootView(activity);
    }

    /**
     * 设置沉浸式状态栏
     */
    private static void initImmerse(Activity activity) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
            activity.getWindow().setStatusBarColor(Color.TRANSPARENT);
        } else {
            activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        }
    }

    /**
     * 设置根布局参数
     */
    private static void addStatusView(Activity activity,int color) {
        ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
        int count = decorView.getChildCount();
        if (count > 0 && decorView.getChildAt(count - 1) instanceof StatusBarView) {
            decorView.getChildAt(count - 1).setBackgroundColor(color);
        } else {
            StatusBarView statusView = createStatusBarView(activity, color);
            decorView.addView(statusView);
        }

    }

    /**
     * 设置根布局参数
     */
    private static void setRootView(Activity activity) {
        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);
            }
        }
    }

    private static StatusBarView createStatusBarView(Activity activity,int color) {
        StatusBarView view = new StatusBarView(activity);
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,getStatusBarHeight(activity));
        view.setLayoutParams(params);
        view.setBackgroundColor(color);
        return view;
    }

    /**
     * 通过反射的方式获取状态栏高度
     *
     * @return
     */
    public static int getStatusBarHeight(Context context) {
        try {
            Class<?> c = Class.forName("com.android.internal.R$dimen");
            Object obj = c.newInstance();
            Field field = c.getField("status_bar_height");
            int x = Integer.parseInt(field.get(obj).toString());
            return context.getResources().getDimensionPixelSize(x);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }


}
StatusBarView
package com.hand.gaoli.widget;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;

/**
 * Created by cool on 2017/1/10.
 */

public class StatusBarView extends View {
    public StatusBarView(Context context) {
        super(context);
    }

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

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

使用:

//设置沉浸式状态栏
        StatusBarUtil.setImmerse(this, getResources().getColor(R.color.main_color));


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值