如何实现沉浸式状态栏

前段时间项目中需要实现一个这样的功能,也是具体去研究了一下,趁着最近不是很忙,所以就整理了一个工具类XStatusBarHelper,也在这儿分享一下自己的实现方式。

何为沉浸式状态栏

简单的来说,就是状态栏可以改变颜色,不再是默认的黑色。或者状态栏是透明的,内容在状态栏下面。当然很多人也说这样不叫沉浸式状态栏,这个就不去深入研究了,先来看看我们最终想要的效果。

《如何实现沉浸式状态栏》 效果一:状态栏变色
《如何实现沉浸式状态栏》 效果二:状态栏透明全屏

如何实现

首先只有Android版本大于等于4.4才能够实现这样的效果,并且在4.4和5.0的上可以有不同的方式实现,这里我就讲一讲我是如何实现的。

效果一:状态栏变色

大致的思路就是设置状态栏透明,然后为根ViewGroup添加一个与状态栏相同高度的View,设置其颜色。

    /**
 * Android4.4以上的状态栏着色
 *
 * @param window         一般都是用于Activity的window,也可以是其他的例如Dialog,DialogFragment
 * @param statusBarColor 状态栏颜色
 * @param alpha          透明栏透明度[0.0-1.0]
 */
public static void tintStatusBar(Window window, @ColorInt int statusBarColor, @FloatRange(from = 0.0, to = 1.0)
        float alpha) {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
        return;
    }

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
        window.setStatusBarColor(Color.TRANSPARENT);
    } else {
        window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
    }

    ViewGroup decorView = (ViewGroup) window.getDecorView();
    ViewGroup contentView = (ViewGroup) window.getDecorView().findViewById(Window.ID_ANDROID_CONTENT);
    View rootView = contentView.getChildAt(0);
    if (rootView != null) {
        //设置为true后,布局会自动加上状态栏高度的距离
        ViewCompat.setFitsSystemWindows(rootView, true);
    }
    //设置一个状态栏
    setStatusBar(decorView, statusBarColor, true);
    //设置一个半透明效果,Material Design的效果
    setTranslucentView(decorView, alpha);
}

/**
 * 创建假的状态栏View
 */
private static void setStatusBar(ViewGroup container, @ColorInt int statusBarColor, boolean visible, boolean
        addToFirst) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        View statusBarView = container.findViewById(R.id.statusbar_view);
        if (statusBarView == null) {
            statusBarView = new View(container.getContext());
            statusBarView.setId(R.id.statusbar_view);
            ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(container.getContext()));
            if (addToFirst) {
                container.addView(statusBarView, 0, lp);
            } else {
                container.addView(statusBarView, lp);
            }
        }

        statusBarView.setBackgroundColor(statusBarColor);
        statusBarView.setVisibility(visible ? View.VISIBLE : View.GONE);
    }
}

效果二:全屏状态栏透明

/**
 * Android4.4以上的沉浸式全屏模式
 * <p>
 * 注:
 * 1.删除fitsSystemWindows属性:Android5.0以上使用该方法如果出现界面展示不正确,删除布局中所有fitsSystemWindows属性
 * 或者调用forceFitsSystemWindows方法
 * 2.不删除fitsSystemWindows属性:也可以区别处理,Android5.0以上使用自己的方式实现,不调用该方法
 *
 * @param window 一般都是用于Activity的window,也可以是其他的例如Dialog,DialogFragment
 * @param alpha  透明栏透明度[0.0-1.0]
 */
public static void immersiveStatusBar(Window window, @FloatRange(from = 0.0, to = 1.0) float alpha) {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
        return;
    }

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
        window.setStatusBarColor(Color.TRANSPARENT);

        int systemUiVisibility = window.getDecorView().getSystemUiVisibility();
        systemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
        systemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
        window.getDecorView().setSystemUiVisibility(systemUiVisibility);
    } else {
        window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
    }

    ViewGroup decorView = (ViewGroup) window.getDecorView();
    ViewGroup contentView = (ViewGroup) window.getDecorView().findViewById(Window.ID_ANDROID_CONTENT);
    View rootView = contentView.getChildAt(0);
    int statusBarHeight = getStatusBarHeight(window.getContext());
    if (rootView != null) {
        FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) rootView.getLayoutParams();
        ViewCompat.setFitsSystemWindows(rootView, true);
        lp.topMargin = -statusBarHeight;
        rootView.setLayoutParams(lp);
    }

    setTranslucentView(decorView, alpha);
}

详细的代码太多了,这里就不全部贴出来了,全部代码可到这儿查看XStatusBarHelper:https://github.com/fodroid/XStatusBarHelper

XStatusBarHelper使用

《如何实现沉浸式状态栏》 使用效果图

�快速集成

gradle

Add it in your root build.gradle at the end of repositories:

allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}

Add the dependency

dependencies {
    compile 'com.github.fodroid:XStatusBarHelper:v1.1'
}

maven

<repositories>
    <repository>
        <id>jitpack.io</id>
        <url>https://jitpack.io</url>
    </repository>
</repositories>

<dependency>
    <groupId>com.github.fodroid</groupId>
    <artifactId>XStatusBarHelper</artifactId>
    <version>v1.1</version>
</dependency>

具体调用代码

包含DrawerLayout

XStatusBarHelper.tintStatusBarForDrawer(this, drawer, getResources().getColor(R.color.colorPrimary));

效果一

XStatusBarHelper.tintStatusBar(this, getResources().getColor(R.color.colorPrimary));
//或者采用以下方式
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
XStatusBarHelper.forceFitsSystemWindows(this);
XStatusBarHelper.immersiveStatusBar(this);
XStatusBarHelper.setHeightAndPadding(this, toolbar);

效果二

Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
XStatusBarHelper.forceFitsSystemWindows(this);
XStatusBarHelper.immersiveStatusBar(this);
XStatusBarHelper.setHeightAndPadding(this, toolbar);

详细的调用方式,可以查看Github上面的例子:XStatusBarHelper

如果你觉得有用,请在Github不吝给我一个Star,非常感谢。

写在最后的话:个人能力有限,欢迎大家在下面吐槽。喜欢的话就为我点一个赞吧。也欢迎 Fork Me On Github 。

    原文作者:fodroid
    原文地址: https://www.jianshu.com/p/00fed1371bb0
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞