Flutter: gonfler AppBar et SliverAppBar

Flutter utilise la célèbre AppBar pour créer une barre d'outils, mais lorsque nous avons besoin d'une barre d'outils dynamique qui affiche du contenu lors du glissement, nous utilisons l'excellent widget SliverAppBar .


Les deux widgets vous permettent de rendre l'application un peu plus belle, ce qui est sans aucun doute très simple dans Flutter.


J'ai vu beaucoup de questions sur StackOverflow et dans les groupes Facebook sur la façon de changer AppBar et SliverAppBar en termes de comportement ou de conception.


Regardons deux tâches.


Tâche 1


Nous voulons créer un AppBar qui n'est pas vissé en haut de l'écran, mais pas comme nous le faisons habituellement. Nous voulons ajouter un tiroir (menu latéral), à l'ouverture duquel l' AppBar répondra. C'est tout: notre propre AppBar   avec les dimensions dont nous avons besoin.


Le problème est que, comme nous le savons, AppBar a une taille par défaut et nous ne pouvons pas la modifier. Après avoir regardé le code source, nous voyons le paramètre appBar dans Scaffold , nous voyons qu'il accepte un widget du type PreferredSizeWidget , maintenant nous regardons le code source AppBar et découvrons que c'est seulement StatefulWidget qui implémente PreferredSizeWidget .



Le point est petit: créez simplement notre propre widget qui implémente PreferredSizeWidget .


Voilà ce que nous voulons



Comment feriez-vous pour que lorsque vous cliquez sur le bouton de menu de notre AppBar, un menu latéral s'ouvre.


Nous pouvons le faire de deux manières:


Utilisation de l'AppBar


C'est ainsi que AppBar peut contrôler l'ouverture de la barre latérale à l'intérieur de l' échafaudage .


class Sample1 extends StatelessWidget { @override Widget build(BuildContext context) { return SafeArea( child: Scaffold( drawer: Drawer(), appBar: MyCustomAppBar( height: 150, ), body: Center( child: FlutterLogo( size: MediaQuery.of(context).size.width / 2, ), ), ), ); } } class MyCustomAppBar extends StatelessWidget implements PreferredSizeWidget { final double height; const MyCustomAppBar({ Key key, @required this.height, }) : super(key: key); @override Widget build(BuildContext context) { return Column( children: [ Container( color: Colors.grey[300], child: Padding( padding: EdgeInsets.all(30), child: AppBar( title: Container( color: Colors.white, child: TextField( decoration: InputDecoration( hintText: "Search", contentPadding: EdgeInsets.all(10), ), ), ), actions: [ IconButton( icon: Icon(Icons.verified_user), onPressed: () => null, ), ], ) , ), ), ], ); } @override Size get preferredSize => Size.fromHeight(height); } 

Utiliser un widget personnalisé


Ici, nous avons plus de flexibilité et vous pouvez utiliser GlobalKey comme ScaffoldState ou InheritedWidget de Scaffold , accédant ainsi aux méthodes d'état pour ouvrir Drawer .


 import 'package:flutter/material.dart'; class Sample1 extends StatelessWidget { @override Widget build(BuildContext context) { return SafeArea( child: Scaffold( drawer: Drawer(), appBar: MyCustomAppBar( height: 150, ), body: Center( child: FlutterLogo( size: MediaQuery.of(context).size.width / 2, ), ), ), ); } } class MyCustomAppBar extends StatelessWidget implements PreferredSizeWidget { final double height; const MyCustomAppBar({ Key key, @required this.height, }) : super(key: key); @override Widget build(BuildContext context) { return Column( children: [ Container( color: Colors.grey[300], child: Padding( padding: EdgeInsets.all(30), child: Container( color: Colors.red, padding: EdgeInsets.all(5), child: Row(children: [ IconButton( icon: Icon(Icons.menu), onPressed: () { Scaffold.of(context).openDrawer(); }, ), Expanded( child: Container( color: Colors.white, child: TextField( decoration: InputDecoration( hintText: "Search", contentPadding: EdgeInsets.all(10), ), ), ), ), IconButton( icon: Icon(Icons.verified_user), onPressed: () => null, ), ]), ), ), ), ], ); } @override Size get preferredSize => Size.fromHeight(height); } 

Résultat



C'est simple, non? Examinons la deuxième tâche pour SliverAppBar .


Tâche 2


Comme nous le savons, SliverAppBar fonctionne comme suit:



Ce que nous voulons, c'est de mettre la carte intégrée dans notre SliverAppBar , comme le montre la figure suivante.



Attendez, mais le contenu à l'intérieur de SliverAppBar est rogné, il ne peut donc pas aller au-delà de quoi faire?



Sans panique, voyons le code source de SliverAppBar et, oh surprise, c'est StatefulWidget utilisant SliverPersistentHeader à l' intérieur, c'est tout le secret.


Nous allons créer notre propre SliverPersistentHeaderDelegate pour utiliser le SliverPersistentHeader .


 class Sample2 extends StatelessWidget { @override Widget build(BuildContext context) { return SafeArea( child: Material( child: CustomScrollView( slivers: [ SliverPersistentHeader( delegate: MySliverAppBar(expandedHeight: 200), pinned: true, ), SliverList( delegate: SliverChildBuilderDelegate( (_, index) => ListTile( title: Text("Index: $index"), ), ), ) ], ), ), ); } } class MySliverAppBar extends SliverPersistentHeaderDelegate { final double expandedHeight; MySliverAppBar({@required this.expandedHeight}); @override Widget build( BuildContext context, double shrinkOffset, bool overlapsContent) { return Stack( fit: StackFit.expand, overflow: Overflow.visible, children: [ Image.network( "https://images.pexels.com/photos/396547/pexels-photo-396547.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500", fit: BoxFit.cover, ), Center( child: Opacity( opacity: shrinkOffset / expandedHeight, child: Text( "MySliverAppBar", style: TextStyle( color: Colors.white, fontWeight: FontWeight.w700, fontSize: 23, ), ), ), ), Positioned( top: expandedHeight / 2 - shrinkOffset, left: MediaQuery.of(context).size.width / 4, child: Opacity( opacity: (1 - shrinkOffset / expandedHeight), child: Card( elevation: 10, child: SizedBox( height: expandedHeight, width: MediaQuery.of(context).size.width / 2, child: FlutterLogo(), ), ), ), ), ], ); } @override double get maxExtent => expandedHeight; @override double get minExtent => kToolbarHeight; @override bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) => true; } 

Résultat



Terminé, les deux tâches sont résolues.


Des exemples sont dans ce référentiel .


Conclusion


Souvent, nous désespérons lorsque nous ne trouvons aucune propriété du widget, mais il vous suffit de regarder son code source pour comprendre comment il est implémenté dans Flutter, découvrant ainsi comment nous pouvons implémenter nos propres widgets.

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


All Articles