
BottomAppBar est l'un des nouveaux composants de matériel Android qui ont été introduits lors de Google I / O 2018 . En déplaçant le tiroir de navigation et le menu des applications en bas de l'écran, BottomAppBar change radicalement l'apparence des applications Android.
Dans les première et deuxième parties de notre série d'articles sur BottomAppBar, nous avons rencontré BottomAppBar et discuté de ses attributs. Nous avons également expliqué comment implémenter le tiroir de navigation et les menus d'application dans le BottomAppBar.
Comportement
Selon Material Design, les composants de l'application ne sont pas statiques. Ils peuvent se déplacer ou se transformer, c'est-à-dire d'avoir une sorte de comportement. Material Design forme également un cadre pour ce comportement. Dans cet article, nous allons discuter des détails d'implémentation du comportement recommandé pour le BottomAppBar, qui est présenté sur la page des directives pour le BottomAppBar .
Disposition
La première directive décrit la disposition de la BottomAppBar. Voici ce qui est suggéré :
Pour les écrans d'application de différentes significations, vous pouvez modifier la disposition et l'ensemble des éléments de menu dans BottomAppBar. Par exemple, vous pouvez afficher plus ou moins d'éléments de menu en fonction de ce qui convient le mieux à un écran particulier.

Sur la base de cette directive, il est recommandé d'utiliser la disposition BottomAppBar sur les écrans principaux , affichant plusieurs éléments de menu et un FAB (bouton d'action flottant) centré. Sur les écrans secondaires , dont la transition est effectuée à partir des écrans principaux, la disposition BottomAppBar doit être constituée d'un FAB aligné à droite et de plusieurs éléments de menu supplémentaires. Les transitions entre ces deux écrans doivent être effectuées correctement. Gif en haut illustre cette ligne directrice.
Voyons maintenant comment ce comportement peut être implémenté. Nous avons deux fichiers xml dans le dossier res/menu
pour le menu de chaque écran:
<?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>
Lorsqu'il y a une transition entre les écrans, par exemple, en appuyant sur le bouton TOGGLE SCREEN dans notre cas, la disposition de la BottomAppBar, y compris le menu et FAB, devrait changer. Voici le code de base pour ce comportement de la disposition 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 vous souhaitez effectuer des transitions animées, vous avez besoin de code supplémentaire. Vous pouvez étudier le code source joint à la fin de cet article dans lequel vous trouverez une animation.
Défilement
Le défilement est un déclencheur de comportement important pour des composants tels que BottomAppBar. Sur la page Consignes de conception des matériaux, le comportement suivant est recommandé dans ce cas:
Lors du défilement, un BottomAppBar peut apparaître ou disparaître:
- Le défilement vers le bas masque la barre inférieure. S'il avait FAB, il se déconnecte du panneau et reste à l'écran.
- Le défilement vers le haut montre le BottomAppBar et le rattache au FAB s'il était là.
Ce qui suit est une démonstration du comportement de BottomAppBar lors du défilement.

Pour utiliser ce comportement, BottomAppBar et FAB doivent être des enfants directs de CoordinatorLayout . Ensuite, nous activons hideOnScroll et définissons les drapeaux de défilement pour 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"/>
Cela suffit pour implémenter ce comportement de BottomAppBar.
Élévation
Chaque composant du monde Material Design a une élévation similaire à notre monde physique. À BottomAppBar, l'élévation est de 8dp et le contenu de l'écran lui-même monte à 0dp . FAB dans un état statique augmente de 12dp . Les deux composants que nous retiendrons dans cet article, Navigation Drawer et Snackbar, montent respectivement à 16dp et 6dp .
En règle générale, Snackbar est un composant permettant d'avertir l'utilisateur qui apparaît en bas de l'écran. Mais s'il y a un BottomAppBar ou un tiroir de navigation à l'écran, le comportement de la Snackbar devrait changer. Dans ces cas, la Snackbar doit être affichée au - dessus des composants inférieurs. Voici une démo et un code associé à implémenter:

private fun displayMaterialSnackBar() { val marginSide = 0 val marginBottom = 550 val snackbar = Snackbar.make( coordinatorLayout2, "FAB Clicked", Snackbar.LENGTH_LONG ).setAction("UNDO") { }
Comme nous l'avons déjà mentionné, le tiroir de navigation augmente de 16dp , ce qui signifie - selon la directive -
Les menus qui sortent du BottomAppBar (par exemple, le tiroir de navigation) s'ouvrent en tant que fenêtres modales un niveau plus haut que le BottomAppBar lui-même.
Voici l'implémentation de notre tiroir de navigation:

Le tiroir de navigation est une fenêtre modale et suit donc la règle d'implémentation ci-dessus.
Les détails de l'implémentation de ce comportement sont les suivants. Dans le dossier res/menu
, un fichier de menu xml pour la vue de navigation doit être créé, qui sera utilisé dans le tiroir de navigation:
<?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>
Ensuite, un fichier de mise en page doit être créé pour le fragment à l'aide du tiroir de navigation:
<?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>
Ce fichier de disposition contient la vue de navigation et d'autres composants qui composent la disposition du tiroir de navigation. Pour créer cette disposition, nous avons besoin d'une classe de fragment qui étend 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 ->
Lorsque vous cliquez sur l'icône du tiroir de navigation, une instance de ce fragment est créée, qui s'affiche sous la forme d'une fenêtre modale:
override fun onOptionsItemSelected(item: MenuItem?): Boolean { when (item!!.itemId) { android.R.id.home -> { val bottomNavDrawerFragment = BottomNavigationDrawerFragment() bottomNavDrawerFragment.show(supportFragmentManager, bottomNavDrawerFragment.tag) } } return true }
Cet article conclut notre série d'articles sur BottomAppBar. Vous pouvez trouver le code source de cet article sur Github . Commentez et posez des questions.
← Implémentation de BottomAppBar. Partie 1: Composants matériels pour Android
← Implémentation de BottomAppBar. Partie 2: Contrôle du menu et du tiroir de navigation