Android应用隐藏导航栏
2019-04-30 本文已影响0人
Youremywoman
应用隐藏导航栏
工具类
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);
}
}
//调起输入法 用于隐藏输入法后隐藏导航栏
public static void hideWhenSystemUiVisible(View v){
v.setOnSystemUiVisibilityChangeListener(visibility -> {
if(visibility==View.SYSTEM_UI_FLAG_VISIBLE){
hideBottomUIMenu(v);
}
});
}
/**
*spinner里也有popwindow 会调起导航栏
* @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使用 不会创建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分发机制:从顶层view开始分发 直到其中的mSystemWindowInsets 和mStableInsets 被消费则完成分发
DecorView的updateColorViews方法会根据设置的systemUiVisibility 判断是否消耗导航栏 通过设置mContentRoot的margin值(尝试改这个margin值 可以看到content与导航栏状态栏距离就会) ,导航栏的和状态栏的颜色及动画可以看updateColorViewInt方法中的逻辑
View的 fitSystemWindowsInt方法,如果view 设置了FITS_SYSTEM_WINDOWS 会去计算padding值 设置View的padding(尝试把decorview下第一个字view top改小 很明显看到被状态栏遮挡了一部分)