检查导航栏

我试图检查是否在Android导航栏是否存在加载,以便我可以相应地调整布局,有没有人有任何build议?

这是我想要检测的导航栏: 在这里输入图像描述

PS到目前为止,我发现的所有方法都是“坏”的方法来尝试删除酒吧,我不想这样做。

花了我一些时间,但我发现比依靠hasPermanentMenuKey()这样的更可靠的方法不适用于像HTC One这样的新手机,它没有菜单键,但有主键和后键,所以不需要(或显示)软导航栏。 为了解决这个问题,请尝试下面的代码来检查后退button:

boolean hasMenuKey = ViewConfiguration.get(context).hasPermanentMenuKey(); boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK); if(!hasMenuKey && !hasBackKey) { // Do whatever you need to do, this device has a navigation bar } 

没有可靠的方法来检查导航栏。 通过使用KeyCharacterMap.deviceHasKey您可以检查设备上是否存在某些物理密钥,但是由于具有物理密钥的设备仍然可以具有导航栏,因此该信息并不十分有用。 像OnePlus One这样的设备,或者运行自定义ROM的设备,都可以在禁用物理按键的设置中添加一个选项,并添加一个导航栏。 没有办法检查是否启用此选项,并且deviceHasKey对于由此选项禁用的密钥仍然返回true。

这是最接近你可以得到:

 boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK); boolean hasHomeKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_HOME); if (hasBackKey && hasHomeKey) { // no navigation bar, unless it is enabled in the settings } else { // 99% sure there's a navigation bar } 

如果后退和主页button在设备上不存在,则必须具有导航栏,否则用户根本无法导航。 然而,你永远不能100%确定这一点,因为制造商可以实现deviceHasKey错误。

这是一个快速的答案,结合了Pauland和Philask的解决scheme。 但是,恐怕我没有足够的设备来testing它是否可以在任何地方使用。 我有兴趣听到别人的结果。

 boolean hasNavBar(Context context) { Resources resources = context.getResources(); int id = resources.getIdentifier("config_showNavigationBar", "bool", "android"); if (id > 0) { return resources.getBoolean(id); } else { // Check for keys boolean hasMenuKey = ViewConfiguration.get(context).hasPermanentMenuKey(); boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK); return !hasMenuKey && !hasBackKey; } } 

另一个解决scheme(我的类UtilsUISystem的一部分)

  public static boolean hasNavBar (Resources resources) { //Emulator if (Build.FINGERPRINT.startsWith("generic")) return true; int id = resources.getIdentifier("config_showNavigationBar", "bool", "android"); return id > 0 && resources.getBoolean(id); } 

你可以将这段代码添加到你的activity的onCreate()方法中:

  View decorView = getWindow().getDecorView(); decorView.setOnSystemUiVisibilityChangeListener (new View.OnSystemUiVisibilityChangeListener() { @Override public void onSystemUiVisibilityChange(int visibility) { if ((visibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0) { // TODO: The navigation bar is visible. Make any desired // adjustments to your UI, such as showing the action bar or // other navigational controls. } else { // TODO: The navigation bar is NOT visible. Make any desired // adjustments to your UI, such as hiding the action bar or // other navigational controls. } } }); 

这种方法为我工作

  int id = getResources().getIdentifier("config_showNavigationBar","bool","android"); boolean result = id > 0 && getResources().getBoolean(id); // if(result) { // Do whatever you need to do, this device has a soft Navigation Bar } 

它为我工作,并在许多设备进行testing。

一些可能更好的工作是测量屏幕。

从API 17开始,有getWindowManager().getDefaultDisplay().getRealSize() ,它可以与getWindowManager().getDefaultDisplay().getSize()返回的大小进行比较。

如果你得到不同的结果,我认为可以肯定地说,有一个导航栏,如果你得到相同的结果没有一个。 需要注意的一件事是您的目标SDK和支持的屏幕,如果Android认为您的应用在当前设备上无法正常工作,可能会导致getSize()的结果缩放。

在API 17以下,您可以通过getWindowManager().getDefaultDisplay().getMetrics()在横向和纵向模式下测量屏幕,不同的结果可能意味着有一个导航栏。

但是,如果获得相同的结果,则实际上并不知道,因为即使在横向模式下,手机也可以将导航栏保持在较短的边缘。 一个有教养的猜测是,如果宽度或高度比1280x800等标准尺寸小4%到8%,而另一个尺寸是相等的,那么可能还有一个导航栏。 不过,不要下注。 有太多的解决scheme,彼此之间差距太小,为此运作良好。

 boolean hasNavBar(Context context) { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) { // navigation bar was introduced in Android 4.0 (API level 14) Resources resources = context.getResources(); int id = resources.getIdentifier("config_showNavigationBar", "bool", "android"); if (id > 0) { return resources.getBoolean(id); } else { // Check for keys boolean hasMenuKey = ViewConfiguration.get(context).hasPermanentMenuKey(); boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK); return !hasMenuKey && !hasBackKey; } } else { return false; } } 

我看到上面的答案,我想说明“不存在”可以看作是0的高度; 所以它可以是这样的:

 public static int getScreenH(Context context) { DisplayMetrics dm = new DisplayMetrics(); dm = context.getResources().getDisplayMetrics(); int h = dm.heightPixels; return h; } public static int getDpi(Context context) { DisplayMetrics displayMetrics1 = context.getResources().getDisplayMetrics(); int height1 = displayMetrics1.heightPixels; int dpi = 0; WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); Display display = windowManager.getDefaultDisplay(); DisplayMetrics displayMetrics = new DisplayMetrics(); @SuppressWarnings("rawtypes") Class c; try { c = Class.forName("android.view.Display"); @SuppressWarnings("unchecked") Method method = c.getMethod("getRealMetrics", DisplayMetrics.class); method.invoke(display, displayMetrics); dpi = displayMetrics.heightPixels; } catch (Exception e) { e.printStackTrace(); } return dpi; } public static int getBottomStatusHeight(Context context) { int totalHeight = getDpi(context); int contentHeight = getScreenH(context); return totalHeight - contentHeight; } 

“`

解决scheme:只有没有永久硬件密钥的设备才有导航栏,因此您可以检查API版本并使用hasPermanentMenuKey()来查找硬件密钥

  boolean hasMenuKey = ViewConfiguration.get(context).hasPermanentMenuKey();