¿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:
- Diálogo de ocultar de Android después de tiempo establecido, como un tostado personalizado de intervalo de tiempo
- ¿Cómo puedo hacer un diamante ShapeDrawable?
- Establecer atributos (margen, gravedad, etc ...) en una vista de Android mediante programación (sin XML)
- Animación de botón de acción flotante de Android
- Cómo eliminar drawableleft
¿Cómo puedo obtener el tamaño del ancho y la altura de este elemento de interfaz de usuario en píxeles?
- Android: técnica para atenuar un campo de edición de texto
- Libgdx Scene2d - Set actor (TextField) de relleno?
- Android: ¿Ajusta la pantalla cuando aparece el teclado?
- ¿Cuál es el propósito de requestWindowFeature ()?
- Aplicación de la plantilla de PSD de Photoshop para Android
- Cómo configurar el encabezado y el pie de página en android?
- Actualización de GUI: Runnables vs Messages
- ¿La mejor manera de crear Barra de progreso segmentada?
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; }
- Diseño de vista previa con la etiqueta de raíz de mezcla en Intellij IDEA / Android Studio
- ¿Mueve los diseños cuando se muestra el teclado suave?