美文网首页
手机屏幕适配

手机屏幕适配

作者: crossroads | 来源:发表于2021-03-15 15:21 被阅读0次

    前言

    公司有很多要根据样式自动改变位置的需求,安卓机型各种各样,适配起来就是一个坑啊,今天把大致的坑填一下,供大家参考。

    一坑:底部导航栏

    一般手机我们会用这样的方法来判断有无导航栏

    /**
         * @return 是否存在虚拟按键栏
         */
        @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
        public static boolean hasNavBar(Context context) {
            Resources res = context.getResources();
            int resourceId = res.getIdentifier("config_showNavigationBar", "bool", "android");
            if (resourceId != 0) {
                boolean hasNav = res.getBoolean(resourceId);
                String sNavBarOverride = getNavBarOverride();
                if ("1".equals(sNavBarOverride)) {
                    hasNav = false;
                } else if ("0".equals(sNavBarOverride)) {
                    hasNav = true;
                }
                return hasNav;
            } else {
                return !ViewConfiguration.get(context).hasPermanentMenuKey();
            }
        }
    
    
        /**
         * 判断虚拟按键栏是否重写
         */
        private static String getNavBarOverride() {
            String sNavBarOverride = null;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                try {
                    Class c = Class.forName("android.os.SystemProperties");
                    Method m = c.getDeclaredMethod("get", String.class);
                    m.setAccessible(true);
                    sNavBarOverride = (String) m.invoke(null, "qemu.hw.mainkeys");
                } catch (Exception e) {
                    TRTCLogTools.e(TAG, e.toString());
                }
            }
            return sNavBarOverride;
        }
    
    

    然而,会发现华为、小米、vivo不管有没有隐藏底部导航栏,它都返回true!所以只能针对这几个机型进行机型适配了。

    1. 首先判断手机机型
        /**
         * 获取手机品牌
         */
        public static String getDeviceManufacturer() {
            return android.os.Build.MANUFACTURER;
        }
        public static boolean isHuawei() {
            if ("HUAWEI".equalsIgnoreCase(getDeviceManufacturer())) {
                return true;
            }
            return false;
        }
    
    1. 根据不同手机判断有无底部导航栏
    
        public static boolean isXiaoMiNavigationBarShow(Context context) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
                if (Settings.Global.getInt(context.getContentResolver(), "force_fsg_nav_bar", 0) != 0) {
                    //开启手势,不显示虚拟键
                    return false;
                }
            }
            return true;
        }
    
        public static boolean isHuaWeiNavigationBarShow(Context context) {
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
                return Settings.System.getInt(context.getContentResolver(), "navigationbar_is_min", 0) == 0;
            } else {
                return Settings.Global.getInt(context.getContentResolver(), "navigationbar_is_min", 0) == 0;
            }
        }
    
        public static boolean isVivoNavigationBarShow(Context context) {
            return Settings.Secure.getInt(context.getContentResolver(), "navigation_gesture_on", 0) == 0;
        }
    

    至此就可以判断是否有导航栏了。接下来,就可以获取导航栏高度了

    
        /**
         * 获取虚拟按键的高度
         */
        public static int getNavigationBarHeight(Context context) {
            int result = 0;
            if (hasNavBar(context)
                    && (!isMIUI() || isXiaoMiNavigationBarShow(context))
                    && (!isVivo() || isVivoNavigationBarShow(context))
                    && (!isHuawei() || isHuaWeiNavigationBarShow(context))) {
                Resources res = context.getResources();
                int resourceId = res.getIdentifier("navigation_bar_height", "dimen", "android");
                if (resourceId > 0) {
                    result = res.getDimensionPixelSize(resourceId);
                }
            }
            return result;
        }
    

    二坑:弹窗
    场景:当做直播的时候,通常需要直播页面充满全屏,也就是要做沉浸式。这时,我们要设置页面全屏,使用android:windowTranslucentNavigation设置透明导航栏,然后发现有些手机show底部弹窗dialog底部永远在导航栏上方,而我们的activity的布局底部是在导航栏下方


    灰色是activity底部,红色是弹窗底部

    为了统一在导航栏上方,这时候就需要将activity的我们需要在虚拟导航栏之上的根布局使用

            android:fitsSystemWindows="true"
    

    将布局底部也变为导航栏的上方,其实是设置了android:fitsSystemWindows="true"属性的view会自动添加一个值等于导航栏高度的paddingBottom。这样view的底部也就和dialog的底部保持一致啦。记住:不要在activity的根布局设置,因为如果你设置的话,它的顶部也不能到最上面啦。所以只要针对你想要至于导航栏之上的view的根布局就好。
    三坑、手机屏幕高度
    要做沉浸式,需要获取手机屏幕的真实高度,即包含导航栏这些的真正高度,要这样获取

        public static int getScreenRealHeight(Context context) {
            WindowManager windowManager =
                    (WindowManager) context.getSystemService(Context.
                            WINDOW_SERVICE);
            final Display display = windowManager.getDefaultDisplay();
            Point outPoint = new Point();
            if (Build.VERSION.SDK_INT >= 19) {
                // 可能有虚拟按键的情况
                display.getRealSize(outPoint);
            } else {
                // 不可能有虚拟按键
                display.getSize(outPoint);
            }
            return outPoint.y;
        }
    
    

    参考网址

    底部导航栏适配
    fitsystemwindow的分析

    相关文章

      网友评论

          本文标题:手机屏幕适配

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