Flutter: aumentando o AppBar e o SliverAppBar

O Flutter usa a conhecida AppBar para criar uma barra de ferramentas, mas quando precisamos de uma barra de ferramentas dinâmica que exibe conteúdo ao deslizar, usamos o excelente widget SliverAppBar .


Ambos os widgets permitem tornar o aplicativo um pouco mais bonito, o que no Flutter, sem dúvida, é muito simples.


Vi muitas perguntas no StackOverflow e nos grupos do Facebook sobre como você pode alterar o AppBar e o SliverAppBar em termos de comportamento ou design.


Vejamos duas tarefas.


Tarefa 1


Queremos criar uma AppBar que não esteja aparafusada na parte superior da tela, mas não como costumamos fazer. Queremos adicionar uma gaveta (menu lateral), cuja abertura a AppBar responderá. É isso: nossa própria AppBar   com as dimensões que precisamos.


O problema é que, como sabemos, o AppBar tem um tamanho padrão e não podemos alterá-lo. Depois de analisar o código-fonte, vemos o parâmetro appBar no Scaffold , vemos que ele aceita um widget como PreferredSizeWidget , agora analisamos o código-fonte AppBar e descobrimos que este é apenas o StatefulWidget que implementa o PreferredSizeWidget .



O ponto é pequeno: basta criar nosso próprio widget que implementa o PreferredSizeWidget .


É isso que queremos



Como você faria para que, ao clicar no botão de menu da nossa AppBar, um menu lateral seja aberto.


Podemos fazer isso de duas maneiras:


Usando o `AppBar`


É assim que o AppBar pode controlar a abertura da barra lateral dentro do andaime .


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); } 

Usando um widget customizado


Aqui temos mais flexibilidade e você pode usar GlobalKey como ScaffoldState ou InheritedWidget do Scaffold , obtendo acesso aos métodos de estado para abrir o 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); } 

Resultado



Simples, certo? Vejamos a segunda tarefa para SliverAppBar .


Tarefa 2


Como sabemos, o SliverAppBar funciona da seguinte maneira:



O que queremos é colocar o cartão em nosso SliverAppBar , como mostra a figura a seguir.



Espere, mas o conteúdo dentro do SliverAppBar é cortado, portanto não pode ir além do que fazer?



Sem pânico, vamos ver o código fonte do SliverAppBar e, oh surpresa, este é o StatefulWidget usando o SliverPersistentHeader por dentro, esse é o segredo.


Criaremos nosso próprio SliverPersistentHeaderDelegate para usar o 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; } 

Resultado



Concluído, as duas tarefas estão resolvidas.


Exemplos estão neste repositório .


Conclusão


Freqüentemente nos desesperamos quando não encontramos nenhuma propriedade do widget, mas precisamos apenas olhar seu código-fonte para entender como ele é implementado no Flutter, abrindo para nós as opções para implementar nossos próprios widgets.

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


All Articles