Android4.4之后实现沉浸式状态栏及虚拟按键的适配

沉浸式状态栏就是大家常见的把某张图片放到了状态栏上,其实从安卓4.4之后我们就可以更改状态栏的颜色了,不过4.4到5.0之间的设备操作方式比5.0之后要复杂一点,让我们一步一步实现操作吧。

代码控制

我们可以通过代码来实现:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    Window window = 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_HIDE_NAVIGATION
            | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
    window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
    window.setStatusBarColor(Color.TRANSPARENT);
    window.setNavigationBarColor(Color.TRANSPARENT);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {//4.45.0
    WindowManager.LayoutParams localLayoutParams = getWindow().getAttributes();
    localLayoutParams.flags = (WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | localLayoutParams.flags);
}

缺点:
所以我们的界面会向上偏移一个状态栏的高度,一般首页上方是Banner,图片UI可以给调整,但是其他界面就会出现问题,比如你的Toolbar就可能被状态栏遮挡,一般我处理这种问题就是上方加一个25dp高度的View,颜色和Toolbar保持一致。
有个属性叫fitsSystemWindows 得属性,在activity的整体布局中使用,设置为true之后就可以自动的处理虚拟按键、状态栏和我们界面的关系,但是无法做到沉浸,状态栏会变成灰色,我们的页面不能沉到他的下面去,而是并在一起。

项目中的使用

说一说我在项目中的使用吧,由于我的项目只有HomeFragment(首页)的Banner要沉浸在状态栏下方,所以我给MainActivity单独设置了一个Theme,但是MainActivity中又只有HomeFragment含有此banner,对于其他的Fragment我单独添加的view来适配。
1.values-v19包中和values-v21包中都对状态栏设置成透明,虚拟按键不设置成透明,如果你设置成透明的,在华为和Nexus系列的手机上会遮挡布局。
2.V-19包中MainActivity的fitsSystemWindows设置为false,其他的页面此属性设置为true这样他就不会被整个页面操控从而空出状态栏了,因为我们想要修改4.4到5.0之间手机的状态栏颜色,必须要先把状态栏给搞没,然后才能做下一步操作
V-21包中fitsSystemWindows属性都要设置为false,因为5.0之后我们就可以自定义状态栏颜色了,其实这个属性是相对与状态栏来使用的,如果我的状态栏设置为透明,此属性设置为true之后,状态栏变成灰色,否则就沉到状态栏下面,我们的MainActivity设置了状态栏透明,而且就是要沉到状态栏下方,所以此属性就设置成false;
v-19:

<style name="AppTheme" parent="Theme.Design.NoActionBar">
    <!-- 虚拟按键不透明 -->
    <item name="android:windowTranslucentNavigation">false</item>
    <!-- 透明状态栏 -->
    <item name="android:windowTranslucentStatus">true</item>
    <!-- 界面不沉浸到状态栏下方 -->
    <item name="android:fitsSystemWindows">true</item>
<style name="MainTheme" parent="AppTheme">
    <item name="android:windowTranslucentStatus">true</item>
    <item name="android:windowTranslucentNavigation">false</item>
    <item name="android:fitsSystemWindows">false</item>
</style>
 然后是v-21,因为5.0之后的可以自定义状态栏颜色,所以其他页面不需要让状态栏透明:
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:fitsSystemWindows">false</item>
    <!-- Actionbar color toolbar-->
    <item name="colorPrimary">@color/colorPrimary</item>
    <!-- Status bar color 顶部状态栏 -->
    <item name="colorPrimaryDark">@color/colorPrimary</item>
<style name="MainTheme" parent="AppTheme">
    <item name="android:windowTranslucentStatus">true</item>
    <item name="android:windowTranslucentNavigation">false</item>
</style>

3.恶心的地方就是4.4到5.0这些个版本,我们已经把项目中的所有非MainActivity的页面的状态栏给变灰了,其实就是空出了状态栏的高度,那个地方现在时空的,为此,我在顶层封装的BaseActivity中,判断了当前的手机版本,如果是该区间的手机版本,就构建出一个对应高度的view填充到状态栏,这样4.4之后的手机状态栏的颜色都是可控的了

public void setContentView(int layoutResID) {
    super.setContentView(layoutResID);
    StatusBarCompat.compat(this, getResources().getColor(R.color.colorPrimary));

其中StatusBarCompat是从鸿洋那搬过来的,稍加了改动,就是剔除了不需要添加view的界面,附在下面。对于MainActivity中,由于我们的一个Fragment需要沉到状态栏下面,所以除了需要沉下去的,其他Fragment我在布局中都给他们添加了一个25dp的view。
这就是我的方式了,虽然这样做有点牵强,但是我纠结很多天之后最终还是选择了这种方式,暂时还没有找到更好的解决方式,希望以后能解决。

public class StatusBarCompat
{
    private static final int INVALID_VAL = -1;
    private static final int COLOR_DEFAULT = Color.parseColor("#f94548");

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public static void compat(Activity activity, int statusColor)
    {
        //剔除引导页、启动页、主界面
        Class cls =activity.getClass();
        if(cls.equals(MainActivity.class)||cls.equals(WelcomeActivity.class)||cls.equals(IntroduceActivity.class)){
            return;
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
        {
            int color = COLOR_DEFAULT;
            ViewGroup contentView = (ViewGroup) activity.findViewById(android.R.id.content);
            contentView.setFitsSystemWindows(true);
            if (statusColor != INVALID_VAL)
            {
                color = statusColor;
            }
            View statusBarView = new View(activity);
            ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                    getStatusBarHeight(activity));
            statusBarView.setBackgroundColor(color);
            contentView.addView(statusBarView, lp);
        }

    }

    public static void compat(Activity activity)
    {
        compat(activity, INVALID_VAL);
    }


    public static int getStatusBarHeight(Context context)
    {
        int result = 0;
        int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0)
        {
            result = context.getResources().getDimensionPixelSize(resourceId);
        }
        return result;
    }
}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值