
BottomAppBar es uno de los nuevos componentes de Android Material que se introdujeron en Google I / O 2018 . Al mover el cajón de navegación y el menú de la aplicación a la parte inferior de la pantalla, BottomAppBar cambia radicalmente el aspecto de las aplicaciones de Android.
En la primera y segunda parte de nuestra serie de artículos sobre BottomAppBar, nos reunimos con BottomAppBar y discutimos sus atributos. También explicamos cómo implementar Navigation Drawer y los menús de aplicaciones dentro de BottomAppBar.
Comportamiento
Según Material Design, los componentes de la aplicación no son estáticos. Pueden moverse o transformarse, es decir tener algún tipo de comportamiento. El diseño de materiales también forma un marco para este comportamiento. En este artículo, discutiremos los detalles de implementación del comportamiento recomendado para BottomAppBar, que se presenta en la página de pautas para BottomAppBar .
Diseño
La primera directriz describe el diseño de BottomAppBar. Esto es lo que se sugiere :
Para pantallas de aplicación de diferentes significados, puede cambiar el diseño y el conjunto de elementos del menú en BottomAppBar. Por ejemplo, puede mostrar más o menos elementos de menú según lo que mejor se adapte a una pantalla en particular.

Según esta directriz, se recomienda que utilice el diseño BottomAppBar en las pantallas principales , que muestre varios elementos de menú y un FAB (botón de acción flotante) centrado. En las pantallas secundarias , cuya transición se realiza desde las principales, el diseño de BottomAppBar debe consistir en un FAB alineado a la derecha y varios elementos de menú adicionales. Las transiciones entre estas dos pantallas deben realizarse correctamente. Gif en la parte superior muestra esta guía.
Ahora veamos cómo se puede implementar este comportamiento. Tenemos dos archivos xml en la carpeta res/menu
para el menú de cada pantalla:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/app_bar_search" android:icon="@drawable/baseline_search_white_24" android:title="@string/action_search" app:showAsAction="ifRoom"/> </menu>
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/app_bar_mail" android:icon="@drawable/baseline_mail_white_24" android:title="@string/action_mail" app:showAsAction="ifRoom"/> <item android:id="@+id/app_bar_delete" android:icon="@drawable/baseline_delete_white_24" android:title="@string/action_delete" app:showAsAction="ifRoom"/> <item android:id="@+id/app_bar_archieve" android:icon="@drawable/baseline_archive_white_24" android:title="@string/action_archieve" app:showAsAction="ifRoom"/> </menu>
Cuando hay una transición entre pantallas, por ejemplo, presionando el botón TOGGLE SCREEN en nuestro caso, el diseño de BottomAppBar, incluido el menú y FAB, debería cambiar. Aquí está el código básico para este comportamiento del diseño BottomAppBar:
// Hide navigation drawer icon bottom_app_bar.navigationIcon = null // Move FAB from the center of BottomAppBar to the end of it bottom_app_bar.fabAlignmentMode = BottomAppBar.FAB_ALIGNMENT_MODE_END // Replace the action menu bottom_app_bar.replaceMenu(bottomappbar_menu_secondary) // Change FAB icon fab?.setImageDrawable(baseline_reply_white_24)
Si desea hacer transiciones animadas, necesita un código adicional. Puede estudiar el código fuente adjunto al final de este artículo en el que encontrará animación.
Desplazamiento
El desplazamiento es un desencadenante de comportamiento importante para componentes como BottomAppBar. En la página de pautas de diseño de materiales, se recomienda el siguiente comportamiento para este caso:
Al desplazarse, una BottomAppBar puede aparecer o desaparecer:
- Desplazarse hacia abajo oculta la BottomAppBar. Si tenía FAB, se desconecta del panel y permanece en la pantalla.
- Al desplazarse hacia arriba, se muestra BottomAppBar y se vuelve a conectar a la FAB si estaba allí.
La siguiente es una demostración del comportamiento de BottomAppBar al desplazarse.

Para usar este comportamiento, BottomAppBar y FAB deben ser hijos directos de CoordinatorLayout . Luego habilitamos hideOnScroll y establecemos las banderas de desplazamiento para BottomAppBar:
<com.google.android.material.bottomappbar.BottomAppBar android:id="@+id/bottom_app_bar" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" app:fabAlignmentMode="center" app:hideOnScroll="true" app:layout_scrollFlags="scroll|enterAlways"/>
Esto es suficiente para implementar este comportamiento de BottomAppBar.
Elevacion
Cada componente en el mundo de Diseño de materiales tiene una elevación similar a nuestro mundo físico. En BottomAppBar, la elevación es de 8dp , y el contenido de la pantalla se eleva a 0dp . FAB en un estado estático aumenta en 12dp . Los dos componentes que recordaremos en este artículo, Navigation Drawer y Snackbar, aumentan 16dp y 6dp respectivamente.
Típicamente, Snackbar es un componente para notificar al usuario que aparece desde la parte inferior de la pantalla. Pero si hay un BottomAppBar o Navigation Drawer en la pantalla, el comportamiento de Snackbar debería cambiar. En estos casos, la Snackbar debe mostrarse encima de los componentes inferiores. Aquí hay una demostración y un código relacionado para implementar:

private fun displayMaterialSnackBar() { val marginSide = 0 val marginBottom = 550 val snackbar = Snackbar.make( coordinatorLayout2, "FAB Clicked", Snackbar.LENGTH_LONG ).setAction("UNDO") { }
Como ya mencionamos, el cajón de navegación aumenta en 16dp , lo que significa, según la directriz,
Los menús que se caen de BottomAppBar (por ejemplo, Navigation Drawer) se abren como ventanas modales un nivel más alto que BottomAppBar.
La siguiente es la implementación de nuestro cajón de navegación:

Navigation Drawer es una ventana modal y, por lo tanto, sigue la regla de implementación anterior.
Los detalles de la implementación de este comportamiento son los siguientes. En la carpeta res/menu
, se debe crear un archivo de menú xml para la Vista de navegación , que se utilizará en el Cajón de navegación:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <group android:checkableBehavior="none"> <item android:id="@+id/nav1" android:icon="@drawable/baseline_mail_white_24" android:title="@string/nav_item1" /> <item android:id="@+id/nav2" android:icon="@drawable/baseline_bookmark_white_24" android:title="@string/nav_item2" /> <item android:id="@+id/nav3" android:icon="@drawable/baseline_message_white_24" android:title="@string/nav_item3" /> <item android:id="@+id/nav4" android:icon="@drawable/baseline_note_white_24" android:title="@string/nav_item4" /> <item android:id="@+id/nav5" android:icon="@drawable/baseline_location_on_white_24" android:title="@string/nav_item5" /> <item android:id="@+id/nav6" android:icon="@drawable/baseline_sync_white_24" android:title="@string/nav_item6" /> <item android:id="@+id/nav7" android:icon="@drawable/baseline_cloud_upload_white_24" android:title="@string/nav_item7" /> <item android:id="@+id/nav8" android:icon="@drawable/baseline_favorite_white_24" android:title="@string/nav_item8" /> <item android:id="@+id/nav9" android:icon="@drawable/baseline_chrome_reader_mode_white_24" android:title="@string/nav_item9" /> <item android:id="@+id/nav10" android:icon="@drawable/baseline_select_all_white_24" android:title="@string/nav_item10" /> <item android:id="@+id/nav11" android:icon="@drawable/baseline_sort_white_24" android:title="@string/nav_item11" /> <item android:id="@+id/nav12" android:icon="@drawable/baseline_access_time_white_24" android:title="@string/nav_item12" /> <item android:id="@+id/nav13" android:icon="@drawable/baseline_data_usage_white_24" android:title="@string/nav_item13" /> </group> </menu>
Luego, se debe crear un archivo de diseño para el fragmento utilizando el cajón de navegación:
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/navigation_view_layout" android:layout_width="match_parent" android:layout_height="wrap_content" app:behavior_hideable="true" app:layout_behavior="@string/bottom_sheet_behavior"> <com.google.android.material.navigation.NavigationView android:id="@+id/navigation_view" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="bottom" android:layout_marginTop="4dp" android:paddingBottom="40dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/view2" app:menu="@menu/bottom_nav_drawer_menu" app:theme="@style/NavigationDrawerStyle" /> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="12dp" android:layout_marginTop="16dp" android:fontFamily="@font/rubik_medium" android:text="@string/bottom_sheet_name" android:textColor="@color/colorAccent" android:textSize="18sp" android:textStyle="bold" app:layout_constraintStart_toEndOf="@+id/imageView" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/textView2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="2dp" android:text="@string/bottom_sheet_email" android:textColor="@color/colorAccent" app:layout_constraintStart_toStartOf="@+id/textView" app:layout_constraintTop_toBottomOf="@+id/textView" /> <ImageView android:id="@+id/imageView" android:layout_width="48dp" android:layout_height="48dp" android:layout_marginStart="24dp" android:background="@drawable/baseline_account_circle_black_48" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@+id/textView" /> <View android:id="@+id/view2" android:layout_width="match_parent" android:layout_height="2dip" android:layout_marginTop="15dp" android:background="#447e7e7e" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/textView2" /> <ImageView android:id="@+id/close_imageview" android:layout_width="24dp" android:layout_height="24dp" android:layout_marginTop="8dp" android:layout_marginEnd="16dp" android:layout_marginBottom="8dp" android:background="@drawable/baseline_close_black_24" android:visibility="gone" app:layout_constraintBottom_toBottomOf="@+id/textView2" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="@+id/textView" /> </androidx.constraintlayout.widget.ConstraintLayout>
Este archivo de diseño contiene la Vista de navegación y otros componentes que forman el diseño para el Cajón de navegación. Para crear este diseño, necesitamos una clase de fragmento que extienda BottomSheetDialogFragment:
class BottomNavigationDrawerFragment: BottomSheetDialogFragment() { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return inflater.inflate(R.layout.fragment_bottom_navigation_drawer, container, false) } override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) navigation_view.setNavigationItemSelectedListener { menuItem ->
Cuando hace clic en el icono del cajón de navegación, se crea una instancia de este fragmento, que se muestra como una ventana modal:
override fun onOptionsItemSelected(item: MenuItem?): Boolean { when (item!!.itemId) { android.R.id.home -> { val bottomNavDrawerFragment = BottomNavigationDrawerFragment() bottomNavDrawerFragment.show(supportFragmentManager, bottomNavDrawerFragment.tag) } } return true }
Este artículo concluye nuestra serie de artículos sobre BottomAppBar. Puede encontrar el código fuente de este artículo en Github . Comenta y haz preguntas.
← Implementación de BottomAppBar. Parte 1: componentes materiales para Android
← Implementación de BottomAppBar. Parte 2: Control de menú y cajón de navegación