如何實現沉浸式狀態欄

前段時間項目中需要實現一個這樣的功能,也是具體去研究了一下,趁著最近不是很忙,所以就整理了一個工具類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 。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,818評論 25 708
  • 今日去市里開人才新政會議,午休有時間,還去感受了下臺州人力網的14周年會現場。二個會議,有個共同的東西讓我深深...
    無憂俠閱讀 130評論 0 0
  • 本文源自 Salman Khan 對 Elon Musk 四年前的一次 Chat,也是 Khan Academy ...
    馬文Marvin閱讀 1,210評論 2 0
  • 這幾天已經慢慢習慣早上一起床就aom,然后就是聲音練習,從無聲到有聲,無聲包括發si音、長短交替si音、狗喘氣、打...
    云淡風輕一閱讀 95評論 0 0
  • 今天,我和楠哥又吵架了。 其實不是什么大不了的事情,只是因為他在玩兒游戲,而我想他陪我出去晃蕩。 好難過啊,感覺楠...
    熊師娘閱讀 354評論 8 12