Como usar Snackbar em Flutter?!
Tags: android, flutter, snackbar, mobile
Published: 2020-09-28 19:05:14

## Por que resolvi escrever este post 

Eai galera DEV, tudo certo? 

Vim aqui publicar mais um  post pra poder estar contribuindo para nossa comunidade dev e adquirindo conhecimento. 

Nessa semana eu tive que fazer um Snackbar para o meu app de TCC e eu não sabia como poderia ser feito. Na verdade eu não sabia nem o nome do widget, então eu fui pesquisando por “barrinha de alerta mobile” até que encontrei o nome que era utilizado. Depois disso eu fui até a documentação do framework e aprendi como ele funciona, também pesquisei no Design Material suas boas práticas de uso. Vale muito a pena dedicar seu tempo para ler, os links estão no final do post.

Não achei muita coisa em português e para mim não foi algo tão simples de utilizar, mas depois que eu percorri por vários posts, vídeos e documentação eu consegui entender. Então resolvi juntar tudo em um lugar o que eu aprendi.

Separei alguns pontos que considero mais fundamentais e importantes na hora de programar. 

## Entenda seu uso 

O Snackbar é utilizado para informar ao usuário um processo que foi executado ou irá ser executado. Ele tem que aparecer temporariamente na parte inferior da tela para que não atrapalhe o uso do aplicativo. 

Ele tem basicamente três princípios: 

1. Informativo: Fornece atualização do processo
2. Temporário: Ele aparece temporariamente e desaparece por conta própria
3. Contextual: É colocado na área mais adequada da interface.

## Anatomia 

![Anatomia de um snackbar](https://dev-to-uploads.s3.amazonaws.com/i/m5milnp2ocb1zqqnt4vy.png)

1. Etiqueta de texto
2. Recipiente
3. Ação (opcional)

## Comportamento

O Snackbar aparece por tempo determinado e depois é fechado sozinho, mas cuidado ao realizar muitas chamadas. Ele tem que aparecer um de cada vez, não deixa fazer uma pilha de Snackbar.

![Exemplo de snackbar empilhado](https://dev-to-uploads.s3.amazonaws.com/i/e9rcnvtqm6i5kyiyt1a0.png)

Não altere o comportamento dos elementos da tela para mostrar seu Snackbar, isso pode ser uma péssima experiência para o usuário. 

![Exemplo snackbar](https://dev-to-uploads.s3.amazonaws.com/i/nssceq531vodihfwvzlj.png)


## Colocação

O Snackbar deve ficar na na parte inferior da interface do aplicativo, mas tem que ter cuidado com o lugar. Ele não pode cobrir a barra de navegação.

![Exemplo snackbar cobrindo barra de navegação](https://dev-to-uploads.s3.amazonaws.com/i/k4harc65aws4gc5xd2hj.png)

Snackbar que abrange toda a largura eu diria que é o mais importante a ter cuidado para o uso, pois até mesmo na documentação do Flutter eles mostram a explicação do snackbar desta maneira.

Então  isso quer dizer que não podemos usar esse modo que abrange toda a largura da interface? 

Não! 

Pode ser utilizado, mas temos que tomar muito cuidado ao utilizá-lo. Como o exemplo anterior é bem retratado, ele pode cobrir barra de navegação.

![Exemplo de snackbar com largura total](https://dev-to-uploads.s3.amazonaws.com/i/orufp651ogfvtnuspmig.png)


Uma boa prática de uso de um snackbar.

![Exemplo de uma boa pratica do uso de um snackbar](https://dev-to-uploads.s3.amazonaws.com/i/6hseo8f3zlvd418behae.png)

## Mão na massa!

Para utilizar o snackbar é bem simples, basta chamar a função showSnackBar passando o snackbar por parâmetro.

Desta maneira:

```
class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Code Sample for Scaffold.of.',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        body: MyScaffoldBody(),
        appBar: AppBar(title: Text('Scaffold.of Example')),
      ),
      color: Colors.white,
    );
  }
}

class MyScaffoldBody extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: RaisedButton(
        child: Text('SHOW A SNACKBAR'),
        onPressed: () {
          Scaffold.of(context).showSnackBar(
            SnackBar(
              content: Text('Have a snack!'),
            ),
          );
        },
      ),
    );
  }
}
```

Mas como na vida nem tudo são rosas, você tem que ficar ligado que o ShowSnackbar é filho do Scaffold. E se você não usar um BuildContext diferente do pai do Scaffold pode dar ruim. 



![snackbar é filho do scaffold](https://dev-to-uploads.s3.amazonaws.com/i/5a8p2ymwxiczwdy313nz.png)



## Snackbar Global

A maneira anterior de chamar o snackbar é para uma tela atual somente, isso quer dizer que se você fizer uma mudança de página não irá aparece-lo. Mas tem uma maneira de deixar ele global.

#### Passo 1

Colocar um Scaffold dentro do builder do seu MaterialApp.

```
class MyApp extends StatelessWidget {
 // This widget is the root of your application.
 @override
 Widget build(BuildContext context) {
   return MaterialApp(
     title: 'Flutter Demo',
     theme: ThemeData(
       primarySwatch: Colors.blue,
       visualDensity: VisualDensity.adaptivePlatformDensity,
     ),
     builder: (context, child) {
       return Scaffold(
         key: GlobalScaffold.instance.scafoldKey,
         body: child,
       );
     },
     initialRoute: '/',
     routes: {
       '/': (_) => MyHomePage(title: 'Flutter Demo snackbar global'),
       '/second': (_) => SecondPage(title: 'Segunda página')
     },
   );
 }
}

```

#### Passo 2

Criar uma classe para fazer criar um Scaffold global.

```
class GlobalScaffold {
 static final GlobalScaffold instance = GlobalScaffold();

 final scafoldKey = GlobalKey<ScaffoldState>();

 void showSnackbar(SnackBar snackBar) {
   scafoldKey.currentState.showSnackBar(snackBar);
 }
}

```

#### Passo 3

Criar a função responsável para invocar o snackbar.

```
void onClickSnackbarGlobal() {
 final snackbar = SnackBar(
     behavior: SnackBarBehavior.floating,
     elevation: 150.0,
     content: Text("Eu sou um Snackbar Global!"));
 GlobalScaffold.instance.showSnackbar(snackbar);
}
```

#### Passa 4

Por último é somente chamar a função no seu widget

```
@override
Widget build(BuildContext context) {
 return Scaffold(
   appBar: AppBar(
     title: Text(widget.title),
   ),
   body: ListView(
     padding: EdgeInsets.all(20),
     children: [
       RaisedButton(
           child: Text('Ir para segunda página'),
           onPressed: () {
             Navigator.pushNamed(context, "/second");
           }),
       RaisedButton(
         child: Text('Mostrar Sanackbar Global'),
         onPressed: () => onClickSnackbarGlobal(),
       )
     ],
   ),
 );
}
```

Resultado:

![Telas](https://dev-to-uploads.s3.amazonaws.com/i/3l1kyhd2buhtoyiztklo.png)


## Conclusão

Espero que tenha ajudado, qualquer dúvida ou sugestão pode comentar que será de grande ajuda. Valeu!



Links úteis:
[Material Design](https://material.io/components/snackbars#specs)
[Documentação do Flutter](https://api.flutter.dev/flutter/material/Scaffold/of.html)
[Video do canal Flutter explicando o snackbar](https://www.youtube.com/watch?v=zpO6n_oZWw0&ab_channel=Flutter)
[Aula do canal Flutterando]
(https://www.youtube.com/watch?v=JdYP9YoO6gU&ab_channel=Flutterando)
[Post no stackoverflow](https://stackoverflow.com/questions/51304568/scaffold-of-called-with-a-context-that-does-not-contain-a-scaffold)