¿Cómo puedo obtener la altura y el ancho de la barra de navegación de Android mediante programación?

La barra de navegación negra en la parte inferior de la pantalla no es fácilmente extraíble en Android. Ha sido parte de Android desde la versión 3.0 como un reemplazo de los botones de hardware. Aquí está una imagen:

Barra del sistema

¿Cómo puedo obtener el tamaño del ancho y la altura de este elemento de interfaz de usuario en píxeles?

Intente abajo el código:

Resources resources = context.getResources(); int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android"); if (resourceId > 0) { return resources.getDimensionPixelSize(resourceId); } return 0; 

Consigo el tamaño de la barra de navegación comparando el tamaño de pantalla utilizable en la aplicación con el tamaño real de la pantalla. Supongo que la barra de navegación está presente cuando el tamaño de la pantalla de aplicación es más pequeño que el tamaño real de la pantalla. Luego calculo el tamaño de la barra de navegación. Este método funciona con API 14 y superior.

 public static Point getNavigationBarSize(Context context) { Point appUsableSize = getAppUsableScreenSize(context); Point realScreenSize = getRealScreenSize(context); // navigation bar on the right if (appUsableSize.x < realScreenSize.x) { return new Point(realScreenSize.x - appUsableSize.x, appUsableSize.y); } // navigation bar at the bottom if (appUsableSize.y < realScreenSize.y) { return new Point(appUsableSize.x, realScreenSize.y - appUsableSize.y); } // navigation bar is not present return new Point(); } public static Point getAppUsableScreenSize(Context context) { WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); Display display = windowManager.getDefaultDisplay(); Point size = new Point(); display.getSize(size); return size; } public static Point getRealScreenSize(Context context) { WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); Display display = windowManager.getDefaultDisplay(); Point size = new Point(); if (Build.VERSION.SDK_INT >= 17) { display.getRealSize(size); } else if (Build.VERSION.SDK_INT >= 14) { try { size.x = (Integer) Display.class.getMethod("getRawWidth").invoke(display); size.y = (Integer) Display.class.getMethod("getRawHeight").invoke(display); } catch (IllegalAccessException e) {} catch (InvocationTargetException e) {} catch (NoSuchMethodException e) {} } return size; } 

En realidad, la barra de navegación en las tabletas (al menos Nexus 7) tiene diferentes tamaños en el retrato y el paisaje, por lo que esta función debe tener este aspecto:

 private int getNavigationBarHeight(Context context, int orientation) { Resources resources = context.getResources(); int id = resources.getIdentifier( orientation == Configuration.ORIENTATION_PORTRAIT ? "navigation_bar_height" : "navigation_bar_height_landscape", "dimen", "android"); if (id > 0) { return resources.getDimensionPixelSize(id); } return 0; } 

La altura de NavigationBar varía para algunos dispositivos, pero también para algunas orientaciones. Primero tienes que comprobar si el dispositivo tiene una barra de navegación, entonces si el dispositivo es una tableta o un no-tablet (teléfono) y finalmente tienes que mirar la orientación del dispositivo para obtener la altura correcta.

 public int getNavBarHeight(Context c) { int result = 0; boolean hasMenuKey = ViewConfiguration.get(c).hasPermanentMenuKey(); boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK); if(!hasMenuKey && !hasBackKey) { //The device has a navigation bar Resources resources = getContext().getResources(); int orientation = getResources().getConfiguration().orientation; int resourceId; if (isTablet(c)){ resourceId = resources.getIdentifier(orientation == Configuration.ORIENTATION_PORTRAIT ? "navigation_bar_height" : "navigation_bar_height_landscape", "dimen", "android"); } else { resourceId = resources.getIdentifier(orientation == Configuration.ORIENTATION_PORTRAIT ? "navigation_bar_height" : "navigation_bar_width", "dimen", "android"); } if (resourceId > 0) { return getResources().getDimensionPixelSize(resourceId); } } return result; } private boolean isTablet(Context c) { return (c.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE; } 

Espero que esto te ayude

 public int getStatusBarHeight() { int result = 0; int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android"); if (resourceId > 0) { result = getResources().getDimensionPixelSize(resourceId); } return result; } public int getNavigationBarHeight() { boolean hasMenuKey = ViewConfiguration.get(context).hasPermanentMenuKey(); int resourceId = getResources().getIdentifier("navigation_bar_height", "dimen", "android"); if (resourceId > 0 && !hasMenuKey) { return getResources().getDimensionPixelSize(resourceId); } return 0; } 

Este es mi código para agregar paddingRight y paddingBottom a una vista para esquivar la barra de navegación. He combinado algunas de las respuestas aquí y he hecho una cláusula especial para la orientación horizontal junto con isInMultiWindowMode. La clave es leer navigation_bar_height , pero también comprobar config_showNavigationBar para asegurarnos de que deberíamos usar la altura.

Ninguna de las soluciones anteriores funcionó para mí. A partir de Android 7.0 tienes que tener en cuenta el modo de ventanas múltiples. Esto rompe las implementaciones comparando display.realSize con display.size ya que realSize le da las dimensiones de toda la pantalla (ambas ventanas divididas) y el tamaño sólo le da las dimensiones de su ventana de aplicación. Ajustar el relleno a esta diferencia dejará toda su vista siendo relleno.

 /** Adds padding to a view to dodge the navigation bar. Unfortunately something like this needs to be done since there are no attr or dimens value available to get the navigation bar height (as of December 2016). */ public static void addNavigationBarPadding(Activity context, View v) { Resources resources = context.getResources(); if (hasNavigationBar(resources)) { int orientation = resources.getConfiguration().orientation; int size = getNavigationBarSize(resources); switch (orientation) { case Configuration.ORIENTATION_LANDSCAPE: if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && context.isInMultiWindowMode()) { break; } v.setPadding(v.getPaddingLeft(), v.getPaddingTop(), v.getPaddingRight() + size, v.getPaddingBottom()); break; case Configuration.ORIENTATION_PORTRAIT: v.setPadding(v.getPaddingLeft(), v.getPaddingTop(), v.getPaddingRight(), v.getPaddingBottom() + size); break; } } } private static int getNavigationBarSize(Resources resources) { int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android"); return resourceId > 0 ? resources.getDimensionPixelSize(resourceId) : 0; } private static boolean hasNavigationBar(Resources resources) { int hasNavBarId = resources.getIdentifier("config_showNavigationBar", "bool", "android"); return hasNavBarId > 0 && resources.getBoolean(hasNavBarId); } 

La altura de la barra de navegación inferior es 48dp (en modo vertical y horizontal) y es de 42dp cuando la barra se coloca verticalmente.

La solución propuesta por Egidijus y funciona perfectamente para Build.VERSION.SDK_INT> = 17

Pero tengo "NoSuchMethodException" durante la ejecución de la siguiente instrucción con Build.VERSION.SDK_INT <17 en mi dispositivo:

 Display.class.getMethod("getRawHeight").invoke(display); 

He modificado el método getRealScreenSize () para estos casos:

 else if(Build.VERSION.SDK_INT >= 14) { View decorView = getActivity().getWindow().getDecorView(); size.x = decorView.getWidth(); size.y = decorView.getHeight(); } 

Resolví este problema para todos los dispositivos (incluyendo Nexus 5, Samsung Galaxy Nexus 6 edge +, Samsung S10, Samsung Nota II, etc.). Creo que esto le ayudará a manejar los problemas dependientes del dispositivo.

Aquí estoy agregando dos tipos de códigos,

Código Java (para Native Android):

 import android.content.Context; import android.content.res.Resources; import android.os.Build; import android.util.DisplayMetrics; import android.view.Display; import android.view.ViewConfiguration; import android.view.WindowManager; public class DeviceSpec { private int resourceID = -1; private Display display = null; private DisplayMetrics displayMetrics = null; private DisplayMetrics realDisplayMetrics = null; private Resources resources = null; private WindowManager windowManager = null; public double GetNavigationBarHeight(Context context) { try { windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); display = windowManager.getDefaultDisplay(); displayMetrics = new DisplayMetrics(); if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) { realDisplayMetrics = new DisplayMetrics(); display.getMetrics(displayMetrics); display.getRealMetrics(realDisplayMetrics); if(displayMetrics.heightPixels != realDisplayMetrics.heightPixels) { resources = context.getResources(); return GetNavigationBarSize(context); } } else { resources = context.getResources(); resourceID = resources.getIdentifier("config_showNavigationBar", "bool", "android"); if (resourceID > 0 && resources.getBoolean(resourceID)) return GetNavigationBarSize(context); } } catch (Exception e){ e.printStackTrace(); } return 0; } private double GetNavigationBarSize(Context context) { resourceID = resources.getIdentifier("navigation_bar_height", "dimen", "android"); if (resourceID > 0 && ViewConfiguration.get(context).hasPermanentMenuKey()) return (resources.getDimensionPixelSize(resourceID) / displayMetrics.density); return 0; } } 

Y código C # (para Xamarin Forms / Android)

 int resourceId = -1; IWindowManager windowManager = null; Display defaultDisplay = null; DisplayMetrics displayMatrics = null; DisplayMetrics realMatrics = null; Resources resources = null; public double NavigationBarHeight { get { try { windowManager = Forms.Context.GetSystemService(Context.WindowService).JavaCast<IWindowManager>(); defaultDisplay = windowManager.DefaultDisplay; displayMatrics = new DisplayMetrics(); if (Build.VERSION.SdkInt >= BuildVersionCodes.JellyBeanMr2) { realMatrics = new DisplayMetrics(); defaultDisplay.GetMetrics(displayMatrics); defaultDisplay.GetRealMetrics(realMatrics); if (displayMatrics.HeightPixels != realMatrics.HeightPixels) { resources = Forms.Context.Resources; return GetHeightOfNivigationBar(); } } else { resources = Forms.Context.Resources; resourceId = resources.GetIdentifier("config_showNavigationBar", "bool", "android"); if (resourceId > 0 && resources.GetBoolean(resourceId)) return GetHeightOfNivigationBar(); } } catch (Exception e) { } return 0; } } private double GetHeightOfNivigationBar() { resourceId = resources.GetIdentifier("navigation_bar_height", "dimen", "android"); if (!ViewConfiguration.Get(Forms.Context).HasPermanentMenuKey && resourceId > 0) { return resources.GetDimensionPixelSize(resourceId) / displayMatrics.Density; } return 0; } 

He aquí cómo he resuelto esto. Hice una barra inferior escondible que necesitaba relleno dependiendo de si había una barra de navegación o no (capacitiva, en pantalla o simplemente pre lollipop).


Ver

 setPadding(0, 0, 0, Utils.hasNavBar(getContext()) ? 30 : 0); 

Utils.java

 public static boolean hasNavBar(Context context) { // Kitkat and less shows container above nav bar if (android.os.Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) { return false; } // Emulator if (Build.FINGERPRINT.startsWith("generic")) { return true; } boolean hasMenuKey = ViewConfiguration.get(context).hasPermanentMenuKey(); boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK); boolean hasNoCapacitiveKeys = !hasMenuKey && !hasBackKey; Resources resources = context.getResources(); int id = resources.getIdentifier("config_showNavigationBar", "bool", "android"); boolean hasOnScreenNavBar = id > 0 && resources.getBoolean(id); return hasOnScreenNavBar || hasNoCapacitiveKeys || getNavigationBarHeight(context, true) > 0; } public static int getNavigationBarHeight(Context context, boolean skipRequirement) { int resourceId = context.getResources().getIdentifier("navigation_bar_height", "dimen", "android"); if (resourceId > 0 && (skipRequirement || hasNavBar(context))) { return context.getResources().getDimensionPixelSize(resourceId); } return 0; } 
  • Implementación de la navegación "Exploración avanzada" en la interfaz de usuario de la aplicación de Android
  • Android drawBitmap (...) el método es lento?
  • ¿Hay una descripción gráfica de todo el elemento GUI de Android?
  • ¿Cuál es la relación entre píxeles y píxeles escalados
  • ¿Cómo puedo obtener una función de paginación en vista de desplazamiento horizontal sin ViewPager?
  • Android cómo hacer que resalte la vista cuando se hace clic?
  • Declaración de un elemento personalizado de la interfaz de usuario de Android con XML
  • Cómo crear la interfaz de usuario como la foto adjunta
  • Android Phone Call UI - Cambiar
  • TextView como una barra de progresión con minipulación textcolor?
  • Fuente personalizada en Android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.