A la conférence Google I/O 2018, google a introduit aux composants material un nouveau composant appelé Bottom App Bar .Il se place en bas de la fenêtre contrairement à la Toolbar qui se place en haut de la fenêtre.
Vous pouvez voir ce composant comme une toolbar avec comme possibilité de se raccrocher à un FloatingactionButton et une grande flexibilité de pouvoir positionner le bouton flottant à différents endroits.
La librairie des composants material fournit de nouveaux styles pour le bottom app bar, lui permettant d’avoir l’apparence des composants de la mise à jour du material design.
Table des matières
Créer un nouveau projet
Créer un nouveau projet en allant sur File->New->New Project. Sélectionnez Empty activity puis cliquez sur Next. Dans la fenêtre qui s’affiche ,nommez votre projet par BottomAppBar , puis dans le champ language, sélectionnez votre langage de programmation et enfin cliquez sur Finish.
Ajouter la librairie de composants material
Pour utiliser le composant BottomAppBar, vous devez ajouter la librairies des composants material comme dépendance dans votre projet.Pour cela Ouvrez le fichier build.gradle(Module:app) puis ajoutez la dépendance suivante comme suit
dependencies { ... implementation 'com.google.android.material:material:1.1.0-alpha10' ... }
Utilisation Basique
Créez d’abord une vecteur drawable pour l’icon de navigation du bottomAppBar en allant sur File->New ->Vector Asset puis choisissez une icon. N’oubliez pas de définir la couleur de l’icon à #ffffff.
Pour ajouter un simple BottomAppBar dans votre projet, ouvrez le fichier res/layout/activity_main.xml puis ajoutez le contenu suivant
<?xml version="1.0" encoding="utf-8"?> <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <com.google.android.material.bottomappbar.BottomAppBar android:id="@+id/bar" android:layout_width="match_parent" android:layout_gravity="bottom" android:layout_height="wrap_content" android:backgroundTint="@color/colorPrimary" app:navigationIcon="@drawable/bottomappbarnavigation"/> </androidx.coordinatorlayout.widget.CoordinatorLayout>
Résultat
Accrocher un bouton flottant au BottomAppBar
Créer une vector drawable comme précédemment pour représenter l’icon du bouton flottant.
Vous pouvez raccrocher un bouton flottant au BottomAppBar avec l’attribut app:layout_anchor ou dans le code avec la méthode fab.setLayoutParams() en Java et la méthode fab.setLayoutParams en Kotlin
Raccrocher le bouton flottant au bottom app bar dans le code
val layoutParams:CoordinatorLayout.LayoutParams=fab.layoutParams as CoordinatorLayout.LayoutParams layoutParams.anchorId=R.id.bar fab.layoutParams=layoutParams
CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) fab.getLayoutParams(); layoutParams.setAnchorId(R.id.bar); fab.setLayoutParams(layoutParams);
Raccrocher le bouton flottant au bottom app bar dans le fichier layout
<?xml version="1.0" encoding="utf-8"?> <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <com.google.android.material.bottomappbar.BottomAppBar android:id="@+id/bar" android:layout_width="match_parent" android:layout_gravity="bottom" android:layout_height="wrap_content" android:backgroundTint="@color/colorPrimary" app:navigationIcon="@drawable/bottomappbarnavigation" /> <com.google.android.material.floatingactionbutton.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_anchor="@id/bar" android:src="@drawable/add" app:tint="@android:color/white"/> </androidx.coordinatorlayout.widget.CoordinatorLayout>
Résultat:
Si vous n’avez pas encore lu le tutoriel sur les boutons flottant, cliquez ici
Le nouveau style material
Pour appliquer au composant BottomAppBar le nouveau style des composants material, le thème de votre application doit hériter d’un des thèmes de la librairie des composants material( Theme.MaterialComponents ).Voir l’exemple suivant
<style name="AppTheme" parent="Theme.MaterialComponents.Light.DarkActionBar"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> </style>
Si le thème de votre application n’hérite pas d’un des thèmes de la librairie des composants material( les différentes variantes du du thème Theme.MaterialComponents ), vous devez directement appliquer au bottom app bar un des styles du bottom app bar de la librairie des composants material comme suit
<com.google.android.material.floatingactionbutton.FloatingActionButton android:id="@+id/fab" style="@style/Widget.MaterialComponents.BottomAppBar" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_anchor="@id/bar" android:src="@drawable/add" app:tint="@android:color/white" />
Les thèmes
Vous pouvez créer un thème de couleur, de forme et de typographie sur le bottom App Bar. Pour cela vous devez directement appliquer un style au bottom app bar avec le style de base Widget.MaterialComponents.BottomAppBar . Il existe deux autres variantes de style qui hérite du style de base Widget.MaterialComponents.BottomAppBar . Il s’agit des styles Widget.MaterialComponents.BottomAppBar.Colored et Widget.MaterialComponents.BottomAppBar.PrimarySurface. Les styles Widget.MaterialComponents.BottomAppBar et Widget.MaterialComponents.BottomAppBar.PrimarySurface sont les mêmes.
La différence entre les deux style qui se termine par .Colored et .PrimarySurface est la l’attribut de couleur utilisé pour définir la couleur d’arrière plan du bottomAppBar.
Couleur
Pour changer la couleur d’arrière plan du bottomAppBar , vous devez utiliser l’attribut backgroundTint. La variante qui se termine par .Colored utilise la couleur défini dans l’attribut de couleur colorPrimary pour définir la couleur d’arrière plan tandis que la variante qui se termine par .PrimarySurface utilise la couleur définir dans l’attribut de couleur colorSurface
.
La couleur des items de menu et de navigation peuvent être changé avec l’attribut materialThemeOverlay. Les valeurs des attributs d’un materialThemeOverlay viennent se superposer et changer les valeurs de style définit sur un composant.
Il existe deux variants de style materialThemeOverlay tels que ThemeOverlay.MaterialComponents.BottomAppBar.Primary et ThemeOverlay.MaterialComponents.BottomAppBar.Surface qui hérite du style ThemeOverlay.MaterialComponents.BottomAppBar. Ces deux variantes ont deux attributs colorControlNormal
(pour personnaliser la couleur des icons des items de menu et l’item de navigation) et actionMenuTextColor
(Pour personnalisé la couleur du texte du menu flottant) .
Dans le style ThemeOverlay.MaterialComponents.BottomAppBar.Primary les attributs colorControlNormal et actionMenuTextColor utilisent la couleur défini dans l’attribut colorOnPrimary et dans le style ThemeOverlay.MaterialComponents.BottomAppBar.Surface , les attributs colorControlNormal et actionMenuTextColor utilisent la couleur défini dans l’attribut material_on_surface_emphasis_medium.
Les attributs du Bottom App bar
Voici la liste des attributs du bottom app bar que vous pouvez utiliser
Bottom App Bar Attributes
Feature | Relevant attributes |
---|---|
Background Tint | app:backgroundTint |
FAB Alignment Mode | app:fabAlignmentMode |
FAB Animation Mode | app:fabAnimationMode |
FAB Cradle Margin | app:fabCradleMargin |
FAB Cradle Corner Radius | app:fabCradleRoundedCornerRadius |
FAB Vertical Offset | app:fabCradleVerticalOffset |
Hide on scroll | app:hideOnScroll |
Add Padding for Bottom Insets | app:paddingBottomSystemWindowInsets |
Add Padding for Left Insets | app:paddingLeftSystemWindowInsets |
Add Padding for Right Insets | app:paddingRightSystemWindowInsets |
Vous pouvez ajouter un menu au Bottom App Bar directement dans le fichier xml de la vue ou dans le code
Méthode1: On ajouter un menu au Bottom App Bar dans le fichier xml grâce à l’attribut app:menu
L’exemple suivant ajoute un menu au Bottom App Bar grâce à l’attribut app:menu
<?xml version="1.0" encoding="utf-8"?> <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <com.google.android.material.bottomappbar.BottomAppBar android:id="@+id/bar" android:layout_width="match_parent" android:layout_gravity="bottom" android:layout_height="wrap_content" android:backgroundTint="@color/colorPrimary" app:menu="@menu/menu" app:navigationIcon="@drawable/bottomappbarnavigation" /> <com.google.android.material.floatingactionbutton.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_anchor="@id/bar" android:src="@drawable/add" app:tint="@android:color/white" /> </androidx.coordinatorlayout.widget.CoordinatorLayout>
Méthode2: Vous pouvez aussi ajouter un menu au Bottom App Bar dans le code grâce à la méthode replaceMenu de la manière suivant
package com.example.bottomappbar import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.view.Menu import com.google.android.material.bottomappbar.BottomAppBar class MainActivity : AppCompatActivity() { private lateinit var mBottomAppBar: BottomAppBar override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) mBottomAppBar=findViewById(R.id.bar) mBottomAppBar.replaceMenu(R.menu.menu) } }
package com.example.bottomappbarjava; import androidx.appcompat.app.AppCompatActivity; import androidx.coordinatorlayout.widget.CoordinatorLayout; import android.os.Bundle; import com.google.android.material.bottomappbar.BottomAppBar; import com.google.android.material.floatingactionbutton.FloatingActionButton; public class MainActivity extends AppCompatActivity { private BottomAppBar mBottomAppBar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mBottomAppBar=findViewById(R.id.bar); mBottomAppBar.replaceMenu(R.menu.menu); } }
Une autre manière d’ajouter un menu au bottom app bar est d’appeler la méthode setSupportActionBar () de l’activité depuis une activité ou un fragment.Tout comme une Toolbar, cela configure les méthodes callback Activity#onCreateOptionsMenu() et Activity#onOptionsItemSelected() pou créer et gérer les actions de l’activité auquel se branche une Toolbar. Donc dès que cette méthode est appelée, le bottom app bar est automatiquement branché à ces méthodes callback.
Pour appeler la méthode setSupportActionBar(), votre activité doit hérité de la classe AppCompatActivity d’AndroidX et en plus vous devez utiliser un thème sans actionBar comme par exemple le Theme.MaterialComponents.Light.NoActionBar( .NoActionBar ).
Note:Lorsque vous ajouter le menu avec setSupportActionBar() ,cela vous permet aussi de savoir quand l’item android.R.id.home
est cliqué (L’utilisateur souhaitez faire un retour en arrière) .
Appeler la méthode setSupportActionBar depuis une actvité
Vous pouvez appeler cette méthode depuis une activité de la manière suivante
mBottomAppBar=findViewById(R.id.bar) setSupportActionBar(mBottomAppBar)
mBottomAppBar=findViewById(R.id.bar); setSupportActionBar(mBottomAppBar);
Appeler la méthode setSupportActionBar() depuis un fragment
Si le menu que vous souhaitez ajouter au bottom app bar est dans un fragment vous devez effectuer quelque action pour que cela puis s’afficher dans le bottom app bar déclarer dans la vue de l’activité.
Vous devez appeler la méthode setHasOptionsMenu() dans la méthode Oncreate() du fragment pour demander à l’activer d’ajouter les menu créer dans le fragment au menu de l’activité
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setHasOptionsMenu(true) }
@Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setHasOptionsMenu(true); }
Puis vous devez appeler la méthode setSupportActionBar() dans la méthode onCreateView du fragment comment suit
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { val activity=(requireActivity() as AppCompatActivity) val view=inflater.inflate(R.layout.activity_main,container,false) val mBottomAppBar:BottomAppBar=view.findViewById(R.id.bar) activity.setSupportActionBar(mBottomAppBar) return view }
@Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { AppCompatActivity activity=(AppCompatActivity)requireActivity(); View view=inflater.inflate(R.layout.activity_main,container,false); BottomAppBar mBottomAppBar=view.findViewById(R.id.bar); activity.setSupportActionBar(mBottomAppBar); return view; }
Vous devez ensuite créer le menu dans l’activité comme suit.
override fun onCreateOptionsMenu(menu: Menu?): Boolean { menuInflater.inflate(R.menu.menu,menu) return true }
@Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu,menu); return true; }
Vous devez ensuite créer le menu dans le fragment comme suit.
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { inflater.inflate(R.menu.menu,menu) }
@Override public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { inflater.inflate(R.menu.menu,menu); }
Gérer les clics sur les items de menu quand la méthode setSupportActionBar() est appelée
Vous pouvez gérer les clics sur les items de menu dans la méthode onOptionsItemSelected comme vous le faites avec une Toolbar
override fun onOptionsItemSelected(item: MenuItem): Boolean { when(item.itemId){ R.id.menu_appel->{ true } R.id.menu_message ->{ true } else -> { false } } return super.onOptionsItemSelected(item) }
@Override public boolean onOptionsItemSelected(@NonNull MenuItem item) { switch (item.getItemId()){ case R.id.menu_appel: return true; case R.id.menu_message: return true; } return super.onOptionsItemSelected(item); }
Si vous avez créer le menu du bottom app bar directement depuis le fichier xml de la vue ou si vous l’avez créé grâce à la méthode replaceMenu(),vous devez gérer le clic des items de la manière suivante
mBottomAppBar.setOnMenuItemClickListener {item -> when(item.itemId){ R.id.menu_appel->{ true } R.id.menu_message ->{ true } else -> { false } } }
mBottomAppBar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { switch (item.getItemId()){ case R.id.menu_appel: return true; case R.id.menu_message: return true; } return false; } });
Voici le menu utilisé dans les exemples précédents
<?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"> <item android:id="@+id/menu_appel" android:title="Appeler" android:icon="@drawable/appel" /> <item android:id="@+id/menu_favori" android:title="Favori" android:icon="@drawable/favorie" /> <item android:id="@+id/menu_message" android:title="Message" /> </menu>
Si vous souhaitez forcer l’affichage des icons du menu, utilisez l’attribut app:showAsAction= »ifRoom » dans chaque item de menu.
Voici le résultat obtenu lorsque vous ajoutez un menu
Vous pouvez ajouter l’item de navigation avec l’attribut app:navigationIcon comme dans l’exemple suit
<com.google.android.material.bottomappbar.BottomAppBar android:id="@+id/bar" app:navigationIcon="@drawable/bottomappbarnavigation" />
Ou vous pouvez aussi ajouter l’item de navigation dans le code de la manière suivante
mBottomAppBar.setNavigationIcon(R.drawable.bottomappbarnavigation)
mBottomAppBar.setNavigationIcon(R.drawable.bottomappbarnavigation);
Note:La gestion du clic de l’item de Navigation se fait comme vous le faites pour les autres item du Bottom App bar .C’est à dire géré le clic soir dans la méthode setOnMenuItemClickListener() ,soit dans la méthode onOptionsItemSelected().
Positionner le bouton flottant au centre
Il s’agit du positionnement par défaut lorsque vous raccrocher le bouton flottant au Bottom App bar.Vous pouvez manuellement positionner le bouton flottant au centre grâce à la méthode fabAlignmentMode en définissant la valeur à center.
<com.google.android.material.bottomappbar.BottomAppBar android:id="@+id/bar" android:layout_width="match_parent" android:layout_gravity="bottom" android:layout_height="wrap_content" android:backgroundTint="@color/colorPrimary" app:fabAlignmentMode="center" app:navigationIcon="@drawable/bottomappbarnavigation" />
Positionner le bouton flotant à droit
Vous pouvez manuellement positionner le bouton flottant à droit grâce à la méthode fabAlignmentMode en définissant la valeur à end.
<?xml version="1.0" encoding="utf-8"?> <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <com.google.android.material.bottomappbar.BottomAppBar android:id="@+id/bar" android:layout_width="match_parent" android:layout_gravity="bottom" android:layout_height="wrap_content" android:backgroundTint="@color/colorPrimary" app:fabAlignmentMode="end" app:navigationIcon="@drawable/bottomappbarnavigation" /> <com.google.android.material.floatingactionbutton.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_anchor="@id/bar" android:src="@drawable/add" app:tint="@android:color/white" /> </androidx.coordinatorlayout.widget.CoordinatorLayout>
L’image suivante illustre ce que vous devez obtenir
Le diamètre du creux du bottom app bar
L’attribut fabCradleVerticalOffset
vous permet de définir la distance du décalage vertical entre le bouton flottant et le bottom app par rapport au creux.Si sa valeur est définir à 0dp,le centre du bouton flottant sera aligner avec le haut du bottom app bar.
Bouton flottant resorti
<?xml version="1.0" encoding="utf-8"?> <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <com.google.android.material.bottomappbar.BottomAppBar android:id="@+id/bar" android:layout_width="match_parent" android:layout_gravity="bottom" android:layout_height="wrap_content" android:backgroundTint="@color/colorPrimary" app:fabAlignmentMode="end" app:fabCradleVerticalOffset="20dp" app:navigationIcon="@drawable/bottomappbarnavigation" /> <com.google.android.material.floatingactionbutton.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_anchor="@id/bar" android:src="@drawable/add" app:tint="@android:color/white" /> </androidx.coordinatorlayout.widget.CoordinatorLayout>
Bouton flottant enfoncé
<?xml version="1.0" encoding="utf-8"?> <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <com.google.android.material.bottomappbar.BottomAppBar android:id="@+id/bar" android:layout_width="match_parent" android:layout_gravity="bottom" android:layout_height="wrap_content" android:backgroundTint="@color/colorPrimary" app:fabAlignmentMode="end" app:fabCradleVerticalOffset="0dp" app:navigationIcon="@drawable/bottomappbarnavigation" /> <com.google.android.material.floatingactionbutton.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_anchor="@id/bar" android:src="@drawable/add" app:tint="@android:color/white" /> </androidx.coordinatorlayout.widget.CoordinatorLayout>
Le rayon des coins du creux du bottom app bar
L’attribut app:fabCradleRoundedCornerRadius vous permet de définir le rayon des coins du creux du bottom app bar. Lorsque la valeur du rayon est à 0, les coins du creux sont carré et lorsque la valeur est supérieur à zéro,les coins sont arrondi.
L’exemple suivant défini la valeur du rayon à 20
<?xml version="1.0" encoding="utf-8"?> <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <com.google.android.material.bottomappbar.BottomAppBar android:id="@+id/bar" android:layout_width="match_parent" android:layout_gravity="bottom" android:layout_height="wrap_content" android:backgroundTint="@color/colorPrimary" app:fabAlignmentMode="end" app:fabCradleVerticalOffset="0dp" app:fabCradleRoundedCornerRadius="20dp" app:navigationIcon="@drawable/bottomappbarnavigation" /> <com.google.android.material.floatingactionbutton.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_anchor="@id/bar" android:src="@drawable/add" app:tint="@android:color/white" /> </androidx.coordinatorlayout.widget.CoordinatorLayout>
L’espace entre le creux et le bouton flottant
L’attribut app:fabCradleMargin permet de définir l’espace entre le creux du bottom app bar et le bouton flottant
Espace minime
<?xml version="1.0" encoding="utf-8"?> <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <com.google.android.material.bottomappbar.BottomAppBar android:id="@+id/bar" android:layout_width="match_parent" android:layout_gravity="bottom" android:layout_height="wrap_content" android:backgroundTint="@color/colorPrimary" app:fabCradleMargin="5dp" app:navigationIcon="@drawable/bottomappbarnavigation" /> <com.google.android.material.floatingactionbutton.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_anchor="@id/bar" android:src="@drawable/add" app:tint="@android:color/white" /> </androidx.coordinatorlayout.widget.CoordinatorLayout>
Espacement large
<?xml version="1.0" encoding="utf-8"?> <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <com.google.android.material.bottomappbar.BottomAppBar android:id="@+id/bar" android:layout_width="match_parent" android:layout_gravity="bottom" android:layout_height="wrap_content" android:backgroundTint="@color/colorPrimary" app:fabCradleMargin="20dp" app:navigationIcon="@drawable/bottomappbarnavigation" /> <com.google.android.material.floatingactionbutton.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_anchor="@id/bar" android:src="@drawable/add" app:tint="@android:color/white" /> </androidx.coordinatorlayout.widget.CoordinatorLayout>
L’animation du changement du mode d’alignement du bouton flottant
L’attribut app:fabAnimationMode vous permet de définir l’animation lorsque le mode d’alignement du bouton flottant changera dynamiquement. Vous pouvez définir la valeur de cet attribut à scale ou slide
Mode d’animation définit à scale
Voici l’animation que vous pouvez obtenir lorsque le mode d’animation est défini à scale.
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <com.google.android.material.button.MaterialButton android:id="@+id/btn" android:text="Changer" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintRight_toRightOf="parent" android:layout_width="match_parent" android:layout_height="wrap_content"/> <androidx.coordinatorlayout.widget.CoordinatorLayout android:layout_width="match_parent" android:layout_height="match_parent"> <com.google.android.material.bottomappbar.BottomAppBar android:id="@+id/bar" android:layout_width="match_parent" android:layout_gravity="bottom" android:layout_height="wrap_content" android:backgroundTint="@color/colorPrimary" app:fabAlignmentMode="end" app:fabAnimationMode="scale" app:navigationIcon="@drawable/bottomappbarnavigation" /> <com.google.android.material.floatingactionbutton.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_anchor="@id/bar" android:src="@drawable/add" app:tint="@android:color/white" /> </androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.constraintlayout.widget.ConstraintLayout>
package com.example.bottomappbar import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.view.Menu import android.view.MenuItem import com.google.android.material.bottomappbar.BottomAppBar import com.google.android.material.button.MaterialButton class MainActivity : AppCompatActivity() { private lateinit var mBottomAppBar: BottomAppBar private lateinit var btn: MaterialButton private var changeMod: Boolean=false override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) mBottomAppBar=findViewById(R.id.bar) btn=findViewById(R.id.btn) btn.setOnClickListener { if(changeMod){ changeMod=false mBottomAppBar.fabAlignmentMode=BottomAppBar.FAB_ALIGNMENT_MODE_CENTER } else{ changeMod=true mBottomAppBar.fabAlignmentMode=BottomAppBar.FAB_ALIGNMENT_MODE_END } } } }
package com.example.bottomappbarjava; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; import androidx.coordinatorlayout.widget.CoordinatorLayout; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; import com.google.android.material.bottomappbar.BottomAppBar; import com.google.android.material.button.MaterialButton; import com.google.android.material.floatingactionbutton.FloatingActionButton; public class MainActivity extends AppCompatActivity { private BottomAppBar mBottomAppBar; private boolean changeMod=false; private MaterialButton btn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mBottomAppBar=findViewById(R.id.bar); btn=findViewById(R.id.btn); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if(changeMod){ changeMod=false; mBottomAppBar.setFabAlignmentMode(BottomAppBar.FAB_ALIGNMENT_MODE_CENTER); } else{ changeMod=true; mBottomAppBar.setFabAlignmentMode(BottomAppBar.FAB_ALIGNMENT_MODE_END); } } }); } }
Mode d’animation définit à slide
Voici l’animation que vous pouvez obtenir lorsque le mode d’animation est défini à slide
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <com.google.android.material.button.MaterialButton android:id="@+id/btn" android:text="Changer" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintRight_toRightOf="parent" android:layout_width="match_parent" android:layout_height="wrap_content"/> <androidx.coordinatorlayout.widget.CoordinatorLayout android:layout_width="match_parent" android:layout_height="match_parent"> <com.google.android.material.bottomappbar.BottomAppBar android:id="@+id/bar" android:layout_width="match_parent" android:layout_gravity="bottom" android:layout_height="wrap_content" android:backgroundTint="@color/colorPrimary" app:fabAlignmentMode="end" app:fabAnimationMode="slide" app:navigationIcon="@drawable/bottomappbarnavigation" /> <com.google.android.material.floatingactionbutton.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_anchor="@id/bar" android:src="@drawable/add" app:tint="@android:color/white" /> </androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.constraintlayout.widget.ConstraintLayout>
package com.example.bottomappbar import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.view.Menu import android.view.MenuItem import com.google.android.material.bottomappbar.BottomAppBar import com.google.android.material.button.MaterialButton class MainActivity : AppCompatActivity() { private lateinit var mBottomAppBar: BottomAppBar private lateinit var btn: MaterialButton private var changeMod: Boolean=false override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) mBottomAppBar=findViewById(R.id.bar) btn=findViewById(R.id.btn) btn.setOnClickListener { if(changeMod){ changeMod=false mBottomAppBar.fabAlignmentMode=BottomAppBar.FAB_ALIGNMENT_MODE_CENTER } else{ changeMod=true mBottomAppBar.fabAlignmentMode=BottomAppBar.FAB_ALIGNMENT_MODE_END } } } }
package com.example.bottomappbarjava; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; import androidx.coordinatorlayout.widget.CoordinatorLayout; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; import com.google.android.material.bottomappbar.BottomAppBar; import com.google.android.material.button.MaterialButton; import com.google.android.material.floatingactionbutton.FloatingActionButton; public class MainActivity extends AppCompatActivity { private BottomAppBar mBottomAppBar; private boolean changeMod=false; private MaterialButton btn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mBottomAppBar=findViewById(R.id.bar); btn=findViewById(R.id.btn); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if(changeMod){ changeMod=false; mBottomAppBar.setFabAlignmentMode(BottomAppBar.FAB_ALIGNMENT_MODE_CENTER); } else{ changeMod=true; mBottomAppBar.setFabAlignmentMode(BottomAppBar.FAB_ALIGNMENT_MODE_END); } } }); } }
Comportement lors du scroll
L’attribut app:hideOnScroll vous permet de définir comment vous souhaitez que le bottom app bar réagisse lorsque la vue contient un élément scrollable(Recyclerview ou NestedScrollView).Il faut savoir que que le contenu scrollable et le bottom app bar doivent être placé dans un CoordinatorLayout.
Cet attribut peut prendre deux valeur :true et false. Si la valeur définie est true,le bottom app bar va se cacher lorsque l’utilisateur scroll le contenu vers le haut.
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <androidx.coordinatorlayout.widget.CoordinatorLayout android:layout_width="match_parent" android:layout_height="match_parent"> <androidx.core.widget.NestedScrollView android:layout_width="match_parent" android:paddingRight="16dp" android:paddingLeft="16dp" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:backgroundTint="#f1f1f1" android:orientation="vertical" android:layout_height="match_parent"> <androidx.cardview.widget.CardView android:layout_width="match_parent" android:layout_margin="8dp" android:layout_height="wrap_content" > <LinearLayout android:layout_width="match_parent" android:orientation="vertical" android:padding="8dp" android:layout_height="wrap_content"> <TextView android:text="Contenu scrollable" android:textStyle="bold" android:textSize="16sp" android:textColor="#000000" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:text="Contrairement à une opinion répandue, le Lorem Ipsum n'est pas simplement du texte aléatoire. Il trouve ses racines dans une oeuvre de la littérature latine classique datant de 45 av. J.-C., le rendant vieux de 2000 ans. Un professeur du Hampden-Sydney College, en Virginie, s'est intéressé à un des mots latins les plus obscurs, consectetur, extrai" android:textSize="14sp" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout> </androidx.cardview.widget.CardView> <androidx.cardview.widget.CardView android:layout_width="match_parent" android:layout_margin="8dp" android:layout_height="wrap_content" > <LinearLayout android:layout_width="match_parent" android:orientation="vertical" android:padding="8dp" android:layout_height="wrap_content"> <TextView android:text="Contenu scrollable" android:textStyle="bold" android:textSize="16sp" android:textColor="#000000" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:text="Contrairement à une opinion répandue, le Lorem Ipsum n'est pas simplement du texte aléatoire. Il trouve ses racines dans une oeuvre de la littérature latine classique datant de 45 av. J.-C., le rendant vieux de 2000 ans. Un professeur du Hampden-Sydney College, en Virginie, s'est intéressé à un des mots latins les plus obscurs, consectetur, extrai" android:textSize="14sp" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout> </androidx.cardview.widget.CardView> <androidx.cardview.widget.CardView android:layout_width="match_parent" android:layout_margin="8dp" android:layout_height="wrap_content" > <LinearLayout android:layout_width="match_parent" android:orientation="vertical" android:padding="8dp" android:layout_height="wrap_content"> <TextView android:text="Contenu scrollable" android:textStyle="bold" android:textSize="16sp" android:textColor="#000000" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:text="Contrairement à une opinion répandue, le Lorem Ipsum n'est pas simplement du texte aléatoire. Il trouve ses racines dans une oeuvre de la littérature latine classique datant de 45 av. J.-C., le rendant vieux de 2000 ans. Un professeur du Hampden-Sydney College, en Virginie, s'est intéressé à un des mots latins les plus obscurs, consectetur, extrai" android:textSize="14sp" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout> </androidx.cardview.widget.CardView> <androidx.cardview.widget.CardView android:layout_width="match_parent" android:layout_margin="8dp" android:layout_height="wrap_content" > <LinearLayout android:layout_width="match_parent" android:orientation="vertical" android:padding="8dp" android:layout_height="wrap_content"> <TextView android:text="Contenu scrollable" android:textStyle="bold" android:textSize="16sp" android:textColor="#000000" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:text="Contrairement à une opinion répandue, le Lorem Ipsum n'est pas simplement du texte aléatoire. Il trouve ses racines dans une oeuvre de la littérature latine classique datant de 45 av. J.-C., le rendant vieux de 2000 ans. Un professeur du Hampden-Sydney College, en Virginie, s'est intéressé à un des mots latins les plus obscurs, consectetur, extrai" android:textSize="14sp" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout> </androidx.cardview.widget.CardView> <androidx.cardview.widget.CardView android:layout_width="match_parent" android:layout_margin="8dp" android:layout_height="wrap_content" > <LinearLayout android:layout_width="match_parent" android:orientation="vertical" android:padding="8dp" android:layout_height="wrap_content"> <TextView android:text="Contenu scrollable" android:textStyle="bold" android:textSize="16sp" android:textColor="#000000" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:text="Contrairement à une opinion répandue, le Lorem Ipsum n'est pas simplement du texte aléatoire. Il trouve ses racines dans une oeuvre de la littérature latine classique datant de 45 av. J.-C., le rendant vieux de 2000 ans. Un professeur du Hampden-Sydney College, en Virginie, s'est intéressé à un des mots latins les plus obscurs, consectetur, extrai" android:textSize="14sp" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout> </androidx.cardview.widget.CardView> <androidx.cardview.widget.CardView android:layout_width="match_parent" android:layout_margin="8dp" android:layout_height="wrap_content" > <LinearLayout android:layout_width="match_parent" android:orientation="vertical" android:padding="8dp" android:layout_height="wrap_content"> <TextView android:text="Contenu scrollable" android:textStyle="bold" android:textSize="16sp" android:textColor="#000000" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:text="Contrairement à une opinion répandue, le Lorem Ipsum n'est pas simplement du texte aléatoire. Il trouve ses racines dans une oeuvre de la littérature latine classique datant de 45 av. J.-C., le rendant vieux de 2000 ans. Un professeur du Hampden-Sydney College, en Virginie, s'est intéressé à un des mots latins les plus obscurs, consectetur, extrai" android:textSize="14sp" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout> </androidx.cardview.widget.CardView> <androidx.cardview.widget.CardView android:layout_width="match_parent" android:layout_margin="8dp" android:layout_height="wrap_content" > <LinearLayout android:layout_width="match_parent" android:orientation="vertical" android:padding="8dp" android:layout_height="wrap_content"> <TextView android:text="Contenu scrollable" android:textStyle="bold" android:textSize="16sp" android:textColor="#000000" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:text="Contrairement à une opinion répandue, le Lorem Ipsum n'est pas simplement du texte aléatoire. Il trouve ses racines dans une oeuvre de la littérature latine classique datant de 45 av. J.-C., le rendant vieux de 2000 ans. Un professeur du Hampden-Sydney College, en Virginie, s'est intéressé à un des mots latins les plus obscurs, consectetur, extrai" android:textSize="14sp" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout> </androidx.cardview.widget.CardView> <androidx.cardview.widget.CardView android:layout_width="match_parent" android:layout_margin="8dp" android:layout_height="wrap_content" > <LinearLayout android:layout_width="match_parent" android:orientation="vertical" android:padding="8dp" android:layout_height="wrap_content"> <TextView android:text="Contenu scrollable" android:textStyle="bold" android:textSize="16sp" android:textColor="#000000" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:text="Contrairement à une opinion répandue, le Lorem Ipsum n'est pas simplement du texte aléatoire. Il trouve ses racines dans une oeuvre de la littérature latine classique datant de 45 av. J.-C., le rendant vieux de 2000 ans. Un professeur du Hampden-Sydney College, en Virginie, s'est intéressé à un des mots latins les plus obscurs, consectetur, extrai" android:textSize="14sp" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout> </androidx.cardview.widget.CardView> <androidx.cardview.widget.CardView android:layout_width="match_parent" android:layout_margin="8dp" android:layout_height="wrap_content" > <LinearLayout android:layout_width="match_parent" android:orientation="vertical" android:padding="8dp" android:layout_height="wrap_content"> <TextView android:text="Contenu scrollable" android:textStyle="bold" android:textSize="16sp" android:textColor="#000000" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:text="Contrairement à une opinion répandue, le Lorem Ipsum n'est pas simplement du texte aléatoire. Il trouve ses racines dans une oeuvre de la littérature latine classique datant de 45 av. J.-C., le rendant vieux de 2000 ans. Un professeur du Hampden-Sydney College, en Virginie, s'est intéressé à un des mots latins les plus obscurs, consectetur, extrai" android:textSize="14sp" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout> </androidx.cardview.widget.CardView> </LinearLayout> </androidx.core.widget.NestedScrollView> <com.google.android.material.bottomappbar.BottomAppBar android:id="@+id/bar" android:layout_width="match_parent" android:layout_gravity="bottom" android:layout_height="wrap_content" android:backgroundTint="@color/colorPrimary" app:fabAlignmentMode="end" app:hideOnScroll="true" app:navigationIcon="@drawable/bottomappbarnavigation" /> <com.google.android.material.floatingactionbutton.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_anchor="@id/bar" android:src="@drawable/add" app:tint="@android:color/white" /> </androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.constraintlayout.widget.ConstraintLayout>
L’espace entre le creux du botttom app bar et le bouton flottant
L’attribut app:fabCradleMargin vous permet d’ajutser l’espace entre le bouton flottant et le creux du bottom app bar
Large espace
<?xml version="1.0" encoding="utf-8"?> <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <com.google.android.material.bottomappbar.BottomAppBar android:id="@+id/bar" android:layout_width="match_parent" android:layout_gravity="bottom" android:layout_height="wrap_content" android:backgroundTint="@color/colorPrimary" app:fabCradleMargin="20dp" app:navigationIcon="@drawable/bottomappbarnavigation" /> <com.google.android.material.floatingactionbutton.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_anchor="@id/bar" android:src="@drawable/add" app:tint="@android:color/white" /> </androidx.coordinatorlayout.widget.CoordinatorLayout>
Espace minime
<?xml version="1.0" encoding="utf-8"?> <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <com.google.android.material.bottomappbar.BottomAppBar android:id="@+id/bar" android:layout_width="match_parent" android:layout_gravity="bottom" android:layout_height="wrap_content" android:backgroundTint="@color/colorPrimary" app:fabCradleMargin="5dp" app:navigationIcon="@drawable/bottomappbarnavigation" /> <com.google.android.material.floatingactionbutton.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_anchor="@id/bar" android:src="@drawable/add" app:tint="@android:color/white" /> </androidx.coordinatorlayout.widget.CoordinatorLayout>
Créer un thème de forme sur le composant BottomAppBar
Si c’est votre premier tutoriel sur le material design 2, vous devez lire ce tutoriel sur comment créer des thermes de formes.
Nous allons créer une nouvelle forme(forme coupé au lieu de la forme arrondi) pour le bouton flottant et le creux du bottomAppBar grâce au classe CutCornerTreatment
et MaterialShapeDrawable.
Creer une forme au bouton flottant
Pour donner une forme coupé au bouton flottant procédez comme suite
Etape1:Crer un style ShapeOverlay comme suit.
<style name="ShapeOverlay.MyFloatingActionButton" parent=""> <item name="cornerFamily">cut</item> <item name="cornerSize">8dp</item> </style>
Etape 2:Appliquez ensuite le style au bouton flottant comme suit
<com.google.android.material.floatingactionbutton.FloatingActionButton .... app:shapeAppearance="@style/ShapeOverlay.MyFloatingActionButton" .... />
le fichier layout doit doit se présenter maintenant comme suit
<?xml version="1.0" encoding="utf-8"?> <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <com.google.android.material.bottomappbar.BottomAppBar android:id="@+id/bar" android:layout_width="match_parent" android:layout_gravity="bottom" android:layout_height="wrap_content" app:navigationIcon="@drawable/bottomappbarnavigation" /> <com.google.android.material.floatingactionbutton.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_anchor="@id/bar" android:src="@drawable/add" app:shapeAppearance="@style/ShapeOverlay.MyFloatingActionButton" app:tint="@android:color/white" /> </androidx.coordinatorlayout.widget.CoordinatorLayout>
Résultat:
Créer une forme au creux du bottomAppbar
Pour creer une forme au creux du bottom app bar, nous allons utiliser le BottomAppBarCutCornersTopEdge fourni par Google .
package com.example.bottomappbar import android.annotation.SuppressLint import com.google.android.material.bottomappbar.BottomAppBarTopEdgeTreatment import com.google.android.material.shape.ShapePath class BottomAppBarCutCornersTopEdge internal constructor( private val fabMargin: Float, roundedCornerRadius: Float, private val cradleVerticalOffset: Float ) : BottomAppBarTopEdgeTreatment(fabMargin, roundedCornerRadius, cradleVerticalOffset) { @SuppressLint("RestrictedApi") override fun getEdgePath( length: Float, center: Float, interpolation: Float, shapePath: ShapePath ) { val fabDiameter = fabDiameter if (fabDiameter == 0f) { shapePath.lineTo(length, 0f) return } val diamondSize = fabDiameter / 2f val middle = center + horizontalOffset val verticalOffsetRatio = cradleVerticalOffset / diamondSize if (verticalOffsetRatio >= 1.0f) { shapePath.lineTo(length, 0f) return } shapePath.lineTo(middle - (fabMargin + diamondSize - cradleVerticalOffset), 0f) shapePath.lineTo(middle, (diamondSize - cradleVerticalOffset + fabMargin) * interpolation) shapePath.lineTo(middle + (fabMargin + diamondSize - cradleVerticalOffset), 0f) shapePath.lineTo(length, 0f) } }
package com.example.bottomappbar.cut; import android.annotation.SuppressLint; import com.google.android.material.bottomappbar.BottomAppBarTopEdgeTreatment; import com.google.android.material.shape.ShapePath; public class BottomAppBarCutCornersTopEdge extends BottomAppBarTopEdgeTreatment { private final float fabMargin; private final float cradleVerticalOffset; BottomAppBarCutCornersTopEdge( float fabMargin, float roundedCornerRadius, float cradleVerticalOffset) { super(fabMargin, roundedCornerRadius, cradleVerticalOffset); this.fabMargin = fabMargin; this.cradleVerticalOffset = cradleVerticalOffset; } @Override @SuppressLint("RestrictedApi") public void getEdgePath(float length, float center, float interpolation, ShapePath shapePath) { float fabDiameter = getFabDiameter(); if (fabDiameter == 0) { shapePath.lineTo(length, 0); return; } float diamondSize = fabDiameter / 2f; float middle = center + getHorizontalOffset(); float verticalOffsetRatio = cradleVerticalOffset / diamondSize; if (verticalOffsetRatio >= 1.0f) { shapePath.lineTo(length, 0); return; } shapePath.lineTo(middle - (fabMargin + diamondSize - cradleVerticalOffset), 0); shapePath.lineTo(middle, (diamondSize - cradleVerticalOffset + fabMargin) * interpolation); shapePath.lineTo(middle + (fabMargin + diamondSize - cradleVerticalOffset), 0); shapePath.lineTo(length, 0); } }
Ensuite construisez le ShapeAppearanceMode et définissez le MaterialShappedrawable comme suit
package com.example.bottomappbar import androidx.appcompat.app.AppCompatActivity import android.os.Bundle import android.view.Menu import android.view.MenuItem import com.google.android.material.bottomappbar.BottomAppBar import com.google.android.material.button.MaterialButton import com.google.android.material.shape.MaterialShapeDrawable class MainActivity : AppCompatActivity() { private lateinit var mBottomAppBar: BottomAppBar override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) mBottomAppBar=findViewById(R.id.bar) val topEdget:BottomAppBarCutCornersTopEdge= BottomAppBarCutCornersTopEdge(mBottomAppBar.fabCradleMargin, mBottomAppBar.fabCradleRoundedCornerRadius, mBottomAppBar.cradleVerticalOffset) val materialShapeDrawable= mBottomAppBar.background as MaterialShapeDrawable materialShapeDrawable.shapeAppearanceModel= materialShapeDrawable.shapeAppearanceModel .toBuilder() .setTopEdge(topEdget) .build() } }
package com.example.bottomappbarjava; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import com.google.android.material.bottomappbar.BottomAppBar; import com.google.android.material.shape.MaterialShapeDrawable; public class MainActivity extends AppCompatActivity { private BottomAppBar mBottomAppBar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mBottomAppBar=findViewById(R.id.bar); BottomAppBarCutCornersTopEdge topEdget=new BottomAppBarCutCornersTopEdge(mBottomAppBar.getFabCradleMargin(), mBottomAppBar.getFabCradleRoundedCornerRadius(), mBottomAppBar.getCradleVerticalOffset()); MaterialShapeDrawable materialShapeDrawable =(MaterialShapeDrawable)mBottomAppBar.getBackground(); materialShapeDrawable.setShapeAppearanceModel(materialShapeDrawable.getShapeAppearanceModel() .toBuilder() .setTopEdge(topEdget) .build() ); } }
Voici le fichier layout
<?xml version="1.0" encoding="utf-8"?> <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <com.google.android.material.bottomappbar.BottomAppBar android:id="@+id/bar" android:layout_width="match_parent" android:layout_gravity="bottom" android:layout_height="wrap_content" app:fabCradleMargin="8dp" android:backgroundTint="@color/colorPrimary" app:navigationIcon="@drawable/bottomappbarnavigation" /> <com.google.android.material.floatingactionbutton.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_anchor="@id/bar" android:src="@drawable/add" app:shapeAppearance="@style/ShapeOverlay.MyFloatingActionButton" app:tint="@android:color/white" /> </androidx.coordinatorlayout.widget.CoordinatorLayout>
Résultat
Autres exemple:Ajoutez un le menu au bottomappbar avec l’attribut app:menu= »@menu/menu » et dans le menu ajoutez l’attribut app:showAsAction= »ifRoom » pour l’affichage des icons. L’image suivante montre ce que vous devez obtenir
Pour afficher les items de menu à gauche définissez la valeur de l’attribut app:fabAlignmentMode= »end » du bottom app bar à end. L’image suivant montre ce que vous devez obtenir
Autres ressources
https://material.io/components/app-bars-bottom/
https://developer.android.com/reference/com/google/android/material/bottomappbar/BottomAppBar
Conclusion
Nous sommes à la fin de ce tutoriel sur le bottom app bar.J’espère que ce tutoriel vous aidera à utiliser le composant bottom app bar.A bientôt pour un nouveau tutoriel.
Noe Joel Vigan, auteur de ce blog, est passionné par la programmation Android. Il a créé ce blog pour partager ses connaissances sur le développement d’application android. Il est Développeur Android Fullstack, ce qui lui permet de complètement mettre en place le Backend de ses applications sur Google Cloud à défaut d’utiliser FireBase.