Implémentation de BottomAppBar. Partie 3: Comportement pour Android

Implémentation de BottomAppBar. Partie 3: Comportement pour Android


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.

Disposition des lignes directrices


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.


Défilement et BottomAppBar


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:


Snackbar et BottomAppBar


 private fun displayMaterialSnackBar() { val marginSide = 0 val marginBottom = 550 val snackbar = Snackbar.make( coordinatorLayout2, "FAB Clicked", Snackbar.LENGTH_LONG ).setAction("UNDO") { } // Changing message text color snackbar.setActionTextColor(ContextCompat.getColor(this, R.color.colorSnackbarButton)) val snackbarView = snackbar.view val params = snackbarView.layoutParams as CoordinatorLayout.LayoutParams params.setMargins( params.leftMargin + marginSide, params.topMargin, params.rightMargin + marginSide, params.bottomMargin + marginBottom ) snackbarView.layoutParams = params snackbar.show() } 

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:


Comportement du 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 -> // Bottom Navigation Drawer menu item clicks when (menuItem.itemId) { // R.id.nav1 -> context!!.toast(getString(R.string.nav1_clicked)) } // Add code here to update the UI based on the item selected // For example, swap UI fragments here true } } } 

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

Source: https://habr.com/ru/post/fr422445/


All Articles