修改状态栏颜色

本文介绍的修改状态颜色的方法仅支持android4.4及以上系统,操作大致分为2个步骤:
1.将状态栏透明化
2.覆盖透明的状态栏

效果图:
根布局顶部是图片根据布局切换状态栏颜色
根据布局切换状态栏颜色DrawerLayout + NavigationView + Toolbar

状态栏透明化

可通过代码设置,一般写在BaseActivity中,例如:

//5.0及以上
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
   /*
    View decorView = getWindow().getDecorView();
    int option = View.SYSTEM_UI_FLAG_FULLSCREEN |View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
    decorView.setSystemUiVisibility(option);
    getWindow().setStatusBarColor(Color.TRANSPARENT);
	*/
	
	//上面代码发现在华为mate10的android8.1手机上无效,状态栏是全白的,因此修改成下面
	Window window = getWindow();
	window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
    window.setStatusBarColor(Color.TRANSPARENT);
}
//4.4到5.0
else if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.KITKAT){
    WindowManager.LayoutParams localLayoutParams = getWindow().getAttributes();
    localLayoutParams.flags = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS |
            localLayoutParams.flags;
}

也可以通过样式设置,需要在 values、values-v19、values-v21 目录下分别创建相应的主题

values/styles.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- 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/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>
    <style name="TranslucentTheme" parent="AppTheme"></style>
</resources>

values-v19/styles.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="TranslucentTheme" parent="AppTheme">
        <item name="android:windowTranslucentStatus">true</item>
        <item name="android:windowTranslucentNavigation">false</item>
    </style>
</resources>

values-v21/styles.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="TranslucentTheme" parent="AppTheme">
        <item name="android:windowTranslucentStatus">true</item>
        <item name="android:windowTranslucentNavigation">false</item>
        <item name="android:statusBarColor">@android:color/transparent</item>
    </style>
</resources>

然后在清单文件中设置对应的Activity或者Application的主题为:
android:theme="@style/TranslucentTheme"

提示:将状态栏透明化后,直接运行项目会发现界面布局直接延伸到状态栏,透过状态栏可以看到布局界面.

注意:Android7.0上按照上面的设置后,状态栏会变灰,解决办法如下:
在setContentView方法前调用这段代码:

//解决Android7.0下沉浸式状态栏变灰的问题
    private void initStatueBar() {
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
            try {
                Class decorViewClazz = Class.forName("com.android.internal.policy.DecorView");
                Field field = decorViewClazz.getDeclaredField("mSemiTransparentStatusBarColor");
                field.setAccessible(true);
                field.setInt(getWindow().getDecorView(), Color.TRANSPARENT); //改为透明
            } catch (Exception e) {}
        }
    }

覆盖状态栏

利用布局延伸到状态栏的特性,我们可以直接使用布局的背景颜色做为需要的状态栏颜色,只需要在根布局中设置一个paddingTop为状态栏的高度即可,这个paddingTo最好区分下4.4之前和之后的,因为如果4.4之前的话状态栏是没有透明化,也就不需要设置paddingTop了.解决思路就是创建多一个dimens.xml在values-v19目录下.
values/dimens.xml

<resources>
    <dimen name="padding_top">0dp</dimen>
</resources>

values-v19/dimens.xml

<resources>
    <dimen name="padding_top">25dp</dimen>
</resources>

paddingTop的值可以自行测量,接近状态栏的高度即可,也可以使用下面的代码获取状态栏的高度

private int getStatusBarHeight(Context context) {
    int statusBarHeight = 0;
    try {
        Class c = Class.forName("com.android.internal.R$dimen");
        Object obj = c.newInstance();
        Field field = c.getField("status_bar_height");
        int x1 = Integer.parseInt(field.get(obj).toString());
        statusBarHeight = context.getResources().getDimensionPixelSize(x1);
    } catch (Exception var7) {
        var7.printStackTrace();
    }
    return statusBarHeight;
}

另一种方式,就是屏蔽掉布局延伸到状态栏的特性,然后添加一个和状态栏高/宽相同的指定颜色的View来覆盖透明化的状态栏.
如何屏蔽?
只需要在布局文件的根节点就中设置android:fitsSystemWindows="true"属性即可.
如何通过View覆盖状态栏?
其实Activity在onCreate方法中调用setContentView(resId)方法设置布局的时候,它是将该布局作为系统id为android.R.id.content容器的子节点,而该容器是一个FrameLayout,因此可以通过下面的方式获取该FrameLayout

ViewGroup contentView = (ViewGroup) findViewById(android.R.id.content);
拿到该容器后,就可以添加一个宽高和状态栏相同的View来覆盖状态栏了,具体代码如下:

public void addStatusBarView(int colorId) {
	//创建指定颜色的View
    View view = new View(this);
    view.setBackgroundColor(getResources().getColor(colorId));
    //设置View的宽高,高度为状态栏高度,获取的代码上面有提到
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
            getStatusBarHeight(this));
    //获取布局文件添加的父容器
    ViewGroup contentView = (ViewGroup) findViewById(android.R.id.content);
    //添加到容器中
    contentView.addView(view, params);
}

最后补充下设置状态栏和导航栏相关的flag
View类提供了setSystemUiVisibility和getSystemUiVisibility方法,这两个方法实现对状态栏的动态显示或隐藏的操作,以及获取状态栏当前可见性。
setSystemUiVisibility(int visibility)方法可传入的实参为:
1. View.SYSTEM_UI_FLAG_VISIBLE:显示状态栏,Activity不全屏显示(恢复到有状态栏的正常情况)。
2. View.INVISIBLE:隐藏状态栏,同时Activity会伸展全屏显示。
3. View.SYSTEM_UI_FLAG_FULLSCREEN:Activity全屏显示,且状态栏被隐藏覆盖掉。
4. View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN:Activity全屏显示,但状态栏不会被隐藏覆盖,状态栏依然可见,Activity顶端布局部分会被状态遮住。
5. SYSTEM_UI_FLAG_LAYOUT_STABLE : 表示会让应用的主体内容占用系统状态栏的空间,必须和SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN配合使用.
6. View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION:效果同View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
7. View.SYSTEM_UI_LAYOUT_FLAGS:效果同View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
8. View.SYSTEM_UI_FLAG_HIDE_NAVIGATION:隐藏虚拟按键(导航栏)。有些手机会用虚拟按键来代替物理按键。
9. View.SYSTEM_UI_FLAG_LOW_PROFILE:状态栏显示处于低能显示状态(low profile模式),状态栏上一些图标显示会被隐藏。

如果想实现沉浸式模式,可以重写Activity的onWindowFocusChanged方法如下:

 @Override
 public void onWindowFocusChanged(boolean hasFocus) {
      super.onWindowFocusChanged(hasFocus);
      if (hasFocus && Build.VERSION.SDK_INT >= 19) {
          View decorView = getWindow().getDecorView();
          decorView.setSystemUiVisibility(
                  View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                          | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                          | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                          | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                          | View.SYSTEM_UI_FLAG_FULLSCREEN
                          | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);//状态栏粘性
      }
  }

这样就可以实现,界面默认情况下是全屏的,状态栏和导航栏都不会显示。而当我们需要用到状态栏或导航栏时,只需要在屏幕顶部向下拉,或者在屏幕底部向上拉,状态栏和导航栏就会显示出来
源码下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值