美文网首页Android 碎片
android 判断虚拟导航栏是否在屏幕上显示,适用于Lolli

android 判断虚拟导航栏是否在屏幕上显示,适用于Lolli

作者: HuZC | 来源:发表于2018-09-30 13:33 被阅读60次

    # 写在前面

    找了两天的判断方法,都是通过屏幕真实高度和内容高度作对比来判断,但是我的内容是可以沉到导航栏最底部的啊,这样就判断不了了。最后自己从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 判断虚拟导航栏是否在屏幕上显示,适用于Lolli

        本文链接:https://www.haomeiwen.com/subject/vdlwoftx.html