Cómo controlar la visualización y ocultación de NavigationBar en el sistema Android
El botón Inicio, el botón Atrás y el botón Menú en la mayoría de los teléfonos Android que utilizamos son botones físicos sensibles al tacto. Si usa Nexus4 o Nexus5 de Google, encontrará que no tienen botones físicos ni botones sensibles al tacto. En cambio, se agrega una pequeña barra negra en la parte inferior de la pantalla. Sin duda, la configuración hace que el diseño de la apariencia del teléfono sea más minimalista. Pero cuando conocí a personas que usaban teléfonos Nexus 4, se quejaron de este diseño. La razón es muy simple: la hermosa pantalla tiene un área tallada para mostrar tres botones (como se muestra en la imagen a continuación): Atrás, Inicio y. Reciente. Y ha sido ocupado allí.
En el código fuente de Android, esa área se llama NavigationBar. Al mismo tiempo, Google también ha reservado banderas en el código para controlar su visualización y ocultación. El control de visualización y ocultación de NavigationBar se coloca en SystemU. La ruta específica es: \frameworks\base\packages\SystemUI. Para teléfonos móviles con Android superior a 4.0, SystemUi consta de dos partes: StatusBar y NavigationBar. Hay una clase PhoneStatusBar.java en el proyecto SystemUI. En esta clase, puede encontrar el código relevante para controlar NavigationBar:
En el método start(), puede ver que NavigationBar se agregó en ese momento. Pero sólo sumar, decidir si se muestra o se esconde, se controla detrás.
@Override
public void start() {
mDisplay = ((WindowManager)mContext. getSystemService(Context.WINDOW_SERVICE))
.getDefaultDisplay();
updateDisplaySize();
/// M: Compatible con la función Smartbook.
if (SIMHelper.isMediatekSmartBookSupport()) {
/// M: [ALPS01097705] Consulta el estado del complemento lo antes posible.
mIsDisplayDevice = SIMHelper.isSmartBookPluggedIn (mContext);
Log.v(TAG, "start, mIsDisplayDevice=" + mIsDisplayDevice);
}
super.start(); llama a createAndAddWindows()
addNavigationBar();
// Finalmente, llama a la política de íconos para instalar/actualizar todos los íconos.
mIconPolicy = new PhoneStatusBarPolicy (mContext);
mHeadsUpObserver.onChange(true); // configurar
if (ENABLE_HEADS_UP) {
mContext.getContentResolver().registerContentObserver(
Configuración.Global.getUriFor(SETTING_HEADS_UP), verdadero,
mHeadsUpObserver);
}
}
El método de implementación específico de addNavigationBar() es el siguiente:
// Para dispositivos de pantalla pequeña (léase: teléfonos) que carecen botones de navegación de hardware
private void addNavigationBar() {
if (DEBUG) Slog.v(TAG, "addNavigationBar: a punto de agregar " + mNavigationBarView);
if (mNavigationBarView == null) return;
prepareNavigationBarView();
mWindowManager.addView(mNavigationBarView, getNavigationBarLayoutParams());
}
Puedes ver que la barra de navegación realmente mueve el administrador de ventanas a la ventana
Añade una vista a la ventana. Antes de llamar al método addNavigationBar(), se volverá a llamar al método principal super.start() de start() para determinar si se debe agregar una barra de navegación. CreateAndAddWindows() se llamará en el método de clase principal de super.start(). En este método, se juzgará si es necesario agregar una barra de navegación de visualización y luego se decidirá si se crea una instancia de NavigationBarView.
pruebe {
boolean showNav = mWindowManagerService.hasNavigationBar();
if (DEBUG) Slog.v(TAG, " hasNavigationBar=" + showNav);
if (showNav) {
mNavigationBarView =
(NavigationBarView) View.inflate(context, R.layout.navigation_bar, null);
mNavigationBarView.setDisabledFlags(mDisabled);
mNavigationBarView.setBar(this);
}
} captura (RemoteException ej) {
// ¿no hay administrador de ventanas? Buena suerte con eso
}
La clase WindowManagerService implementa la interfaz WindowManagerPolicy, por lo que WindowManagerService lo hará. Vuelva a llamar a la interfaz hasNavigationBar() de WindowManagerPolicy,
@Override
public boolean hasNavigationBar() {
return mPolicy.hasNavigationBar();
}
La llamada descendente de la política en realidad llama al método hasNavigationBar implementado por PhoneWindowManager. El siguiente código es el método hasNavigationBar(). Administrador de ventanas del teléfono.
// Use esto en lugar de verificar config_showNavigationBar para que pueda ser reemplazado consistentemente
// qemu.hw.mainkeys lo anula en el emulador.
public boolean hasNavigationBar() {
return mHasNavigationBar;
}
Y la asignación de mHasNavigationBar Se puede encontrar en el método setInitialDisplaySize(Display display, int width, int height, int densidad) en PhoneWindowManager,
if (!mHasSystemNavBar) {
mHasNavigationBar = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_showNavigationBar);
// Permitir un sistema propiedad para anular esto. Utilizado por el emulador.
// Consulte también hasNavigationBar().
String navBarOverride = SystemProperties.get("qemu.hw.mainkeys"); p>
if (! "".equals(navBarOverride)) {
if (navBarOverride.equals("1")) mHasNavigationBar = false;
si no (navBarOverride) .equals ("0")) mHasNavigationBar = true;
}
} más {
mHasNavigationBar = false;
}< /span
En el código anterior, puede ver que la configuración del valor mHasNavigationBar está determinada por dos lugares:
1. Primero, obtenga el valor de configuración config_showNavigationBar del sistema. archivo de recursos. Este La ruta del archivo para la configuración de valores es frameworks/base/core/res/res/values/config.xml
2. El sistema quiere obtener el valor "qemu.hw.mainkeys", este valor puede sobrescribir el valor de mHasNavigationBar obtenido anteriormente.
Si el valor obtenido por "qemu.hw.mainkeys" no está vacío, ya sea verdadero o falso, se debe configurar de acuerdo con la situación posterior.
Entonces, las dos configuraciones anteriores determinan simultáneamente la visualización y ocultación de NavigationBar.