获取半透明 Android 导航栏的位置和可见性

Get position and visibility of translucent Android navigation bar

我正在开发一款已移植到 Android 的跨平台应用程序。由于其非 Android 传统,它没有广泛使用 Android UI 元素 – 主应用程序 window 是一个单一的 View.

我想实现从 KitKat 开始支持的半透明系统(状态和导航)栏,同时确保主要 View 内的 UI 元素不会被它们阻挡。

This answer 展示了如何获取这些栏的默认高度(还有 navigation_bar_height_landscape 用于横向模式下的导航栏高度,以及 navigation_bar_width 用于垂直导航的宽度酒吧)。但这些只是系统的默认尺寸,不包含当前是否显示导航栏的信息,以及它是显示在屏幕的右侧还是底部边缘。

到目前为止我发现的其他答案可能适用于非半透明系统栏:它们只是将总屏幕大小与主应用程序视图的大小进行比较,不同之处在于 space系统吧。但是,对于半透明的系统栏,大小差异为零,这种方法将不起作用。

如何可靠地确定是否显示导航栏,以及显示在哪个位置?

环顾四周,包括 this part 的 AOSP 代码,我得出以下结论:

        // determine if navigation bar is going to be shown
        boolean isNavShowing;
        if (Build.VERSION.SDK_INT >= 13) {
            isNavShowing = ViewConfiguration.get(activity.getApplication()).hasPermanentMenuKey();
        }

        // determine where the navigation bar would be displayed
        boolean isNavAtBottom;
        if (Build.VERSION.SDK_INT >= 13) {
            isNavAtBottom = (activity.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE)
                    || (activity.getResources().getConfiguration().smallestScreenWidthDp >= 600);
        }

然后您可以计算以下插图:

  • 左:0
  • 顶部:status_bar_height
  • 的值
  • 右:如果导航栏不在底部,则为 0,否则 navigation_bar_width
  • 底部:如果导航栏不在底部,则为 0,否则:如果方向为横向(参见上面的代码),navigation_bar_height_landscape;否则 navigation_bar_height.

根据 dimens.xml,默认值是:

  • status_bar_height: 24 dp
  • navigation_bar_height: 48 dp
  • navigation_bar_height_landscape: 48 dp
  • navigation_bar_width: 48 dp

(如果您以某种方式无法获得实际值,您可能想回退到这些。)

isNavShowing 的逻辑是我前一段时间实现的东西的变体。即使在 OnePlusOne 运行 CyanogenMod 上,它也能可靠地检测到物理菜单按钮的存在(用户可以通过设置在导航栏和硬件按钮之间切换)。即使在导航栏上添加了一个软件Menu按钮(貌似是CM加的),导航栏依然检测正确

isNavAtBottom 的逻辑主要取自我上面链接的源文件中的 findNavigationBar() 函数,除非您使用 Android 的高度自定义构建,否则应该可以正常工作。 =24=]