作爲Android開發,在解決4.4沉浸式狀態欄遇到挺多問題的,這裏列出我自己的解決方案,僅供參考。
首先是主題的配置:
默認主題 styles配置:
<style name="AppTheme" parent="android:Theme.Light">
<item name="windowNoTitle">true</item>
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
v19以及以上版本主題 styles配置:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
這裏屬性windowTranslucentStatus和windowTranslucentNavigation很重要,不然自定義的沉浸式狀態欄無效。
然後就是佈局文件中的屬性:
android:fitsSystemWindows="true"
該屬性如果不設置的話,那麼就需要完全自定義StatusBar和NavigationBar。
這裏我的解決方案是自定義一個BaseActivity類。裏邊預設一個沉浸式菜單樣式。列出部分代碼。
初始化一個系統狀態欄。
/**
* @param color 頂部狀態欄顏色
* @param alpha 頂部狀態欄透明度
*/
public void initSystemBar(int color, float alpha) {
if (mTintManager == null) {
mTintManager = new SystemBarTintManager(this);
setTranslucentStatus(true);
try {
Field field = mTintManager.getClass().getDeclaredField("mNavBarAvailable");
field.setAccessible(true);
Object obj = field.get(mTintManager);
mNavBarAvailable = obj instanceof Boolean ? (Boolean) obj : false;
Field field1 = mTintManager.getClass().getDeclaredField("mNavBarTintView");
field1.setAccessible(true);
Object view = field1.get(mTintManager);
mNavBarTintView = view instanceof View ? (View) view : null;
if(mNavBarTintView!=null){
mNavBarTintView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
if(navBarLayoutChangeListener!=null)
navBarLayoutChangeListener.onLayoutChange(v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom);
}
});
}
} catch (Exception e) {
e.printStackTrace();
}
}
mTintManager.setStatusBarTintEnabled(true);
mTintManager.setNavigationBarTintEnabled(true);
mTintManager.setStatusBarAlpha(alpha);
mTintManager.setStatusBarTintColor(getResources().getColor(color));
mTintManager.setNavigationBarAlpha(mNavBarAvailable && navVisiablity == View.VISIBLE ? 1.0f : 0.0f);
mTintManager.setNavigationBarTintColor(getResources().getColor(R.color.colorPrimaryDark));//底部狀態欄默認顏色
}
順便列出對於部分手機底部狀態欄可隱藏解決方法。如果有比較好的方法可以告訴我。我這裏主要是寫一個死循環定期去檢測底部狀態欄(應該不是很好),所以做了一定的處理,獲取底部狀態欄是否可用,如果不可用就不啓動死循環檢測。雖然網上有很多方法說去檢測狀態欄可見性,但是好像沒什麼效果。
在onResume方法啓動檢測。
@Override
protected void onResume() {
super.onResume();
initSystemBar(R.color.colorPrimaryDark);
startNavBarTask();
}
在onPause方法暫停檢測。
@Override
protected void onPause() {
super.onPause();
onPauseNaBarTask();
}
在onDestroy方法停止檢測。
@Override
protected void onDestroy() {
super.onDestroy();
cancelNaBarTask();
}
對於自定義頂部狀態欄,我們只需要根據Android手機版本確定是否展示即可:
//根據版本確定是否顯示StatusBar狀態欄 系統版本大於等於19才顯示
statusBar.setVisibility(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT ? View.VISIBLE : View.GONE);
對於自定義底部狀態欄添加監聽:(該方法是在BaseActivity中定義的,就是剛剛那個檢測任務回調,當底部狀態欄改變時)
//添加NavigationBar可見性監聽
addNavBarVisiableChangeListener(new NavBarVisiableChangeListener() {
@Override
public void onNavBarVisiableChange(View navBarView, int visibility) {
if (navigationBar != null) {
navigationBar.setVisibility(visibility == View.VISIBLE ? View.VISIBLE : View.GONE);
}
}
});
當然這裏還做了自定義底部狀態欄高度檢測,主要是有些手機狀態欄高度不同,必須要做(網上有很多方法,但是都不太靠譜,這裏我通過監聽底部狀態視圖佈局變化來實現的)
//設置NavigationBar佈局監聽,這裏主要是因爲系統的狀態欄不同手機高度不同,所以要監聽
setNavBarLayoutChangeListener(new NavBarLayoutChangeListener() {
@Override
public void onLayoutChange(View navBarView, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
int navHeight = navBarView.getMeasuredHeight();
int height = navigationBar.getMeasuredHeight();
if (navHeight > 0 && navHeight != height) {
ViewGroup.LayoutParams lp = navigationBar.getLayoutParams();
if (lp != null)
lp.height = navHeight;
}
}
});
差不多核心代碼都列出來,同時可以參考我自己做的一個demo。
github地址:https://github.com/ttarfall/StatusBarDemo.git