Android沉浸式和状态栏颜色的修改

一、前言

关于沉浸式实现的方法网上已经有很多了,但是也有点良莠不齐,在遇到实际项目中的问题之后还是需要查阅大量的博客来对问题进行查证。本博客主要是在解决沉浸式的几个问题之后,对沉浸式的一点总结方便后面再次遇到同样问题时,能够很快的查阅而不至于重头做起,也希望对你能够有帮助。

二、沉浸式的实现方法

沉浸式的实现方式有两种,一种是通过设置Theme来实现;另一种是在代码中进行实现。
2.1 通过设置Theme参考如下
在res目录下创建目录和文件,如果有的话则不用进行创建
values-v19/style.xml:对应api19+手机型号在此调用。
values-v21/style.xml:对应api21+手机型号在此调用。
values/style.xml:对应values-v19和values-v21的style.xml中没有对应主题时默认在此调用。
方法一:
values/style.xml

<style name="ImageTranslucentTheme" parent="AppTheme">
<!--Android 4.4之前的版本上运行,直接跟随系统主题-->

</style>

values-v19/style.xml

<style name="ImageTranslucentTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="android:windowTranslucentStatus">true</item>
    <item name="android:windowTranslucentNavigation">true</item>
</style>

values-v21/style.xml

<style name="ImageTranslucentTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="android:windowTranslucentStatus">false</item>
    <item name="android:windowTranslucentNavigation">true</item>
    <!--Android 5.x开始需要把颜色设置透明,否则导航栏会呈现系统默认的浅灰色-->
    <item name="android:statusBarColor">@android:color/transparent</item>
</style>

方法二
直接在values/style.xml中通过函数API进行区分

<style name="ColorTranslucentTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="android:windowTranslucentStatus" tools:targetApi="kitkat">true</item>
        <item name="android:windowTranslucentNavigation" tools:targetApi="kitkat">true</item>
        <item name="android:statusBarColor" tools:targetApi="lollipop">@android:color/transparent</item>
</style>

2.2 在代码中进行设置

/**
 * 通过设置全屏,设置状态栏透明
 *
 * @param activity
 */
private void fullScreen(Activity activity) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Window window = activity.getWindow();
            View decorView = window.getDecorView();
            //两个 flag 要结合使用,表示让应用的主体内容占用系统状态栏的空间
            int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
            decorView.setSystemUiVisibility(option);
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            //设置状态栏为透明,否则在部分手机上会呈现系统默认的浅灰色
            window.setStatusBarColor(Color.TRANSPARENT);
            //导航栏颜色也可以考虑设置为透明色
            //window.setNavigationBarColor(Color.TRANSPARENT);
        } else {
            Window window = activity.getWindow();
            WindowManager.LayoutParams attributes = window.getAttributes();
            int flagTranslucentStatus = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
            int flagTranslucentNavigation = WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
            attributes.flags |= flagTranslucentStatus;
//                attributes.flags |= flagTranslucentNavigation;
            window.setAttributes(attributes);
        }
    }
}

在代码中进行上述设置之后,页面会出现如下情况
这里写图片描述
页面中的toolbar挤到状态栏中去了,针对这种情况有两种解决办法,一种是通过在布局中设置android:fitsSystemWindows=”true”;另一种办法是获取状态栏高度之后,设置toolbar的paddingTop值,详情参考如下:
方案一
fitsSystemWindows属性的官方解释:

Boolean internal attribute to adjust view layout based on system windows such as the status bar. If true, adjusts the padding of this view to leave space for the system windows. Will only take effect if this view is in a non-embedded activity.

当设置为true时,会在屏幕最上方预留出状态栏高度的padding。
在布局中的设置代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    >
    <android.support.v7.widget.Toolbar
        android:id="@+id/toolBar"
        android:fitsSystemWindows="true" //ToolBar中设置
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="?attr/colorPrimary"
        app:theme="@style/ToolbarTheme"
        />
</LinearLayout>

方案二
首先通过反射获取状态栏高度

//Get status bar height
    public static int getStatusBarHeight(Context context) {
        int result = 0;
        int resId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resId > 0) {
            result = context.getResources().getDimensionPixelOffset(resId);
        }
        return result;
    }

在代码中设置Toolbar的paddingTop值,让它空出statusBar的高度

final int statusHeight = StatusBarCompat.getStatusBarHeight(this);
mToolBar.setPadding(0, statusHeight, 0, 0);

修正后的效果图如下:
这里写图片描述

三、状态栏颜色修改

Android在Android5.0之后提供了设置状态栏的颜色的函数,window.setStatusColor(@ColorInt int color),该方法生效的一个前提条件:是必须给window添加FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS并取消FLAG_TRANSLUCENT_STATUS,因此可以看到修改状态栏颜色的函数参考为如下:

 @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public static void setStatusBarColor(int statusColor, Activity activity) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Window window = activity.getWindow();
            //取消设置Window半透明的Flag
            window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            //添加Flag把状态栏设为可绘制模式
            window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            //设置状态栏为透明
            window.setStatusBarColor(Color.TRANSPARENT);
        }
    }

在Android6.0中新增了一个属性来修改状态栏的字体的颜色,在代码中参考如下:

View decor = window.getDecorView();
    int ui = decor.getSystemUiVisibility();
    if (lightStatusBar) {
        ui |=View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; //设置状态栏中字体的颜色为黑色
    } else {
        ui &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; //设置状态栏中字体颜色为白色
    }
    decor.setSystemUiVisibility(ui);

四、沉浸式状态栏设计备注

1.除非明确沉浸式页面不会有白色的背景框,否则建议不要在Android4.4-Android5.0的机型上考虑沉浸式的适配,因为如果状态栏被设置为透明色之后,显示为白色的背景会导致状态栏的字体和图标显示不清。
2.可以在项目中考虑使用第三方的沉浸式的实现。
参考文献
1.Android开发技巧–设置系统状态栏颜色
2.终于搞懂令人迷惑的 StatusBar 了
3.Android资源文件夹下面values/style.xml、values-v19/style.xml、values-v21/style.xml主题调用规则
4.Android修改状态栏颜色全方位教程
5.Android 沉浸式状态栏的实现

猜你喜欢

转载自blog.csdn.net/polo2044/article/details/81708196