Android沉浸式狀態列還能這樣玩—教你玩出新花樣

codeGoogle發表於2019-03-04

專案中我們有時候都要用的透明狀態列(這裡也成沉浸式狀態列),今天介紹一個gyf-dev寫的一個封裝狀態列開源框架

效果圖如下:

沉浸式進行測試
沉浸式進行測試

解決白色狀態列問題
解決白色狀態列問題

正文

從Android4.4開始,才可以實現狀態列著色,並且從5.0開始系統更加完善了這一功能。之前寫過關於一篇 關於activity狀態列的一些總結
有關Activity樣式 、狀態列透明、螢幕亮度問題應用場景及其總結

說明

  • 這是狀態列

    這是狀態列
    這是狀態列

  • 這是導航欄(有些手機沒有導航欄)

    導航欄
    導航欄

動態圖

  • 第一種方案: 可直接在主題中設定

      getWindow().setBackgroundDrawable(null);
          //設定透明狀態列
          ViewGroup contentFrameLayout = (ViewGroup) findViewById(Window.ID_ANDROID_CONTENT);
          View parentView = contentFrameLayout.getChildAt(0);
          if (parentView != null && Build.VERSION.SDK_INT >= 14) {
              parentView.setFitsSystemWindows(true);
          }複製程式碼

    或者也可以這樣 :

  • 第二種方案:

將佈局延伸到狀態列來處理,這次我們使用android:fitsSystemWindows=”true”屬性,不讓佈局延伸到狀態列,這時狀態列就是透明的,然後新增一個和狀態列高、寬相同的指定顏色View來覆蓋被透明化的狀態列。我們一步步來實現。

1、第一步還是先將狀態列透明化,方法同上。
2、在佈局檔案中新增android:fitsSystemWindows=”true”屬性:

集合actionBar的使用.gif
集合actionBar的使用.gif

封裝:

 ImmersionBar.with(this)
             .transparentStatusBar()  //透明狀態列,不寫預設透明色
             .transparentNavigationBar()  //透明導航欄,不寫預設黑色(設定此方法,fullScreen()方法自動為true)
             .transparentBar()             //透明狀態列和導航欄,不寫預設狀態列為透明色,導航欄為黑色(設定此方法,fullScreen()方法自動為true)
             .statusBarColor(R.color.colorPrimary)     //狀態列顏色,不寫預設透明色
             .navigationBarColor(R.color.colorPrimary) //導航欄顏色,不寫預設黑色
             .barColor(R.color.colorPrimary)  //同時自定義狀態列和導航欄顏色,不寫預設狀態列為透明色,導航欄為黑色
             .statusBarAlpha(0.3f)  //狀態列透明度,不寫預設0.0f
             .navigationBarAlpha(0.4f)  //導航欄透明度,不寫預設0.0F
             .barAlpha(0.3f)  //狀態列和導航欄透明度,不寫預設0.0f
             .statusBarDarkFont(true)   //狀態列字型是深色,不寫預設為亮色
             .flymeOSStatusBarFontColor(R.color.btn3)  //修改flyme OS狀態列字型顏色
             .fullScreen(true)      //有導航欄的情況下,activity全屏顯示,也就是activity最下面被導航欄覆蓋,不寫預設非全屏
             .hideBar(BarHide.FLAG_HIDE_BAR)  //隱藏狀態列或導航欄或兩者,不寫預設不隱藏
             .addViewSupportTransformColor(toolbar)  //設定支援view變色,可以新增多個view,不指定顏色,預設和狀態列同色,還有兩個過載方法
             .titleBar(view)    //解決狀態列和佈局重疊問題,任選其一
             .statusBarView(view)  //解決狀態列和佈局重疊問題,任選其一
             .fitsSystemWindows(true)    //解決狀態列和佈局重疊問題,任選其一,預設為false,當為true時一定要指定statusBarColor(),不然狀態列為透明色
             .supportActionBar(true) //支援ActionBar使用
             .statusBarColorTransform(R.color.orange)  //狀態列變色後的顏色
             .navigationBarColorTransform(R.color.orange) //導航欄變色後的顏色
             .barColorTransform(R.color.orange)  //狀態列和導航欄變色後的顏色
             .removeSupportView(toolbar)  //移除指定view支援
             .removeSupportAllView() //移除全部view支援
             .navigationBarEnable(true)   //是否可以修改導航欄顏色,預設為true
             .navigationBarWithKitkatEnable(true)  //是否可以修改安卓4.4和emui3.1手機導航欄顏色,預設為true
             .fixMarginAtBottom(true)   //當xml裡使用android:fitsSystemWindows="true"屬性時,解決4.4和emui3.1手機底部有時會出現多餘空白的問題,預設為false,非必須
             .addTag("tag")  //給以上設定的引數打標記
             .getTag("tag")  //根據tag獲得沉浸式引數
             .reset()  //重置所以沉浸式引數
             .keyboardEnable(true)  //解決軟鍵盤與底部輸入框衝突問題,預設為false,還有一個過載方法,可以指定軟鍵盤mode
             .init();  //必須呼叫方可沉浸式複製程式碼

使用方式

  • 第一步:基礎用法(已經可以滿足日常沉浸式)
    ImmersionBar.with(this).init();複製程式碼
  • 第二步

在activity的onDestroy方法中執行

ImmersionBar.with(this).destroy(); //不呼叫該方法,如果介面bar發生改變,在不關閉app的情況下,退出此介面再進入將記憶最後一次bar改變的狀態複製程式碼
  • 建議
    建議在BaseActivity中初始化和銷燬,可以參看demo中
    BaseActivity

    public class BaseActivity extends AppCompatActivity {
    
       private ImmersionBar mImmersionBar;
       @Override
       protected void onCreate(@Nullable Bundle savedInstanceState) {
           super.onCreate(savedInstanceState);
         mImmersionBar = ImmersionBar.with(this);
         mImmersionBar.init();   //所有子類都將繼承這些相同的屬性
    
       }
    
       @Override
       protected void onDestroy() {
           super.onDestroy();
           mImmersionBar.destroy();  //不呼叫該方法,如果介面bar發生改變,在不關閉app的情況下,退出此介面再進入將記憶最後一次bar改變的狀態
       }
    }複製程式碼

    可以結合webView
    可以結合webView

沉浸式fragment
沉浸式fragment

  • 如何 隱藏導航欄或狀態列
    /**
       * 隱藏導航欄或狀態列
       *
       * @param barHide the bar hide
       * @return the immersion bar
       */
      public ImmersionBar hideBar(BarHide barHide) {
          mBarParams.barHide = barHide;
          if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT || OSUtils.isEMUI3_1()) {
              if ((mBarParams.barHide == BarHide.FLAG_HIDE_NAVIGATION_BAR) ||
                      (mBarParams.barHide == BarHide.FLAG_HIDE_BAR)) {
                  mBarParams.navigationBarColor = Color.TRANSPARENT;
                  mBarParams.fullScreenTemp = true;
              } else {
                  mBarParams.navigationBarColor = mBarParams.navigationBarColorTemp;
                  mBarParams.fullScreenTemp = false;
              }
          }
          return this;
      }複製程式碼

    部分問題

解決華為emui3.0或者3.1手機手動隱藏導航欄按鈕時,導航欄背景未被隱藏的問題

什麼叫做手動隱藏,就是下圖中標紅的向下隱藏按鈕

第一種解決方案,監聽華為虛擬按鈕,建議在baseActivity裡使用

 @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        immersionBar = ImmersionBar.with(this);
        immersionBar.init();
        if (OSUtils.isEMUI3_1())  //解決華為emui3.0與3.1手機手動隱藏底部導航欄時,導航欄背景色未被隱藏的問題
            getContentResolver().registerContentObserver(Settings.System.getUriFor
                    ("navigationbar_is_min"), true, mNavigationStatusObserver);
    }

    private ContentObserver mNavigationStatusObserver = new ContentObserver(new Handler()) {
        @Override
        public void onChange(boolean selfChange) {
            int navigationBarIsMin = Settings.System.getInt(getContentResolver(),
                    "navigationbar_is_min", 0);
            if (navigationBarIsMin == 1) {
                //導航鍵隱藏了
                immersionBar
                        .transparentNavigationBar()
                        .init();
            } else {
                //導航鍵顯示了
                immersionBar
                        .navigationBarColor(android.R.color.black)
                        .fullScreen(false)
                        .init();
            }
        }
    };複製程式碼
  • 第二種解決方案,禁止對導航欄相關設定
    ImmersionBar.with(this)
                     .navigationBarEnable(false)   //禁止對導航欄相關設定
                   //或者
                   // .navigationBarWithKitkatEnable(false)  //禁止對4.4裝置導航欄相關設定
                     .init();複製程式碼

    android 6.0 有導航欄效果

 6.0 有導航欄效果
6.0 有導航欄效果

專案地址:

github.com/androidstar…

gyf-dev的部落格地址:

github.com/gyf-dev/Imm…

部落格地址:

blog.csdn.net/androidstar…

如果你覺得此文對您有所幫助,歡迎入群 QQ交流群 :232203809
微信公眾號:終端研發部

職場+技術
職場+技術

相關文章