获取半透明 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=]
我正在开发一款已移植到 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 dpnavigation_bar_height
: 48 dpnavigation_bar_height_landscape
: 48 dpnavigation_bar_width
: 48 dp
(如果您以某种方式无法获得实际值,您可能想回退到这些。)
isNavShowing
的逻辑是我前一段时间实现的东西的变体。即使在 OnePlusOne 运行 CyanogenMod 上,它也能可靠地检测到物理菜单按钮的存在(用户可以通过设置在导航栏和硬件按钮之间切换)。即使在导航栏上添加了一个软件Menu按钮(貌似是CM加的),导航栏依然检测正确
isNavAtBottom
的逻辑主要取自我上面链接的源文件中的 findNavigationBar()
函数,除非您使用 Android 的高度自定义构建,否则应该可以正常工作。 =24=]