美文网首页
Android适配-Android全面屏适配问题

Android适配-Android全面屏适配问题

作者: 289346a467da | 来源:发表于2018-05-11 14:28 被阅读2375次

1全面屏dialog 弹窗问题

注意dialog布局不要设置 背景颜色

<item name="android:windowFrame">@null</item>
<item name="android:windowNoTitle">true</item>

<item name="android:windowBackground">@color/transparent</item>

<item name="android:windowIsFloating">true</item>

<item name="android:windowIsTranslucent">true</item>

<item name="android:windowContentOverlay">@null</item>

2 底部虚拟按键问题

自全面屏出来以后判断虚拟按键是否隐藏的常用方法不管用了,无论是否隐藏都会返回true,比如以下常用的两种检查虚拟按键是否存在的方法:

 public static boolean checkDeviceHasNavigationBar() {
        boolean hasNav = false;
        // 通过WindowManagerGlobal 获取WindowManagerService 反射WindowManagerGlobal.getWindowManagerService();
        try {
            Class<?> windowManagerGlobalClass = Class.forName("android.view.WindowManagerGlobal");
            // 获取WindowManagerGlobal 中的私有方法
            Method getWindowManagerService = windowManagerGlobalClass.getDeclaredMethod("getWindowManagerService");
            getWindowManagerService.setAccessible(true);
            //getWindowManagerService 是静态方法
            Object iwindowManager = getWindowManagerService.invoke(null);

            // 获取windowManagerService 的hasNavigationBar 方法的返回值
            Class<?> aClass = iwindowManager.getClass();
            Method hasNavigationBar = aClass.getDeclaredMethod("hasNavigationBar");
            hasNavigationBar.setAccessible(true);
            hasNav = (boolean) hasNavigationBar.invoke(iwindowManager);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return hasNav;
    }
    
    //判断是否存在NavigationBar
    public static boolean hasNavigationBar(Context context) {
        boolean hasNavigationBar = false;
        Resources rs = context.getResources();
        int id = rs.getIdentifier("config_showNavigationBar", "bool", "android");
        if (id > 0) {
            hasNavigationBar = rs.getBoolean(id);
        }
        try {
            //反射获取SystemProperties类,并调用它的get方法
            Class systemPropertiesClass = Class.forName("android.os.SystemProperties");
            Method m = systemPropertiesClass.getMethod("get", String.class);
            String navBarOverride = (String) m.invoke(systemPropertiesClass, "qemu.hw.mainkeys");
            if ("1".equals(navBarOverride)) {
                hasNavigationBar = false;
            } else if ("0".equals(navBarOverride)) {
                hasNavigationBar = true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return hasNavigationBar;
    }

在华为、小米等全面屏手机上,当虚拟按键隐藏时获取的,调用以上两种方法返回的都是true ,也就是说虚拟按键并没有被真正的隐藏。

解决方案

参考资料

Google

关于全面屏手机虚拟导航键的开关

由于全面屏手机都没有底部的Home,Back等实体按键,因此,大多数全面屏手机都是支持虚拟导航键,即通过上面的方法hasNavigationBar获取的返回值都是true。
当隐藏虚拟导航键时,用户可以通过底部上滑的手势实现导航键同样的功能,非常便利。
但对我们开发者来说这是很蛋疼的问题。在一些全面屏手机上,仅仅通过上面给出的hasNavigationBar是无法准确判断NavigationBar存在与否的,hasNavigationBar这个方法一直都是返回true。并且获取到的虚拟按键的高度一直是130.

解决办法必须得有,那就是获取==setting==中收拾开关的值。代码如下:

public static boolean navigationGestureEnabled(Context context) {
    int val = Settings.Secure.getInt(context.getContentResolver(), NAVIGATION_GESTURE, NAVIGATION_GESTURE_OFF);
    return val != NAVIGATION_GESTURE_OFF;
}

最后,判断当前系统是否存在并开启了NavigationBar,就要结合上面给出的两个方法一起判断才准确:

//navigationGestureEnabled()从设置中取不到值的话,返回false,因此也不会影响在其他手机上的判断
    public static boolean realHasNavigationBar(Context context) {
        return hasNavigationBar(context) && !navigationGestureEnabled(context);
    }
但是在小米和华为的全面屏手机虚拟按键一直存在,找不到获取全面屏的开关 查了半天资料无解。。。。

获取虚拟按键的高度

    /**
     * 获取虚拟功能键高度
     *
     * @param context
     *
     * @return
     */
    public static int getNavigationBarHeight(Activity activity) {
        if (!isNavigationBarShow(activity)) {
            return 0;
        }
        Resources resources = activity.getResources();
        int resourceId = resources.getIdentifier("navigation_bar_height",
                "dimen", "android");
        //获取NavigationBar的高度
        int height = resources.getDimensionPixelSize(resourceId);
        return height;
    }

显示隐藏虚拟按键

1、只使用SYSTEM_UI_FLAG_HIDE_NAVIGATION和SYSTEM_UI_FLAG_FULLSCREEN
这种情况下,在进入全屏模式后,用户有任何操作,SYSTEM_UI_FLAG_HIDE_NAVIGATION和SYSTEM_UI_FLAG_FULLSCREEN就会被清除。状态栏和虚拟按键会一直可见。除非再次设置SYSTEM_UI_FLAG_HIDE_NAVIGATION和SYSTEM_UI_FLAG_FULLSCREEN。在状态栏和虚拟按键显示变化时会调用View.OnSystemUiVisibilityChangeListener。

2、SYSTEM_UI_FLAG_IMMERSIVE配合SYSTEM_UI_FLAG_HIDE_NAVIGATION和SYSTEM_UI_FLAG_FULLSCREEN使用
用户操作不会清除SYSTEM_UI_FLAG_HIDE_NAVIGATION和SYSTEM_UI_FLAG_FULLSCREEN,会一直保持全屏模式。显示切换时也会触发View.OnSystemUiVisibilityChangeListener。还有一个区别就是,全屏模式时,从原本状态栏或者虚拟按键的位置响屏幕内部滑动,会清除SYSTEM_UI_FLAG_HIDE_NAVIGATION和SYSTEM_UI_FLAG_FULLSCREEN,保持可见状态,并且也会触发OnSystemUiVisibilityChangeListener监听。

3、SYSTEM_UI_FLAG_IMMERSIVE_STICKY配合SYSTEM_UI_FLAG_HIDE_NAVIGATION和SYSTEM_UI_FLAG_FULLSCREEN使用
用户操作不会清除SYSTEM_UI_FLAG_HIDE_NAVIGATION和SYSTEM_UI_FLAG_FULLSCREEN。会一直保持全屏模式。显示切换时也会触发View.OnSystemUiVisibilityChangeListener,全屏模式时,从原本状态栏或者虚拟按键的位置 响屏幕内部滑动,状态栏和虚拟按键栏会暂时可见,一段时间后自动隐藏。与SYSTEM_UI_FLAG_IMMERSIVE不同的是,因为是临时的显示,所以不会触发OnSystemUiVisibilityChangeListener。

参考资料

 public void hideNavigationBar(Activity activity) {
        int uiOptions = activity.getWindow().getDecorView().getSystemUiVisibility();
        int newUiOptions = uiOptions;
        boolean isImmersiveModeEnabled =
                ((uiOptions | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) == uiOptions);
        if (!isImmersiveModeEnabled) {
            if (Build.VERSION.SDK_INT >= 14) {
                newUiOptions |= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
            }
            if (Build.VERSION.SDK_INT >= 16) {
                newUiOptions |= View.SYSTEM_UI_FLAG_FULLSCREEN;
            }
            if (Build.VERSION.SDK_INT >= 18) {
                newUiOptions |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
            }
            activity.getWindow().getDecorView().setSystemUiVisibility(newUiOptions);
        }
    }

显示虚拟按键

  public void showNavigationBar(Activity context) {
        int uiOptions = context.getWindow().getDecorView().getSystemUiVisibility();
        int newUiOptions = uiOptions;
        boolean isImmersiveModeEnabled =
                ((uiOptions | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) == uiOptions);
        if (isImmersiveModeEnabled) {
            //先取 非 后再 与, 把对应位置的1 置成0,原本为0的还是0
            if (Build.VERSION.SDK_INT >= 14) {
                newUiOptions &= ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
            }
            if (Build.VERSION.SDK_INT >= 16) {
                newUiOptions &= ~View.SYSTEM_UI_FLAG_FULLSCREEN;
            }
            if (Build.VERSION.SDK_INT >= 18) {
                newUiOptions &= ~View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
            }
            context.getWindow().getDecorView().setSystemUiVisibility(newUiOptions);
        }
    }

监听虚拟按键的显示和隐藏

final View content = getActivity().getWindow().getDecorView().findViewById(android.R.id.content);
            content.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout() {
                //屏幕发生改变
                    int height = content.getHeight();
                    params.height = (height - (ViewMeasureUtils.getHeight(itemView)));//获取DecorView content的高度减去视频的高度,这样可以适配全面屏
                }
            });

参考

相关文章

  • Android适配之版本适配

    这篇文章用来记录学习和开发时遇到的版本适配问题,持续更新 全面屏、刘海屏的适配:Android 9 支持最新的全面...

  • 安卓适配

    ------刘海屏------屏幕适配 | Android 刘海屏适配总结Android刘海屏适配方案Androi...

  • Android适配-Android全面屏适配问题

    1全面屏dialog 弹窗问题 注意dialog布局不要设置 背景颜色 @null true @color/t...

  • 安卓小米全面屏适配问题

    安卓小米全面屏适配问题,在清单文件application下加上 android:resizeableActivit...

  • Android全面屏适配

    Android全面屏适配 方案1: AndroidManifest.xml 文件添加属性: 应用适配建议采用me...

  • Android Studio 图片适配/使用之SVG

    前言 适配可以说是Android的老大难问题了,Android厂商众多,设备碎片化严重.大屏小屏,全面屏,异形屏数...

  • Flutter 全面屏适配Android 和IOS

    概要: 1.全屏幕特色,及存在的问题; 2.适配IOS全屏iPhone X; 3.适配Android 全面屏 总结...

  • Android 全面屏适配

    全面屏 小米mix(18:9屏幕)的出现标志的Android手机进入全面屏时代,这个非主流的尺寸确实带来了更多的观...

  • android全面屏适配

    在迎来全面屏时代之前 屏幕比例基本上都是16:9,所以比较好适配但是现在越来越多的屏幕占比都是为18:9,或者18...

  • Android全面屏适配

    什么是全面屏? 概念 很多人可能把全面屏跟曲面屏混淆,其实这是两个不同的概念。 一般手机的屏幕纵横比为16:9,如...

网友评论

      本文标题:Android适配-Android全面屏适配问题

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