應用隱藏導航欄
工具類
public class HideNavBarUtil {
public static void hideBottomUIMenu(View v) {
//隱藏虛擬按鍵,并且全屏
if (Build.VERSION.SDK_INT > 11 && Build.VERSION.SDK_INT < 19) { // lower api
v.setSystemUiVisibility(View.GONE);
} else if (Build.VERSION.SDK_INT >= 19) {
//for new api versions.
int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY ;
v.setSystemUiVisibility(uiOptions);
}
}
//調(diào)起輸入法 用于隱藏輸入法后隱藏導航欄
public static void hideWhenSystemUiVisible(View v){
v.setOnSystemUiVisibilityChangeListener(visibility -> {
if(visibility==View.SYSTEM_UI_FLAG_VISIBLE){
hideBottomUIMenu(v);
}
});
}
/**
*spinner里也有popwindow 會調(diào)起導航欄
* @param spinner 嘗試隱藏spinner彈出時的導航欄
*/
public static void hideSpinnerSystemUi(Spinner spinner){
Field mPopup = null;
try {
mPopup = spinner.getClass().getDeclaredField("mPopup");
mPopup.setAccessible(true);
ListPopupWindow listPopupWindow = (ListPopupWindow) mPopup.get(spinner);
Field mPopup1 = listPopupWindow.getClass().getSuperclass().getDeclaredField("mPopup");
mPopup1.setAccessible(true);
PopupWindow popupWindow = (PopupWindow) mPopup1.get(listPopupWindow);
popupWindow.setFocusable(false);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Activity
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if(hasFocus){
HideNavBarUtil.hideBottomUIMenu(getWindow().getDecorView());
}
}
DialogFragment
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
/**
* 項目中的CartView 當作普同fragment使用 不會創(chuàng)建dialog
*/
if (getShowsDialog()) {
//not focus 來避免瞬間彈出
getDialog().getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
HideNavBarUtil.hideWhenSystemUiVisible(getDialog().getWindow().getDecorView());
HideNavBarUtil.hideBottomUIMenu(getDialog().getWindow().getDecorView());
//重新設置可獲取焦點 避免彈不出鍵盤
getDialog().getWindow().getDecorView().post(() -> getDialog().getWindow().setFlags(~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE));
}
}
PopWindow
@Override
public void showAtLocation(View parent, int gravity, int x, int y) {
////not focus 來避免瞬間彈出
setFocusable(false);
//這里高設置MATCH_PARENT 默認WRAP 避免下層的activity顯示上來
setHeight(WindowManager.LayoutParams.MATCH_PARENT);
super.showAtLocation(parent, gravity, x, y);
final View contentView = getContentView();
HideNavBarUtil.hideBottomUIMenu(contentView);
setFocusable(true);
update();
}

image-20190222104734937.png

image-20190222104900143.png
DecorView重寫了onApplyWindowInsets方法
WindowInsets分發(fā)機制:從頂層view開始分發(fā) 直到其中的mSystemWindowInsets 和mStableInsets 被消費則完成分發(fā)
DecorView的updateColorViews方法會根據(jù)設置的systemUiVisibility 判斷是否消耗導航欄 通過設置mContentRoot的margin值(嘗試改這個margin值 可以看到content與導航欄狀態(tài)欄距離就會) ,導航欄的和狀態(tài)欄的顏色及動畫可以看updateColorViewInt方法中的邏輯
View的 fitSystemWindowsInt方法,如果view 設置了FITS_SYSTEM_WINDOWS 會去計算padding值 設置View的padding(嘗試把decorview下第一個字view top改小 很明顯看到被狀態(tài)欄遮擋了一部分)