Présentationℹ️
La barre d’application étendue (Collapsing Toolbar) est l’un des comportements de la barre d’application de conception de matériaux qui est largement utilisé pour masquer le contenu de la barre d’application lors du défilement vers le haut. Un cas d’utilisation simple est AppBar qui peut afficher une image de profil complète lorsque l’utilisateur fait défiler vers le bas et effectuer une transition lente pour afficher uniquement le nom d’utilisateur lorsque l’utilisateur fait défiler vers le haut.
Dans Flutter, nous pouvons obtenir le même comportement en utilisant le SliverAppBar widget. Comme le nom du widget l’indique, il ne peut être utilisé qu’à l’intérieur du CustomScrollView widget. Ce widget vous aide à créer divers effets de défilement tels que des listes, des grilles et des en-têtes extensibles en lui fournissant directement des rubans (SliverAppBar, SliverList, SliverGrid…).
Mais attendez… Qu’est-ce que c’est que le ruban? 🧐
Un ruban n’est qu’une partie d’une zone de défilement. C’est ça! Toutes les vues défilantes que vous utilisez, comme ListView et GridView, sont en fait implémentées à l’aide de Slivers. Vous pouvez en quelque sorte considérer Slivers comme une interface de niveau inférieur, offrant un contrôle plus précis sur la mise en œuvre des zones de défilement. Étant donné que les slivers peuvent construire paresseusement chaque élément au moment où il défile dans la vue, les slivers sont particulièrement utiles pour faire défiler efficacement un grand nombre d’enfants. –Éclats, démystifiés
Qu’allons-nous construire ? 👀
Nous allons créer le comportement personnalisé suivant :
Découvrons le widget SliverAppBar ! 🕵🏼
SliverAppBar(
pinned: _pinned,
snap: _snap,
floating: _floating,
expandedHeight: 160.0,
collapsedHeight: 80.0,
flexibleSpace: const FlexibleSpaceBar(
title: Text('SliverAppBar'),
background: FlutterLogo(),
),
),
Comme mentionné précédemment, ce widget est utilisé directement dans CustomScrollView et contient des propriétés utiles pour personnaliser son comportement.
Les propriétés les plus importantes sont :
Nous allons nous concentrer sur ces propriétés :
collapsedHeight
: une valeur double qui définit la hauteur de la barre d’application lorsqu’elle est réduite.expandedHeight
: une valeur double qui définit la hauteur de la barre d’application lorsqu’elle est développée.
flexibleSpace
: Ce widget est empilé derrière la barre d’outils et la barre d’onglets et il est généralement utilisé avec leFlexibleSpaceBar
widget. Le widget FlexibleSpaceBar contient des propriétés permettant de personnaliser l’espace lorsque la barre d’application est développée.
Nous allons nous concentrer sur deux propriétés :
-
Les
title
est un widget qui s’anime (agrandi/réduit) lors de la réduction/développement de la barre d’application. -
Les
background
est un widget qui s’estompe lorsque la barre d’application est réduite. -
Il existe d’autres propriétés qui contrôlent le comportement de la barre d’application réduite, qu’elle soit
pinned
,floating
,snap
, et plus. Pour en savoir plus, consultez la documentation officielle.
Construisons-le! 🏗
Dans un premier temps, nous utiliserons le flutter_hooks
package pour faciliter la gestion de l’état local et la gestion des ScrollControllers. Mais bien sûr, vous pouvez utiliser StatefulWidget
et setState
ou toute autre solution de gestion locale de l’état.
Commençons par ajouter le widget Stack pour ajouter l’image de fond du film et le widget CustomScrollView pour pouvoir utiliser la SliverAppBar.
class MovieProfilePage extends HookWidget {
const MovieProfilePage({super.key, required this.movieDetails});
final MovieDetails movieDetails;
@override
Widget build(BuildContext context) {
return Stack(
children: [
/// The background image
BlurredBackdropImage(movieDetails: movieDetails),
CustomScrollView(
slivers: [
],
),
],
);
}
}
Ajoutons maintenant la SliverAppBar à l’intérieur de CustomScrollView.
@override
Widget build(BuildContext context) {
const collapsedBarHeight = 60.0;
const expandedBarHeight = 400.0;
return Stack(
children: [
/// Blurred Background Image Widget
BlurredBackdropImage(movieDetails: movieDetails),
CustomScrollView(
slivers: [
SliverAppBar(
expandedHeight: expandedBarHeight,
collapsedHeight: collapsedBarHeight,
centerTitle: false,
pinned: true,
/// 1
title: CollapsedAppBarContent(movieDetails: movieDetails),
elevation: ,
/// 2
backgroundColor: Colors.transparent,
leading: const BackButton(
color: Colors.white,
),
/// 3
flexibleSpace: FlexibleSpaceBar(
background: ExpandedAppBarContent(
movieDetails: movieDetails,
),
),
),
/// 4
SliverToBoxAdapter(
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: MediaQuery.of(context).size.height,
),
child: Material(
elevation: 7,
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(15),
topRight: Radius.circular(15),
),
child: PageBodyWidget(movieDetails: movieDetails),
),
),
)
],
),
],
);
}
}
- Ajoute le
CollapsedAppBarContent
widget qui contient le hautRow
au champ titre. Le widget de titre restera toujours visible. - Modifie la barre d’applications
background
couleur àtransparent
pour montrer leBlurredBackdropImage
widget. - Ajoute
FlexibleSpaceBar
widget et attribue leExpandedAppBarContent
widget au champ d’arrière-plan. Lesbackground
le contenu du champ s’estompe lorsque la barre d’application s’effondre, et c’est exactement ce dont nous avons besoin ! - Ajoute
SliverToBoxAdapter
widget pour pouvoir ajouter le contenu du corps. Simplement, ce queSliverToBoxAdapter
est juste un pont entre les rubans et les widgets réguliers (c’est-à-dire les widgets basés sur des boîtes). Depuis leCustomScrollView
ne peut avoir que des objets slivers comme descendants directs.
La barre d’application ressemblerait maintenant à ceci :
Maintenant, si nous analysons la conception requise, nous découvrirons que nous avons le CollapsedAppBarContent
le widget chevauche le ExpandedAppBarContent
widget. De plus, lorsque la barre d’application est réduite, nous devons changer la couleur d’arrière-plan en noir au lieu de transparent.
Mais comment pourrions-nous parvenir à ce comportement ? 👀
Tout d’abord, nous devons savoir si l’AppBar est réduite ou développée ; sur cette base, nous pourrions afficher le contenu approprié de l’AppBar.
Pour ce faire, nous pourrions utiliser le NotificationListener
widget et écoutez le ScrollNotifications
pour détecter les changements dans le décalage de défilement. Sur cette base, nous pourrions savoir si la barre d’application est réduite ou développée.
@override
Widget build(BuildContext context) {
...
/// 1
final scrollController = useScrollController();
final isCollapsed = useState(false);
return NotificationListener<ScrollNotification>(
onNotification: (notification) {
/// 2
isCollapsed.value = scrollController.hasClients &&
scrollController.offset > (expandedBarHeight - collapsedBarHeight);
return false;
},
child: Stack(
children: [
BlurredBackdropImage(movieDetails: movieDetails),
CustomScrollView(
controller: scrollController,
slivers: [
SliverAppBar(
expandedHeight: expandedBarHeight,
collapsedHeight: collapsedBarHeight,
centerTitle: false,
pinned: true,
/// 3
title: AnimatedOpacity(
duration: const Duration(milliseconds: 200),
opacity: isCollapsed.value ? 1 : ,
child: CollapsedAppBarContent(movieDetails: movieDetails),
),
elevation: ,
/// 4
backgroundColor:
isCollapsed.value ? Colors.black : Colors.transparent,
leading: const BackButton(
color: Colors.white,
),
flexibleSpace: FlexibleSpaceBar(
background: ExpandedAppBarContent(
movieDetails: movieDetails,
),
),
),
...
],
),
],
),
);
}
- Utilise deux crochets,
useScrollController()
crochet pour créerScrollController
et unuseState()
crochet avec unfalse
valeur initiale pour créer leisCollapsed
objet d’état. LesisCollapsed
flag sera utilisé pour mettre à jour le contenu de la barre d’application en fonction de sa valeur. - Met à jour le
isCollapsed
valeur d’état en vérifiant quescrollController
l’objet est attaché à la vue de défilement. De plus, il vérifie si le décalage de défilement actuel est supérieur à la différence entre leexpandedBarHeight
etcollapsedBarHeight
. - Enveloppe le
CollapsedAppBarContent
widget avecAnimatedOpacity
widget pour masquer et afficher le contenu en fonction duisCollapsed
évaluer. - Change le
backgroundColor
basé surisCollapsed
évaluer.
La barre d’application ressemblerait maintenant à ceci :
Et hourra nous l’avons fait ! 🎉🎊
🌟
Nous pourrions également ajouter un retour haptique lorsque la barre d’application est réduite pour améliorer encore l’expérience utilisateur. Nous pouvons le faire en utilisant la classe HapticFeedback, qui permet d’accéder à l’interface de retour haptique sur l’appareil.
@override
Widget build(BuildContext context) {
...
final didAddFeedback = useState(false);
return NotificationListener<ScrollNotification>(
onNotification: (notification) {
...
/// When the app bar is collapsed and the feedback
/// hasn't been added previously will invoke
/// the `mediumImpact()` method, otherwise will
/// reset the didAddFeedback value.
///
if (isCollapsed.value && !didAddFeedback.value) {
HapticFeedback.mediumImpact();
didAddFeedback.value = true;
} else if (!isCollapsed.value) {
didAddFeedback.value = false;
}
return false;
},
child: Stack(
children: [
...
],
),
],
),
);
}
Nous avons ajouté une autre variable d’état de crochet nommée didAddFeedback basée sur elle appellera le HapticFeedback.mediumImpact()
méthode.
Concluez 🏁
Les rubans vous aident à personnaliser le comportement de défilement et à créer des effets de défilement complexes. La maîtrise des rubans vous permettra d’améliorer l’interface utilisateur et, plus important encore, l’expérience.
Merci d’avoir lu! ❤️
GitHub
Voir Github