android 判断虚拟导航栏是否在屏幕上显示,适用于Lollipop 5.0 ~ Oreo 8.1.0

# 写在前面

找了两天的判断方法,都是通过屏幕真实高度和内容高度作对比来判断,但是我的内容是可以沉到导航栏最底部的啊,这样就判断不了了。最后自己从DecorView源码中找到了解:
    /**
     * 不用内容高度和屏幕真实高度作对比来判断。
     * 这里只适用于21以后的版本,方法是从DecorView源码中来的,
     * 测试了模拟器21版本,和我自己手机Android 8.1.0都是有效的
     * api min is 21 version
     * 0:statusbar is visible
     * 1:navigation is visible
     *
     * @return statusbar, navigation是否可见
     */
    public static boolean[] isSystemUiVisible(Window window) {
        boolean[] result = new boolean[]{false, false};
        if (window == null) {
            return result;
        }
        WindowManager.LayoutParams attributes = window.getAttributes();
        if (attributes != null) {
            result[0] = (attributes.flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) != WindowManager.LayoutParams.FLAG_FULLSCREEN;
            //
            ViewGroup decorView = (ViewGroup) window.getDecorView();
            result[1] = (((attributes.systemUiVisibility | decorView.getWindowSystemUiVisibility()) &
                    View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0) && (attributes.flags & WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
        }
        //
        Object decorViewObj = window.getDecorView();
        Class clazz = decorViewObj.getClass();
        int mLastBottomInset = 0, mLastRightInset = 0, mLastLeftInset = 0;
        try {
            Field mLastBottomInsetField = clazz.getDeclaredField("mLastBottomInset");
            mLastBottomInsetField.setAccessible(true);
            mLastBottomInset = mLastBottomInsetField.getInt(decorViewObj);
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            Field mLastRightInsetField = clazz.getDeclaredField("mLastRightInset");
            mLastRightInsetField.setAccessible(true);
            mLastRightInset = mLastRightInsetField.getInt(decorViewObj);
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            Field mLastLeftInsetField = clazz.getDeclaredField("mLastLeftInset");
            mLastLeftInsetField.setAccessible(true);
            mLastLeftInset = mLastLeftInsetField.getInt(decorViewObj);
        } catch (Exception e) {
            e.printStackTrace();
        }
        boolean isNavBarToRightEdge = mLastBottomInset == 0 && mLastRightInset > 0;
        int size = isNavBarToRightEdge ? mLastRightInset : (mLastBottomInset == 0 && mLastLeftInset > 0 ? mLastLeftInset : mLastBottomInset);
        result[1] = result[1] && size > 0;
        return result;
    }

# 测试

测试了5.0 和 8.1.0 都是有效的,中间的版本没测,至于5.0之前的版本,正在找方法中。
有什么问题请联系我 [ 笑脸 ]

你可能感兴趣的:(android 判断虚拟导航栏是否在屏幕上显示,适用于Lollipop 5.0 ~ Oreo 8.1.0)