transparente oreo ocultar navegacion los como cambiar botones barra android user-interface graphics android-activity

oreo - ocultar barra de navegacion android



¿Cómo obtengo el alto y el ancho de la barra de navegación de Android programáticamente? (15)

Así es como resolví esto. Hice una barra inferior oculta 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; }

La barra de navegación negra en la parte inferior de la pantalla no se puede quitar fácilmente en Android. Ha sido parte de Android desde 3.0 como reemplazo de los botones de hardware. Aquí hay una foto:

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


Código probado para obtener la altura de la barra de navegación (en píxeles):

public static int getNavBarHeight(Context c) { int resourceId = c.getResources() .getIdentifier("navigation_bar_height", "dimen", "android"); if (resourceId > 0) { return c.getResources().getDimensionPixelSize(resourceId); } return 0; }

Código probado para obtener la altura de la barra de estado (en píxeles):

public static int getStatusBarHeight(Context c) { int resourceId = c.getResources() .getIdentifier("status_bar_height", "dimen", "android"); if (resourceId > 0) { return c.getResources().getDimensionPixelSize(resourceId); } return 0; }

Conversión de píxeles a dp:

public static int pxToDp(int px) { return (int) (px / Resources.getSystem().getDisplayMetrics().density); }


Combinando la respuesta de @egis y otros, esto funciona bien en una variedad de dispositivos, probado en Pixel EMU, Samsung S6, Sony Z3, Nexus 4. Este código usa las dimensiones de la pantalla para probar la disponibilidad de la barra de navegación y luego usa la real tamaño de la barra de navegación del sistema, si está presente.

/** * Calculates the system navigation bar size. */ public final class NavigationBarSize { private final int systemNavBarHeight; @NonNull private final Point navBarSize; public NavigationBarSize(@NonNull Context context) { Resources resources = context.getResources(); int displayOrientation = resources.getConfiguration().orientation; final String name; switch (displayOrientation) { case Configuration.ORIENTATION_PORTRAIT: name = "navigation_bar_height"; break; default: name = "navigation_bar_height_landscape"; } int id = resources.getIdentifier(name, "dimen", "android"); systemNavBarHeight = id > 0 ? resources.getDimensionPixelSize(id) : 0; navBarSize = getNavigationBarSize(context); } public void adjustBottomPadding(@NonNull View view, @DimenRes int defaultHeight) { int height = 0; if (navBarSize.y > 0) { // the device has a nav bar, get the correct size from the system height = systemNavBarHeight; } if (height == 0) { // fallback to default height = view.getContext().getResources().getDimensionPixelSize(defaultHeight); } view.setPadding(0, 0, 0, height); } @NonNull private static Point getNavigationBarSize(@NonNull Context context) { Point appUsableSize = new Point(); Point realScreenSize = new Point(); WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); if (windowManager != null) { Display display = windowManager.getDefaultDisplay(); display.getSize(appUsableSize); display.getRealSize(realScreenSize); } return new Point(realScreenSize.x - appUsableSize.x, realScreenSize.y - appUsableSize.y); } }


Creo que hay una respuesta más correcta aquí, porque también te permite tener una altura de corte pareja.

Tome su vista de raíz, anule enApplyWindowInsets, y tome insets.getSystemWindowInsets de él.

En la actividad de mi cámara, agrego relleno igual al systemWindowInsetBottom a mi diseño inferior. Y finalmente, soluciona el problema del recorte.

@TargetApi(Build.VERSION_CODES.KITKAT_WATCH) @Override public WindowInsets onApplyWindowInsets(WindowInsets insets) { WindowInsets windowInsets = super.onApplyWindowInsets(insets); if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { WindowManager wm = (WindowManager) mActivity.getSystemService(Context.WINDOW_SERVICE); tekePictureLayout.setPadding(0,0,0,insets.getSystemWindowInsetBottom()); } else { tekePictureLayout.setPadding(0,0,0,0); } return windowInsets; }


En el caso de Samsung S8, ninguno de los métodos proporcionados anteriormente daban la altura correcta de la barra de navegación, así que usé el proveedor de altura de teclado KeyboardHeightProvider de Android . Y me dio altura en valores negativos y para mi posicionamiento de disposición ajusté ese valor en los cálculos.

Aquí está KeyboardHeightProvider.java :

import android.app.Activity; import android.content.res.Configuration; import android.graphics.Point; import android.graphics.Rect; import android.graphics.drawable.ColorDrawable; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewTreeObserver.OnGlobalLayoutListener; import android.view.WindowManager.LayoutParams; import android.widget.PopupWindow; /** * The keyboard height provider, this class uses a PopupWindow * to calculate the window height when the floating keyboard is opened and closed. */ public class KeyboardHeightProvider extends PopupWindow { /** The tag for logging purposes */ private final static String TAG = "sample_KeyboardHeightProvider"; /** The keyboard height observer */ private KeyboardHeightObserver observer; /** The cached landscape height of the keyboard */ private int keyboardLandscapeHeight; /** The cached portrait height of the keyboard */ private int keyboardPortraitHeight; /** The view that is used to calculate the keyboard height */ private View popupView; /** The parent view */ private View parentView; /** The root activity that uses this KeyboardHeightProvider */ private Activity activity; /** * Construct a new KeyboardHeightProvider * * @param activity The parent activity */ public KeyboardHeightProvider(Activity activity) { super(activity); this.activity = activity; LayoutInflater inflator = (LayoutInflater) activity.getSystemService(Activity.LAYOUT_INFLATER_SERVICE); this.popupView = inflator.inflate(R.layout.popupwindow, null, false); setContentView(popupView); setSoftInputMode(LayoutParams.SOFT_INPUT_ADJUST_RESIZE | LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED); parentView = activity.findViewById(android.R.id.content); setWidth(0); setHeight(LayoutParams.MATCH_PARENT); popupView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() { @Override public void onGlobalLayout() { if (popupView != null) { handleOnGlobalLayout(); } } }); } /** * Start the KeyboardHeightProvider, this must be called after the onResume of the Activity. * PopupWindows are not allowed to be registered before the onResume has finished * of the Activity. */ public void start() { if (!isShowing() && parentView.getWindowToken() != null) { setBackgroundDrawable(new ColorDrawable(0)); showAtLocation(parentView, Gravity.NO_GRAVITY, 0, 0); } } /** * Close the keyboard height provider, * this provider will not be used anymore. */ public void close() { this.observer = null; dismiss(); } /** * Set the keyboard height observer to this provider. The * observer will be notified when the keyboard height has changed. * For example when the keyboard is opened or closed. * * @param observer The observer to be added to this provider. */ public void setKeyboardHeightObserver(KeyboardHeightObserver observer) { this.observer = observer; } /** * Get the screen orientation * * @return the screen orientation */ private int getScreenOrientation() { return activity.getResources().getConfiguration().orientation; } /** * Popup window itself is as big as the window of the Activity. * The keyboard can then be calculated by extracting the popup view bottom * from the activity window height. */ private void handleOnGlobalLayout() { Point screenSize = new Point(); activity.getWindowManager().getDefaultDisplay().getSize(screenSize); Rect rect = new Rect(); popupView.getWindowVisibleDisplayFrame(rect); // REMIND, you may like to change this using the fullscreen size of the phone // and also using the status bar and navigation bar heights of the phone to calculate // the keyboard height. But this worked fine on a Nexus. int orientation = getScreenOrientation(); int keyboardHeight = screenSize.y - rect.bottom; if (keyboardHeight == 0) { notifyKeyboardHeightChanged(0, orientation); } else if (orientation == Configuration.ORIENTATION_PORTRAIT) { this.keyboardPortraitHeight = keyboardHeight; notifyKeyboardHeightChanged(keyboardPortraitHeight, orientation); } else { this.keyboardLandscapeHeight = keyboardHeight; notifyKeyboardHeightChanged(keyboardLandscapeHeight, orientation); } } /** * */ private void notifyKeyboardHeightChanged(int height, int orientation) { if (observer != null) { observer.onKeyboardHeightChanged(height, orientation); } } public interface KeyboardHeightObserver { void onKeyboardHeightChanged(int height, int orientation); } }

popupwindow.xml :

<?xml version="1.0" encoding="utf-8"?> <View xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/popuplayout" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/transparent" android:orientation="horizontal"/>

Uso en MainActivity

import android.os.Bundle import android.support.v7.app.AppCompatActivity import kotlinx.android.synthetic.main.activity_main.* /** * Created by nileshdeokar on 22/02/2018. */ class MainActivity : AppCompatActivity() , KeyboardHeightProvider.KeyboardHeightObserver { private lateinit var keyboardHeightProvider : KeyboardHeightProvider override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) keyboardHeightProvider = KeyboardHeightProvider(this) parentActivityView.post { keyboardHeightProvider?.start() } } override fun onKeyboardHeightChanged(height: Int, orientation: Int) { // In case of 18:9 - e.g. Samsung S8 // here you get the height of the navigation bar as negative value when keyboard is closed. // and some positive integer when keyboard is opened. } public override fun onPause() { super.onPause() keyboardHeightProvider?.setKeyboardHeightObserver(null) } public override fun onResume() { super.onResume() keyboardHeightProvider?.setKeyboardHeightObserver(this) } public override fun onDestroy() { super.onDestroy() keyboardHeightProvider?.close() } }

Para cualquier ayuda adicional, puede ver el uso avanzado de esto here .


En mi caso, cuando quería tener algo como esto:

Tuve que seguir lo mismo sugerido por @Mdlc pero probablemente un poco más simple ( solo dirigido a> = 21):

//kotlin val windowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager val realSize = Point() windowManager.defaultDisplay.getRealSize(realSize); val usableRect = Rect() windowManager.defaultDisplay.getRectSize(usableRect) Toast.makeText(this, "Usable Screen: " + usableRect + " real:"+realSize, Toast.LENGTH_LONG).show() window.decorView.setPadding(usableRect.left, usableRect.top, realSize.x - usableRect.right, realSize.y - usableRect.bottom)

También funciona en el paisaje:

Editar La solución anterior no funciona correctamente en el modo de múltiples ventanas donde el rectángulo utilizable no es más pequeño solo por la barra de navegación, sino también por el tamaño de ventana personalizado. Una cosa que noté es que en múltiples ventanas la barra de navegación no se cierne sobre la aplicación, por lo que incluso sin cambios en el relleno DecorView tenemos el comportamiento correcto:

Tenga en cuenta la diferencia entre cómo se desplaza la barra de navegación sobre la parte inferior de la aplicación a escenarios. Afortunadamente, esto es fácil de arreglar. Podemos verificar si la aplicación tiene varias ventanas. El código a continuación también incluye la parte para calcular y ajustar la posición de la barra de herramientas (solución completa: https://.com/a/14213035/477790 )

// kotlin // Let the window flow into where window decorations are window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN) window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS) // calculate where the bottom of the page should end up, considering the navigation bar (back buttons, ...) val windowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager val realSize = Point() windowManager.defaultDisplay.getRealSize(realSize); val usableRect = Rect() windowManager.defaultDisplay.getRectSize(usableRect) Toast.makeText(this, "Usable Screen: " + usableRect + " real:" + realSize, Toast.LENGTH_LONG).show() if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N || !isInMultiWindowMode) { window.decorView.setPadding(usableRect.left, usableRect.top, realSize.x - usableRect.right, realSize.y - usableRect.bottom) // move toolbar/appbar further down to where it should be and not to overlap with status bar val layoutParams = ConstraintLayout.LayoutParams(appBarLayout.layoutParams as ConstraintLayout.LayoutParams) layoutParams.topMargin = getSystemSize(Constants.statusBarHeightKey) appBarLayout.layoutParams = layoutParams }

Resultado en el modo emergente de Samsung:


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 debería verse así:

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; }


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. Combiné algunas de las respuestas aquí e hice una cláusula especial para orientación horizontal junto con isInMultiWindowMode. La clave es leer navigation_bar_height , pero también verificar config_showNavigationBar para asegurarse de que realmente deberíamos usar la altura.

Ninguna de las soluciones anteriores funcionó para mí. A partir de Android 7.0, debes tener en cuenta el modo de ventana múltiple. Esto rompe las implementaciones que comparan display.realSize con display.size ya que realSize le da las dimensiones de toda la pantalla (ambas ventanas divididas) y el tamaño solo le da las dimensiones de la ventana de su aplicación. Establecer el relleno en esta diferencia hará que toda su vista se rellene.

/** 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 NavigationBar varía para algunos dispositivos, pero también para algunas orientaciones. Primero debe verificar si el dispositivo tiene una barra de navegación, luego si el dispositivo es una tableta o no-tableta (teléfono) y, finalmente, debe observar 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 = c.getResources(); int orientation = resources.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 resources.getDimensionPixelSize(resourceId); } } return result; } private boolean isTablet(Context c) { return (c.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE; }


La altura de la barra de navegación inferior es de 48dp (tanto en modo vertical como 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 obtuve "NoSuchMethodException" durante la ejecución de la siguiente declaración con Build.VERSION.SDK_INT <17 en mi dispositivo:

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

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

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


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

public static Point getNavigationBarSize(Context context) { Point appUsableSize = getAppUsableScreenSize(context); Point realScreenSize = getRealScreenSize(context); // navigation bar on the side 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; }


Pruebe el siguiente código:

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


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

Aquí estoy agregando dos tipos de códigos,

Código Java (para Android nativo):

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 el 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; }