Solucionado (ver solução)
Solucionado
(ver solução)
5
respostas

SnackBar não funciona

Estava funcionando antes de alterar o tipo de widget. gostei muito do efeito, e queria manter ele. Meu arquivo lista.dart:

import 'package:bytebank/models/transferencia.dart';
import 'package:bytebank/screens/transferencia/formulario.dart';
import 'package:flutter/material.dart';

const _tituloAppBar = 'Transferências';

class ListaTransferencias extends StatefulWidget {
  final List<Transferencia> _transferencias = List();

  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return ListaTransferenciasState();
  }
}

class ListaTransferenciasState extends State<ListaTransferencias> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(_tituloAppBar),
      ),
      body: ListView.builder(
        itemCount: widget._transferencias.length,
        itemBuilder: (
          context,
          indice,
        ) {
          final transferencia = widget._transferencias[indice];
          return ItemTransferencia(transferencia);
        },
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: () {
              Navigator.push(context, MaterialPageRoute(builder: (context) {
            return FormularioTransferencia();
          })).then((transferenciaRecebida) {
            //Future.delayed(Duration(seconds: 1), () {
              //debugPrint('chegou no then do future');
              //debugPrint('$transferenciaRecebida');
            //});
            _atualiza(transferenciaRecebida);
            Scaffold.of(context).showSnackBar(
              SnackBar(
                content: Text('$transferenciaRecebida'),
              ),
            );
          });
        },
      ),
    );
  }

  void _atualiza(Transferencia transferenciaRecebida) {
     if (transferenciaRecebida != null) {
      setState(() {
        widget._transferencias.add(transferenciaRecebida);
      });
    }
  }
}

class ItemTransferencia extends StatelessWidget {
  final Transferencia _transferencia;

  ItemTransferencia(this._transferencia);

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Card(
        child: ListTile(
      leading: Icon(Icons.monetization_on),
      title: Text(_transferencia.valor.toString()),
      subtitle: Text(_transferencia.numeroConta.toString()),
    ));
  }
}
5 respostas

Até agora não entendi muito essa coisa de build e context.

Oi Diego, tudo bem?

Você consegue compartilhar o seu projeto via GitHub para que eu consiga executar e testar? Dessa maneira eu consigo verificar o erro que acontece e quando acontece, então, fica mais fácil de te passar com mais precisão o motivo do problema.

Caso não tenha ideia de como pode compartilhar projetos no GitHub, dê uma olhada neste Alura+.

Então mestre, estou falando do projeto bytebank do curso Fundamentos de Flutter: Crie o seu primeiro App". Apesar de está tendo o mesmo problema no bytebank2 do curso Persistência com Flutter: "Crie um app com armazenamento interno". Eu consegui resolver assim:

lista.dart

import 'package:bytebank/models/transferencia.dart';
import 'package:bytebank/screens/transferencia/formulario.dart';
import 'package:flutter/material.dart';

const _tituloAppBar = 'Transferências';

class ListaTransferencias extends StatefulWidget {

  final List<Transferencia> _transferencias = List();


  @override
  State<StatefulWidget> createState() {
    return ListaTransferenciasState();
  }
}

class ListaTransferenciasState extends State<ListaTransferencias> {
  final _scaffoldKey = GlobalKey<ScaffoldState>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: _scaffoldKey,
      appBar: AppBar(
        title: Text(_tituloAppBar),
      ),
      body: ListView.builder(
        itemCount: widget._transferencias.length,
        itemBuilder: (
          context,
          indice,
        ) {
          final transferencia = widget._transferencias[indice];
          return ItemTransferencia(transferencia);
        },
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: () {
          Navigator.push(context, MaterialPageRoute(builder: (context) {
            return FormularioTransferencia();
          })).then((transferenciaRecebida) {
            //Future.delayed(Duration(seconds: 1), () {
            //debugPrint('chegou no then do future');
            //debugPrint('$transferenciaRecebida');
            //});
            _atualiza(transferenciaRecebida);
            _displaySnackBar(context);
          });
        },
      ),
    );
  }

  _displaySnackBar(BuildContext context) {
    final snackBar = SnackBar(content: Text('Are you talkin\' to me?'));
    _scaffoldKey.currentState.showSnackBar(snackBar);  
  }

  void _atualiza(Transferencia transferenciaRecebida) {
    if (transferenciaRecebida != null) {
      setState(() {
        widget._transferencias.add(transferenciaRecebida);
      });
    }
  }
}

class ItemTransferencia extends StatelessWidget {
  final Transferencia _transferencia;

  ItemTransferencia(this._transferencia);

  @override
  Widget build(BuildContext context) {
    return Card(
        child: ListTile(
      leading: Icon(Icons.monetization_on),
      title: Text(_transferencia.valor.toString()),
      subtitle: Text(_transferencia.numeroConta.toString()),
    ));
  }
}

Criei uma GlobalKey. Não gostei muito da solução. Pensei em envolver todo o widget ListView.builder() em um Builder na propriedade builder.

body: Builder(
        builder: (context) => 
           ListView.builder()
            .....
    ....... // resto do código
    .....
    ....
            ),
        ),
    ),

Mas dessa forma, eu não tenho como adicionar a propriedade "floatingActionButton:" dentro de Builder ou de sua propriedade builder. Teria que criar um RaisedButton. Já entendi que se eu chamar um Scaffold.of () abaixo de um Scaffold, ele acaba buscando um ancestral acima do Scaffold. Qual solução sem ter que usar uma GlobalKey, eu poderia chamar meu SnackBar ali mesmo dentro floatingActionButton: FloatingActionButton() ?

solução!

Entendi, você pode usar o Builder direto no Widget que precisa desse contexto diferente, no caso envolveria apenas o FloatingActionButton:

      floatingActionButton: Builder(
        builder: (context) => FloatingActionButton(
          child: Icon(Icons.add),
          onPressed: () {
            Navigator.push(context, MaterialPageRoute(builder: (context) {
              return FormularioTransferencia();
            })).then((transferenciaRecebida) {
              _atualiza(transferenciaRecebida);
              Scaffold.of(context).showSnackBar(
                  SnackBar(content: Text('Are you talkin\' to me?')));
            });
          },
        ),
      ),

Entendi, me sentindo o "jumentinho" da galera aqui. kkkkkkkk Não sabia que na propriedade "floatingActionButton:" aceitava outro widget. Obrigado!

Esperando mais cursos de Flutter....

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software