Android 4.4以上"沉浸式"狀態欄效果的實現方法

實現原理android

      從4.4後系統增長了透明狀態欄的特性WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
一旦添加上這個屬性後,那麼佈局中的內容DecorView就會自動填充到狀態欄。全部的實現都是基於這個特性,就至關於這個時候狀態欄會默認空出來,而後開發者能夠自定義view來填充這個高度的.windows

     實現的過程當中可能還要用到android:fitsSystemWindows="true" ,這個屬性很重要。其含義:view能夠根據系統窗口(如status bar,軟鍵盤)來調整本身的佈局,若是值爲true,就會調整view的paingding屬性來給system windows留出空間....佈局

那麼如今來看看具體實現方式吧學習

android,4.4,沉浸模式,android4.4狀態欄沉浸,沉浸式狀態欄
通常頁面都是本身定義個類標題欄ui

實現this

從實現效果上,這裏大體分爲兩種code

一、單獨給狀態欄着色對象

使用這個開源庫SystemBarTintblog

/**
  * 狀態欄顏色設置方法
  * @param context
  * @param color
  */
 public static void smartTintManager(Activity context, int color){
   if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
     Window window = context.getWindow();
     window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
     // 建立狀態欄的管理實例
     SystemBarTintManager tintManager = new SystemBarTintManager(context);
     // 激活狀態欄設置
     tintManager.setStatusBarTintEnabled(true);
     tintManager.setStatusBarTintColor(color);
   }
 }

在對應的頁面的根佈局中添加android:fitsSystemWindows="true" ,且根佈局中不能設置總體的大背景色,不然狀態欄着色就會被覆蓋開發

調用上面方法設置具體的顏色(依據開源庫,其中就一個核心類,能夠直接把那個類拷貝到項目中)

這裏主要講一下具體的實現原理

private void setupStatusBarView(Context context, ViewGroup decorViewGroup) {
   mStatusBarTintView = new View(context);
   LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, mConfig.getStatusBarHeight());
   params.gravity = Gravity.TOP;
   if (mNavBarAvailable && !mConfig.isNavigationAtBottom()) {
     params.rightMargin = mConfig.getNavigationBarWidth();
   }
   mStatusBarTintView.setLayoutParams(params);
   mStatusBarTintView.setBackgroundColor(DEFAULT_TINT_COLOR);
   mStatusBarTintView.setVisibility(View.GONE);
   decorViewGroup.addView(mStatusBarTintView);
 }

經過這段代碼,很容易看出,經過動態生成一個view,而後這個view寬是MATCH_PARENT , 高度是系統狀態欄的高度;而後爲這個動態生成的view設置一個背景顏色;最後將這個view添加到decorViewGroup這個view容器中,那再看看這個view究竟是誰

/**
  * Constructor. Call this in the host activity onCreate method after its
  * content view has been set. You should always create new instances when
  * the host activity is recreated.
  *
  * @param activity The host activity.
  */
 @TargetApi(19)
 public SystemBarTintManager(Activity activity) {

   Window win = activity.getWindow();
   //得到DecorView根佈局容器
   ViewGroup decorViewGroup = (ViewGroup) win.getDecorView(); 
   ..... 
   if (mStatusBarAvailable) {
     // 這個view容器是decorViewGroup
     setupStatusBarView(activity, decorViewGroup);
   }
   if (mNavBarAvailable) {
     setupNavBarView(activity, decorViewGroup);
   }

 }

注意看上面兩個我手動添加的註釋,可見,這種作法思想就是狀態欄透明後,向根佈局decorViewGroup中添加一個和狀態欄等高度的view。至於你讓這個view是什麼顏色,那就隨你心情了。

二、用標題欄的背景色來填充狀態欄

將狀態欄設置爲半透明的,此時出現的問題是下面的內容會佔據了狀態欄。

若是咱們在activity的根佈局添加 android:fitsSystemWindows="true"

那麼此時狀態欄仍是能夠看見的,並無佔據。那這個屬性的做用就在此了。

此時咱們藉助狀態欄的高度,爲下面的內容設置一個padding-top距離(由於狀態欄半透明後,下面的內容會佔據原有的狀態欄,那麼將其設置一個padding的狀態欄高度便可)這樣設置後,在這個view的背景的padding下,原有的狀態欄高度填充了一樣的背景色,那麼這樣的話就貌似所謂的沉浸式了

這種方式說白了,就是狀態欄半透明後,用下面的內容來合適的填充(由於默認半透明會是被佔據)

代碼以下:

@SuppressLint("InlinedApi")
public static void setImmerseLayout(Activity context, View view) {
  if (context == null || view == null) {
    return;
  }
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    Window window = context.getWindow();
    window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
        WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
    int statusBarHeight = getStatusBarHeight(context.getBaseContext());
    view.setPadding(0, statusBarHeight, 0, 0);
  }
}

/**
 * 用於獲取狀態欄的高度。 使用Resource對象獲取(推薦這種方式)
 *
 * @return 返回狀態欄高度的像素值。
 */
public static int getStatusBarHeight(Context context) {
  int result = 0;
  int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
  if (resourceId > 0) {
    result = context.getResources().getDimensionPixelSize(resourceId);
  }
  return result;
}

對這個view設置一個padding_top,而這個padding的距離恰好是狀態欄的高度,那麼這個view的背景就填充到了狀態欄了。

值得注意的是:這個標題欄的高度必定要是wrap_content,由於若是是具體的高度,而後在設置個paddingtop的話,那麼就會把部分標題欄的內容擠出去了,不完整了。

因此一般的作法是將原有的標題欄外面在嵌套一個<FrameLayout /> ,而後將標題欄背景設置成<FrameLayout />的背景色

<FrameLayout
   android:id="@+id/title"
   android:layout_width="match_parent"
   android:background="@color/common_theme_color"
   android:layout_height="wrap_content">

總結

關於沉浸式效果的實現方式就到這了,但願這篇文章的內容對你們的學習或者工做能帶來必定的幫助,若是有疑問你們也能夠留言交流。

相關文章
相關標籤/搜索