關於android透明狀態列總結

xingstarx發表於2018-01-18

主要程式碼

網上資料太多,將這塊的內容也不少,無論是知乎,簡書,還是github上的,這裡只針對我所處理的專案

貼上一下我覺得關鍵的程式碼,處理TRANSLUCENT的,使之成為透明主題,SystemBarTintManager來自SystemBarTint

@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_match_actionbar);

		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
			setTranslucentStatus(true);
		}

		SystemBarTintManager tintManager = new SystemBarTintManager(this);
		tintManager.setStatusBarTintEnabled(true);
		tintManager.setStatusBarTintResource(R.color.statusbar_bg);

	}

	@TargetApi(19) 
	private void setTranslucentStatus(boolean on) {
		Window win = 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);
	}
複製程式碼

設定fitsSystemWindows,讓xml佈局內容位於狀態列之下,當然了這塊的程式碼可以做一下進一步的封裝

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(getLayoutResId());//把設定佈局檔案的操作交給繼承的子類
        ViewGroup contentFrameLayout = (ViewGroup) findViewById(Window.ID_ANDROID_CONTENT);
        View parentView = contentFrameLayout.getChildAt(0);
        if (parentView != null && Build.VERSION.SDK_INT >= 14) {
            parentView.setFitsSystemWindows(true);
        }
    }
複製程式碼

這段程式碼來自AndroidSystemUiTraining 做了一定的封裝,這樣就不需要我們在每個xml的root節點裡面加上android:fitsSystemWindows = 'true'

對於透明主題,我們需要做的就是,修改window的主題,然後修改狀態列顏色值,android4.4的版本稍微特殊,可以通過其他的方式實現修改狀態列的顏色,4.4以下無法修改顏色,5.0以上的可以通過系統api,修改statusBarColor。 修改為了透明主題後,預設情況下,我們的佈局是佔滿全屏區域的,那麼我們的xml佈局是會遮擋住statusbar的(擋住一詞有點不準確,應該說是佔據了statusbar的位置)。

有兩種解決辦法,一種是如上述的程式碼中,設定findViewById(Window.ID_ANDROID_CONTENT).getChildAt(0).setFitsSystemWindows(true),這樣強制的讓佈局內容從狀態列下面開始,狀態列以上的顯示的是SystemBarTintManager.setStatusBarTintResource(R.color.statusbar_bg)設定的顏色

另外一種是不設定setFitsSystemWindows(true),xml佈局佔滿全屏,通過一個高度為25dp的view,佔滿狀態列的位置,用paddingTop也可以實現,可以針對具體情況處理,具體可以看知乎上的這篇https://www.zhihu.com/question/31468556,第一個答案

優化後

本文優化後的程式碼主要是這兩種方式混用的,針對不同的頁面採用不同的方案。

 //呼叫此方法,當前activity將變成translucent主題,content區域包含全屏,statusBarRes用來設定狀態列顏色值,isFitSystemWindows設定是否需要讓xml佈局內容位於狀態列之下,預設是在狀態列下面
    open fun setupStatusBar(@ColorRes statusBarRes: Int, isFitSystemWindows: Boolean = true) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            window.setFlags(
                    WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
                    WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
            SystemBarTintManager(this).apply {
                isStatusBarTintEnabled = true
                setStatusBarTintResource(statusBarRes)
            }
        }
        if (isFitSystemWindows) {
            val contentFrameLayout = findViewById(Window.ID_ANDROID_CONTENT) as ViewGroup
            val parentView = contentFrameLayout.getChildAt(0)
            if (parentView != null && Build.VERSION.SDK_INT >= 14) {
                parentView.fitsSystemWindows = true
            }
        }
    }
複製程式碼

子類只需要重寫這個方法,就可以滿足常見的場景需求了。

相關可以參考的資料

AndroidSystemUiTraining SystemBarTint

相關文章