Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 沉浸式狀態欄那些事兒

沉浸式狀態欄那些事兒

編輯:關於Android編程

一、什麼是沉浸式狀態欄

首先請讓我們看看沒有使用沉浸式的效果:

上面這張圖是沒有使用沉浸式的美團外賣,我們可以看到最上面的黑色的那一條就是狀態欄,大部分android默認是黑色底,白色字。

好了,下面讓我祭出使用了沉浸式以後的效果圖:

說回來吧,狀態欄(系統)跟我們的app的標題欄的顏色融為一體,非常美觀大方得體。而這樣就是我今天要介紹的效果。

這裡需要注意的的是:ISO很早以前原生就支持了沉浸式狀態欄,但是android要到API 19以上才有了支持,也就是說,API 19以下的手機是不能兼容的。如果你們的項目經理叫你們去適配API 19以下的手機,那你就可以告訴他唯一的解決的辦法就是要用戶去買一台API 19以上的手機,哈哈!

為了能夠和ISO盡量統一風格,為了更加美觀大方,我們還是有必要學習一下沉浸式的實現方法。

二、沉浸式狀態欄的實現方式

方式1:布局的內容不進入狀態欄

這種方法主要是通過GitHub上面的一個開源庫實現,下面讓我原汁原味貼出項目的源碼:

//需要引入的類庫
compile 'com.readystatesoftware.systembartint:systembartint:1.0.4'

import android.annotation.TargetApi;
import android.app.Activity;
import android.os.Build;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;

import com.readystatesoftware.systembartint.SystemBarTintManager;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * 設置狀態欄顏色的工具類
 */
public class TintBarUtils {

    /**
     * 設置activity的狀態欄顏色,注意需要在activity的布局當中添加屬性:android:fitsSystemWindows="true"
     *
     * @param activity
     * @param statusBarTintColor
     */
    public static void setStatusBarTintColor(Activity activity, int statusBarTintColor) {

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            setTranslucentStatus(true, activity);
            SystemBarTintManager mTintManager = new SystemBarTintManager(activity);
            mTintManager.setStatusBarTintEnabled(true);
            mTintManager.setNavigationBarTintEnabled(true);
            mTintManager.setTintColor(statusBarTintColor);

            setStatusBarTextStyle(activity, true);
        }
    }

    public static void setStatusBarTextStyle(Activity activity, boolean lightMode) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (lightMode) {
                activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
            }
        } else {
            MIUISetStatusBarLightMode(activity.getWindow(), lightMode);
            FlymeSetStatusBarLightMode(activity.getWindow(), lightMode);
        }
    }

    @TargetApi(19)
    private static void setTranslucentStatus(boolean on, Activity activity) {
        Window win = activity.getWindow();
        WindowManager.LayoutParams winParams = win.getAttributes();
        final int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
        if (on) {
            winParams.flags |= bits;
        } else {
            winParams.flags &= ~bits;
        }
        win.setAttributes(winParams);
    }

    @TargetApi(19)
    public static void hideStatusBar(Activity activity) {

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {

            setTranslucentStatus(false, activity);

            SystemBarTintManager mTintManager = new SystemBarTintManager(activity);
            mTintManager.setStatusBarTintEnabled(false);
            mTintManager.setNavigationBarTintEnabled(false);

            Window win = activity.getWindow();
            WindowManager.LayoutParams winParams = win.getAttributes();
            final int bits = WindowManager.LayoutParams.FLAG_FULLSCREEN;
            winParams.flags &= ~bits;
            win.setAttributes(winParams);
        }
    }

    /**
     * 設置狀態欄圖標為深色和魅族特定的文字風格 * 可以用來判斷是否為Flyme用戶 * @param window 需要設置的窗口 * @param dark 是否把狀態欄字體及圖標顏色設置為深色 * @return boolean 成功執行返回true *
     */
    public static boolean FlymeSetStatusBarLightMode(Window window, boolean dark) {
        boolean result = false;
        if (window != null) {
            try {
                WindowManager.LayoutParams lp = window.getAttributes();
                Field darkFlag = WindowManager.LayoutParams.class.getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON");
                Field meizuFlags = WindowManager.LayoutParams.class.getDeclaredField("meizuFlags");
                darkFlag.setAccessible(true);
                meizuFlags.setAccessible(true);
                int bit = darkFlag.getInt(null);
                int value = meizuFlags.getInt(lp);
                if (dark) {
                    value |= bit;
                } else {
                    value &= ~bit;
                }
                meizuFlags.setInt(lp, value);
                window.setAttributes(lp);
                result = true;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 設置狀態欄字體圖標為深色,需要MIUIV6以上
     *
     * @param window 需要設置的窗口
     * @param dark   是否把狀態欄字體及圖標顏色設置為深色
     * @return boolean 成功執行返回true
     */
    public static boolean MIUISetStatusBarLightMode(Window window, boolean dark) {
        boolean result = false;
        if (window != null) {
            Class clazz = window.getClass();
            try {
                int darkModeFlag = 0;
                Class layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
                Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
                darkModeFlag = field.getInt(layoutParams);
                Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
                if (dark) {
                    extraFlagField.invoke(window, darkModeFlag, darkModeFlag);//狀態欄透明且黑色字體 }else{ extraFlagField.invoke(window, 0, darkModeFlag);//清除黑色字體 } result=true; }catch (Exception e){ } } return result; }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return result;
    }

}

這裡需要特別強調一點就是activity布局文件中的跟布局必須有下面這個屬性,否則我們的設置是沒有效果的:

android:fitsSystemWindows="true"

我們要關注的核心方法是setStatusBarTintColor,這個方法需要傳入一個Activity對象,以及顏色值,即可設置狀態欄的顏色。需要注意的是這個方法需要判斷當前的API版本是不是大於19才能使用。至於具體的實現,大家可以仔細看源碼。這裡只強調如何快速使用到你的項目當中。

但是這裡有一個尴尬的問題就是:當我們的APP標題欄是白色的時候,例如上面的第二張圖,如果我們設置了白色的狀態欄,那麼狀態辣女白色的文字將會看不到。解決的辦法比較棘手,我當時也是懵逼了好久,在項目經理的重壓之下還是找到了解決方案。在android M也就是API23以上,google官方提供了設置狀態欄文字風格的方法:

activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);

為了向下兼容,小米和魅族兩個品牌由於深度定制過android的ROM,都提供了通過反射的方式是改變狀態欄的文字顏色。他們分別是:
MIUISetStatusBarLightMode和FlymeSetStatusBarLightMode,通過傳入的參數dark為true就可改變狀態欄文字顏色,至於怎麼改變,大家可以親自嘗試一下,這裡不再啰嗦。

方式2:布局的內容進入狀態欄

如上面第三張圖所示,我們的contentView進入了狀態欄,這又是怎麼實現的呢?其實很簡單,只要把我們的布局延伸到狀態欄,並且添加一個高度為狀態欄高度的View(status_bar_top)或者上Padding即可。

protected int statusBarHeight;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    immerseLayout();
}

protected void immerseLayout() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        Window window = getWindow();
        window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        statusBarHeight = getStatusBarHeight(this.getBaseContext());
        viewStatusBarTop = findViewById(R.id.status_bar_top);
        RelativeLayout.LayoutParams params2 = (RelativeLayout.LayoutParams) viewStatusBarTop.getLayoutParams();
        params2.height = statusBarHeight;
        viewStatusBarTop.setLayoutParams(params2);
        viewStatusBarTop.setVisibility(View.VISIBLE);
    }
}

public int getStatusBarHeight(Context context) {
    if (statusBarHeight != 0)
        return statusBarHeight;

    int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
    if (resourceId > 0) {
        statusBarHeight = context.getResources().getDimensionPixelSize(resourceId);
    }
    return statusBarHeight;
}

下面給出這個activity的布局文件

<relativelayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:fitssystemwindows="false">

    <view android:id="@+id/status_bar_top" android:layout_width="match_parent" android:layout_height="0dp" android:layout_alignparenttop="true" android:background="@drawable/status_bar" android:visibility="gone">

    。。。這裡是我們的布局         

</view></relativelayout>
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved