6
respostas

Como usar um timer pra trocar de widget

Eu estou trabalhando num projeto, e nele eu criei um componente de mensagem, o que eu gostaria é que antes de aparecer o Text com a mensagem, tivesse uma pequena animação de carregamento. Pesquisando, eu descobri uma dependência que eu posso baixar chamada progress_indicators que tem a animação que eu quero, mas eu ainda não sei como fazer para se o meu _loader for true, aparecer a animação e depois de um certo timer, trocar pro Text.

import 'package:flutter/material.dart';
import 'package:progress_indicators/progress_indicators.dart';

// Classe genérica pra criar as mensagens
abstract class Message extends StatefulWidget {
  final MainAxisAlignment _alignment;
  final Color _backgroundColor;
  final Color _textColor;
  final String _msg;
  final bool _loader;

  Message(this._msg, this._alignment, this._backgroundColor, this._textColor,
      this._loader);

  @override
  _MessageState createState() => _MessageState();
}

class _MessageState extends State<Message> {
  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: widget._alignment,
      children: [
        Card(
          color: widget._backgroundColor,
          child: Padding(
            padding: const EdgeInsets.all(8.0),
            child: Text(
              widget._msg,
              style: TextStyle(
                fontSize: 20,
                color: widget._textColor,
              ),
            ),
          ),
        ),
      ],
    );
  }
}

class UserMessage extends Message {
  UserMessage(String msg)
      : super(msg, MainAxisAlignment.end, Colors.white, Colors.black, true);
}
6 respostas

Você pode tentar aplicar um debounce junto com um StreamBuilder pra que ele note a mudança de state e recarregue a tela. Talvez isso de um trigger de um reset de posição. Teria que testar pra analisar.

poderia dar um exemplo de código?

import 'dart:async';

import 'package:flutter/material.dart';
// Comentei aqui porque não queria importar algo no pubspec dai usei um progress indicator do material mesmo, 
// deve funcionar com qualquer widget que você colocar
//import 'package:progress_indicators/progress_indicators.dart';  

// Classe genérica pra criar as mensagens
abstract class Message extends StatefulWidget {
  final MainAxisAlignment _alignment;
  final Color _backgroundColor;
  final Color _textColor;
  final String _msg;
  bool _loader;

  Message(this._msg, this._alignment, this._backgroundColor, this._textColor,
      this._loader);

  @override
  _MessageState createState() => _MessageState();
}

class _MessageState extends State<Message> {
  _changeText() {
    Timer _debounce;
    if (_debounce?.isActive ?? false) _debounce.cancel();
    _debounce = Timer(Duration(seconds: 3), () {
      setState(() {
        widget._loader = !widget._loader;
      });
    });
  }

  @override
  void initState() {
    _changeText();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: widget._alignment,
      children: [
        Card(
          color: widget._backgroundColor,
          child: Padding(
            padding: const EdgeInsets.all(8.0),
        //TODO Aqui você altera pra como você quer que ele apareça visualmente, 
        //TODO só fiz assim pra parar de quebrar no projeto que eu tava trabalhando
            child: widget._loader
                ? Container(width: 50.0,child: LinearProgressIndicator())     
                : Text(
                    widget._msg,
                    style: TextStyle(
                      fontSize: 20,
                      color: widget._textColor,
                    ),
                  ),
          ),
        ),
      ],
    );
  }
}

class UserMessage extends Message {
  UserMessage(String msg)
      : super(msg, MainAxisAlignment.end, Colors.white, Colors.black, true);
}

É um exemplo bem rápido, da pra refatorar e deixar mais enxuto, vai dai você vê como quer aplicar no seu projeto. E também tem muitas outras manerias de resolver esse problema haha, essa foi a que eu pensei que seria mais rápido :P

Gustavo, valeu, funcionou, mas tive um pequeno problema, quando eu dou um scroll na ListView das mensagens, talvez por causa do initState ele chama novamente o _changeText() e as mensagens que já tinham sido enviadas voltam pro 'estado de carregamento'. Eu sei que tu já me ajudou bastante, mas se puder ajudar mais um pouquinho eu agradeço : )

Não sei se já resolveu, mas tenta fazer essa lista com um ListView.builder ao invés de apenas ListView

Bom, eu já uso o ListView.builder, mas valeu.