简化开发

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改小 很明显看到被状态栏遮挡了一部分)

上一篇下一篇

猜你喜欢

热点阅读