Como trabalhar com indicador de progresso em vibração?


86

Sou novato em flutter e queria saber qual a melhor forma de adicionar CircularProgressIndicatorno meu layout. Por exemplo, minha visualização de login. Esta visão tem nome de usuário, senha e botão de login. Eu queria criar um layout de sobreposição (com Opacity) que, ao carregar, mostrasse o indicador de progresso como eu uso no NativeScript, mas estou um pouco confuso sobre como fazer e também se é a melhor maneira. No NativeScript, por exemplo, adiciono IndicatorActivity no layout principal e defini ocupado como verdadeiro ou falso, de forma que ele sobreponha todos os componentes de exibição ao carregar.

Editar:

Consegui chegar a este resultado:

    void main() {
      runApp(new MyApp());
    }

    class MyApp extends StatelessWidget {
      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        return new MaterialApp(
          title: 'Flutter Demo',
          theme: new ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: new MyHomePage(title: 'Flutter Demo Home Page'),
        );
      }
    }

    class MyHomePage extends StatefulWidget {
      MyHomePage({Key key, this.title}) : super(key: key);

      final String title;

      @override
      _MyHomePageState createState() => new _MyHomePageState();
    }

    class _MyHomePageState extends State<MyHomePage> {
      bool _loading = false;

      void _onLoading() {
        setState(() {
          _loading = true;
          new Future.delayed(new Duration(seconds: 3), _login);
        });
      }


      Future _login() async{
        setState((){
          _loading = false;
        });
      }

      @override
      Widget build(BuildContext context) {


          var body = new Column(
              children: <Widget>[
                new Container(
                  height: 40.0,
                  padding: const EdgeInsets.all(10.0),
                  margin: const EdgeInsets.fromLTRB(15.0, 150.0, 15.0, 0.0),
                  decoration: new BoxDecoration(
                    color: Colors.white,
                  ),
                  child: new TextField(
                    decoration: new InputDecoration.collapsed(hintText: "username"),
                  ),
                ),
                new Container(
                  height: 40.0,
                  padding: const EdgeInsets.all(10.0),
                  margin: const EdgeInsets.all(15.0),
                  decoration: new BoxDecoration(
                    color: Colors.white,
                  ),
                  child: new TextField(
                    decoration: new InputDecoration.collapsed(hintText: "password"),
                  ),
                ),
              ],
            );


          var bodyProgress = new Container(
            child: new Stack(
              children: <Widget>[
                body,
                new Container(
                  alignment: AlignmentDirectional.center,
                  decoration: new BoxDecoration(
                    color: Colors.white70,
                  ),
                  child: new Container(
                    decoration: new BoxDecoration(
                      color: Colors.blue[200],
                      borderRadius: new BorderRadius.circular(10.0)
                    ),
                    width: 300.0,
                    height: 200.0,
                    alignment: AlignmentDirectional.center,
                    child: new Column(
                      crossAxisAlignment: CrossAxisAlignment.center,
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: <Widget>[
                        new Center(
                          child: new SizedBox(
                            height: 50.0,
                            width: 50.0,
                            child: new CircularProgressIndicator(
                              value: null,
                              strokeWidth: 7.0,
                            ),
                          ),
                        ),
                        new Container(
                          margin: const EdgeInsets.only(top: 25.0),
                          child: new Center(
                            child: new Text(
                              "loading.. wait...",
                              style: new TextStyle(
                                color: Colors.white
                              ),
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
              ],
            ),
          );

          return new Scaffold(
            appBar: new AppBar(
              title: new Text(widget.title),
            ),
            body: new Container(
              decoration: new BoxDecoration(
                color: Colors.blue[200]
              ),
              child: _loading ? bodyProgress : body
            ),
            floatingActionButton: new FloatingActionButton(
              onPressed: _onLoading,
              tooltip: 'Loading',
              child: new Icon(Icons.check),
            ),
          );
      }
    }

resultado da tela do aplicativo

Ainda estou me adaptando à ideia de estados. Esse código está dentro do esperado ao trabalhar com flutter?

Obrigado!


1
como desativar a compressão de volta enquanto a caixa de diálogo é exibida?
Aprendiz rápido

Respostas:


77

Na vibração, existem algumas maneiras de lidar com ações assíncronas.

Uma maneira preguiçosa de fazer isso pode ser usando um modal. O que irá bloquear a entrada do usuário, evitando ações indesejadas. Isso exigiria muito poucas alterações em seu código. Apenas modificando seu _onLoadingpara algo assim:

void _onLoading() {
  showDialog(
    context: context,
    barrierDismissible: false,
    builder: (BuildContext context) {
      return Dialog(
        child: new Row(
          mainAxisSize: MainAxisSize.min,
          children: [
            new CircularProgressIndicator(),
            new Text("Loading"),
          ],
        ),
      );
    },
  );
  new Future.delayed(new Duration(seconds: 3), () {
    Navigator.pop(context); //pop dialog
    _login();
  });
}

A maneira mais ideal de fazer isso é usando FutureBuilderum widget com estado. Que é o que você começou. O truque é que, em vez de ter um boolean loading = falseem seu estado, você pode usar diretamente umFuture<MyUser> user

Em seguida, passe-o como argumento para FutureBuilder, que fornecerá algumas informações como "hasData" ou a instância de MyUserquando concluído.

Isso levaria a algo assim:

@immutable
class MyUser {
  final String name;

  MyUser(this.name);
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      home: new MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  Future<MyUser> user;

  void _logIn() {
    setState(() {
      user = new Future.delayed(const Duration(seconds: 3), () {
        return new MyUser("Toto");
      });
    });
  }

  Widget _buildForm(AsyncSnapshot<MyUser> snapshot) {
    var floatBtn = new RaisedButton(
      onPressed:
          snapshot.connectionState == ConnectionState.none ? _logIn : null,
      child: new Icon(Icons.save),
    );
    var action =
        snapshot.connectionState != ConnectionState.none && !snapshot.hasData
            ? new Stack(
                alignment: FractionalOffset.center,
                children: <Widget>[
                  floatBtn,
                  new CircularProgressIndicator(
                    backgroundColor: Colors.red,
                  ),
                ],
              )
            : floatBtn;

    return new ListView(
      padding: const EdgeInsets.all(15.0),
        children: <Widget>[
          new ListTile(
            title: new TextField(),
          ),
          new ListTile(
            title: new TextField(obscureText: true),
          ),
          new Center(child: action)
        ],
    );
  }

  @override
  Widget build(BuildContext context) {
    return new FutureBuilder(
      future: user,
      builder: (context, AsyncSnapshot<MyUser> snapshot) {
        if (snapshot.hasData) {
          return new Scaffold(
            appBar: new AppBar(
              title: new Text("Hello ${snapshot.data.name}"),
            ),
          );
        } else {
          return new Scaffold(
            appBar: new AppBar(
              title: new Text("Connection"),
            ),
            body: _buildForm(snapshot),
          );
        }
      },
    );
  }
}

1
Legal, os dois exemplos serão úteis no login e em outras situações. O progresso do manipulador com diálogo parece melhor do que minha versão e FutureBuilder É mais elegante do que minha solução também. obrigado pela ajuda!
Ricardo Bocchi

uma questão fora do tópico .. para cada TextField preciso de um TextEditingController exclusivo?
Ricardo Bocchi

@RicardoBocchi Sim
aziza

Eu não acho que o Dialog funcionará com o exemplo real, é confuso como o usuário será redirecionado após o retorno de _login (). Seu segundo exemplo parece muito mais conveniente. Bem cozido.
aziza

1
Bem, o Dialog é funcional e requer muito poucas modificações em seu código original. Ele poderia, por exemplo, seguir o fechamento do diálogo com um Navigator.pushNamed("/home").
Rémi Rousselet

38

Para mim, uma maneira legal de fazer isso é mostrar um SnackBarna parte inferior enquanto o processo de login é realizado. Este é um exemplo do que quero dizer:

insira a descrição da imagem aqui

Aqui está como configurar o SnackBar.

Defina uma chave global para o seu Scaffold

final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();

Adicione ao seu Scaffold keyatributo

return new Scaffold(
      key: _scaffoldKey,
.......

Retorno do botão de login onPressed:

onPressed: () {
                  _scaffoldKey.currentState.showSnackBar(
                      new SnackBar(duration: new Duration(seconds: 4), content:
                      new Row(
                        children: <Widget>[
                          new CircularProgressIndicator(),
                          new Text("  Signing-In...")
                        ],
                      ),
                      ));
                  _handleSignIn()
                      .whenComplete(() =>
                      Navigator.of(context).pushNamed("/Home")
                  );
                }

Realmente depende de como você deseja construir seu layout, e não tenho certeza do que você tem em mente.

Editar

Você provavelmente quer assim, eu usei um Stack para alcançar este resultado e apenas mostrar ou ocultar meu indicador com base onPressed

insira a descrição da imagem aqui

class TestSignInView extends StatefulWidget {
  @override
  _TestSignInViewState createState() => new _TestSignInViewState();
}


class _TestSignInViewState extends State<TestSignInView> {
  bool _load = false;
  @override
  Widget build(BuildContext context) {
    Widget loadingIndicator =_load? new Container(
      color: Colors.grey[300],
      width: 70.0,
      height: 70.0,
      child: new Padding(padding: const EdgeInsets.all(5.0),child: new Center(child: new CircularProgressIndicator())),
    ):new Container();
    return new Scaffold(
      backgroundColor: Colors.white,
      body:  new Stack(children: <Widget>[new Padding(
        padding: const EdgeInsets.symmetric(vertical: 50.0, horizontal: 20.0),
        child: new ListView(

          children: <Widget>[
            new Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center
              ,children: <Widget>[
            new TextField(),
            new TextField(),

            new FlatButton(color:Colors.blue,child: new Text('Sign In'),
                onPressed: () {
              setState((){
                _load=true;
              });

                  //Navigator.of(context).push(new MaterialPageRoute(builder: (_)=>new HomeTest()));
                }
            ),

            ],),],
        ),),
        new Align(child: loadingIndicator,alignment: FractionalOffset.center,),

      ],));
  }

}

Olá, era isso que eu queria fazer, mas não estava conseguindo o layout de que precisava. Stack é a resposta. Sobre StatefulWidget, é correto construir todas as visualizações quando o estado de progresso muda?
Ricardo Bocchi

Ei, eu não entendi sua pergunta?
aziza

No meu código, quando _loadingmuda, todas as visualizações são reconstruídas. É assim mesmo?
Ricardo Bocchi

1
Usar um modal é provavelmente muito mais fácil e intuitivo ao mesmo tempo. Você pode simplesmente empurrar uma caixa de diálogo de carregamento no início ou seu pedido e abri-la quando terminar. Ele também tem a vantagem de impedir outras entradas do usuário.
Rémi Rousselet

2
Ok, deixe-me assar algo.
Rémi Rousselet

34

Crie um bool isLoadinge defina-o como false. Com a ajuda do operador ternário, quando o usuário clica no botão de login, defina o estado de isLoadingpara true. Você obterá um indicador de carregamento circular no lugar do botão de login

 isLoading ? new PrimaryButton(
                      key: new Key('login'),
                      text: 'Login',
                      height: 44.0,
                      onPressed: setState((){isLoading = true;}))
                  : Center(
                      child: CircularProgressIndicator(),
                    ),

Você pode ver as capturas de tela como fica antes de clicar no login insira a descrição da imagem aqui

Depois que o login é clicado insira a descrição da imagem aqui

Nesse meio tempo, você pode executar o processo de login e login do usuário. Se as credenciais do usuário estão errados em seguida, novamente você vai setStatede isLoadinga false, tal que o indicador de carga se tornará botão invisível e login visível para o usuário. A propósito, primaryButton usado no código é meu botão personalizado. Você pode fazer o mesmo com OnPressedem button.


Isso é realmente muito inteligente! Não há necessidade de clicar duas vezes, etc. Obrigado.
Benobab

como lidar com o duplo clique em vibração como este cenário?

Nunca tive essa situação para lidar com o toque duplo, pois com um único toque ele muda para o indicador de carregamento. Pelo que entendi do seu comentário, acho que podemos envolver o botão personalizado com o detector de gestos e, então, você pode trabalhar com um toque duplo.
Harsha pulikollu

Onde usar o operador ternário? Seu exemplo parece inteligente, mas não tem certeza de como implementá-lo.
Bikram Pahi

Use o trecho de código mencionado acima no método de construção onde você deseja ter um botão (login). Quando o usuário clica nesse botão, o bool (isLoading) torna-se verdadeiro e mostra o indicador de carregamento circular em vez do botão.
Harsha pulikollu

20

1. Sem plugin

    class IndiSampleState extends State<ProgHudPage> {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        appBar: new AppBar(
          title: new Text('Demo'),
        ),
        body: Center(
          child: RaisedButton(
            color: Colors.blueAccent,
            child: Text('Login'),
            onPressed: () async {
              showDialog(
                  context: context,
                  builder: (BuildContext context) {
                    return Center(child: CircularProgressIndicator(),);
                  });
              await loginAction();
              Navigator.pop(context);
            },
          ),
        ));
  }

  Future<bool> loginAction() async {
    //replace the below line of code with your login request
    await new Future.delayed(const Duration(seconds: 2));
    return true;
  }
}

2. Com plugin

verifique este plugin progress_hud

adicione a dependência no arquivo pubspec.yaml

dev_dependencies:
  progress_hud: 

importar o pacote

import 'package:progress_hud/progress_hud.dart';

O código de amostra é fornecido abaixo para mostrar e ocultar o indicador

class ProgHudPage extends StatefulWidget {
  @override
  _ProgHudPageState createState() => _ProgHudPageState();
}

class _ProgHudPageState extends State<ProgHudPage> {
  ProgressHUD _progressHUD;
  @override
  void initState() {
    _progressHUD = new ProgressHUD(
      backgroundColor: Colors.black12,
      color: Colors.white,
      containerColor: Colors.blue,
      borderRadius: 5.0,
      loading: false,
      text: 'Loading...',
    );
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        appBar: new AppBar(
          title: new Text('ProgressHUD Demo'),
        ),
        body: new Stack(
          children: <Widget>[
            _progressHUD,
            new Positioned(
                child: RaisedButton(
                  color: Colors.blueAccent,
                  child: Text('Login'),
                  onPressed: () async{
                    _progressHUD.state.show();
                    await loginAction();
                    _progressHUD.state.dismiss();
                  },
                ),
                bottom: 30.0,
                right: 10.0)
          ],
        ));
  }

  Future<bool> loginAction()async{
    //replace the below line of code with your login request
    await new Future.delayed(const Duration(seconds: 2));
    return true;
  }
}

12
Não vote nisso, algumas pessoas não querem lidar com os detalhes essenciais da IU e eu sou uma delas, então este plugin é útil
Vladtn

3
a barra de progresso na api é justa o suficiente adicionar dependência aumenta o tamanho da compilação. já a construção de vibração é excessiva.
prashant0205

Você realmente deveria adicionar isso como uma dependência de desenvolvimento?
George

verifique com o exemplo mais recente pub.dartlang.org/packages/progress_hud#-example-tab-
Shyju M

1
@MohammadMeshkani use Navigator.pop (contexto); antes de navegar para a próxima tela
Shyju M

13

Etapa 1: Criar diálogo

   showAlertDialog(BuildContext context){
      AlertDialog alert=AlertDialog(
        content: new Row(
            children: [
               CircularProgressIndicator(),
               Container(margin: EdgeInsets.only(left: 5),child:Text("Loading" )),
            ],),
      );
      showDialog(barrierDismissible: false,
        context:context,
        builder:(BuildContext context){
          return alert;
        },
      );
    }

Etapa 2: Ligue para ele

showAlertDialog(context);
await firebaseAuth.signInWithEmailAndPassword(email: email, password: password);
Navigator.pop(context);

Exemplo com diálogo e formulário de login

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
class DynamicLayout extends StatefulWidget{
  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return new MyWidget();
    }
  }
showAlertDialog(BuildContext context){
  AlertDialog alert=AlertDialog(
    content: new Row(
        children: [
           CircularProgressIndicator(),
           Container(margin: EdgeInsets.only(left: 5),child:Text("Loading" )),
        ],),
  );
  showDialog(barrierDismissible: false,
    context:context,
    builder:(BuildContext context){
      return alert;
    },
  );
}

  class MyWidget extends State<DynamicLayout>{
  Color color = Colors.indigoAccent;
  String title='app';
  GlobalKey<FormState> globalKey=GlobalKey<FormState>();
  String email,password;
  login() async{
   var currentState= globalKey.currentState;
   if(currentState.validate()){
        currentState.save();
        FirebaseAuth firebaseAuth=FirebaseAuth.instance;
        try {
          showAlertDialog(context);
          AuthResult authResult=await firebaseAuth.signInWithEmailAndPassword(
              email: email, password: password);
          FirebaseUser user=authResult.user;
          Navigator.pop(context);
        }catch(e){
          print(e);
        }
   }else{

   }
  }
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        appBar:AppBar(
        title: Text("$title"),
        ) ,
          body: Container(child: Form(
            key: globalKey,
            child: Container(
              padding: EdgeInsets.all(10),
              child: Column(children: <Widget>[
              TextFormField(decoration: InputDecoration(icon: Icon(Icons.email),labelText: 'Email'),
              // ignore: missing_return
              validator:(val){
                if(val.isEmpty)
                  return 'Please Enter Your Email';
              },
              onSaved:(val){
                email=val;
              },
              ),
                TextFormField(decoration: InputDecoration(icon: Icon(Icons.lock),labelText: 'Password'),
             obscureText: true,
                  // ignore: missing_return
                  validator:(val){
                    if(val.isEmpty)
                      return 'Please Enter Your Password';
                  },
                  onSaved:(val){
                    password=val;
                  },
              ),
                RaisedButton(color: Colors.lightBlue,textColor: Colors.white,child: Text('Login'),
                  onPressed:login),
            ],)
              ,),)
         ),
    );
  }
}

insira a descrição da imagem aqui


2
Adicione um pouco mais de contexto à sua resposta.
Death Waltz

10

Adotei a abordagem a seguir, que usa um widget indicador de progresso modal simples que envolve tudo o que você deseja tornar modal durante uma chamada assíncrona.

O exemplo no pacote também aborda como lidar com a validação de formulário ao fazer chamadas assíncronas para validar o formulário (consulte flutter / issues / 9688 para obter detalhes sobre esse problema). Por exemplo, sem sair do formulário, este método de validação de formulário assíncrono pode ser usado para validar um novo nome de usuário em relação aos nomes existentes em um banco de dados durante a inscrição.

https://pub.dartlang.org/packages/modal_progress_hud

Aqui está a demonstração do exemplo fornecido com o pacote (com o código-fonte):

validação assíncrona de formulário com indicador de progresso modal

O exemplo pode ser adaptado a outro comportamento do indicador de progresso modal (como diferentes animações, texto adicional no modal, etc.).


2

Esta é a minha solução com pilha

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'dart:async';

final themeColor = new Color(0xfff5a623);
final primaryColor = new Color(0xff203152);
final greyColor = new Color(0xffaeaeae);
final greyColor2 = new Color(0xffE8E8E8);

class LoadindScreen extends StatefulWidget {
  LoadindScreen({Key key, this.title}) : super(key: key);
  final String title;
  @override
  LoginScreenState createState() => new LoginScreenState();
}

class LoginScreenState extends State<LoadindScreen> {
  SharedPreferences prefs;

  bool isLoading = false;

  Future<Null> handleSignIn() async {
    setState(() {
      isLoading = true;
    });
    prefs = await SharedPreferences.getInstance();
    var isLoadingFuture = Future.delayed(const Duration(seconds: 3), () {
      return false;
    });
    isLoadingFuture.then((response) {
      setState(() {
        isLoading = response;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text(
            widget.title,
            style: TextStyle(color: primaryColor, fontWeight: FontWeight.bold),
          ),
          centerTitle: true,
        ),
        body: Stack(
          children: <Widget>[
            Center(
              child: FlatButton(
                  onPressed: handleSignIn,
                  child: Text(
                    'SIGN IN WITH GOOGLE',
                    style: TextStyle(fontSize: 16.0),
                  ),
                  color: Color(0xffdd4b39),
                  highlightColor: Color(0xffff7f7f),
                  splashColor: Colors.transparent,
                  textColor: Colors.white,
                  padding: EdgeInsets.fromLTRB(30.0, 15.0, 30.0, 15.0)),
            ),

            // Loading
            Positioned(
              child: isLoading
                  ? Container(
                      child: Center(
                        child: CircularProgressIndicator(
                          valueColor: AlwaysStoppedAnimation<Color>(themeColor),
                        ),
                      ),
                      color: Colors.white.withOpacity(0.8),
                    )
                  : Container(),
            ),
          ],
        ));
  }
}

2

Eu sugiro usar este plugin flutter_easyloading

flutter_easyloading é um widget de carregamento simples e leve para o aplicativo Flutter, fácil de usar sem contexto, compatível com iOS e Android

Adicione isto ao pubspec.yamlarquivo do seu pacote :

dependencies:
  flutter_easyloading: ^2.0.0

Agora, em seu código Dart, você pode usar:

import 'package:flutter_easyloading/flutter_easyloading.dart';

Para usar primeiro, inicialize FlutterEasyLoadingem MaterialApp/CupertinoApp

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import './custom_animation.dart';

import './test.dart';

void main() {
  runApp(MyApp());
  configLoading();
}

void configLoading() {
  EasyLoading.instance
    ..displayDuration = const Duration(milliseconds: 2000)
    ..indicatorType = EasyLoadingIndicatorType.fadingCircle
    ..loadingStyle = EasyLoadingStyle.dark
    ..indicatorSize = 45.0
    ..radius = 10.0
    ..progressColor = Colors.yellow
    ..backgroundColor = Colors.green
    ..indicatorColor = Colors.yellow
    ..textColor = Colors.yellow
    ..maskColor = Colors.blue.withOpacity(0.5)
    ..userInteractions = true
    ..customAnimation = CustomAnimation();
}

Em seguida, use de acordo com sua necessidade

import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:dio/dio.dart';

class TestPage extends StatefulWidget {
  @override
  _TestPageState createState() => _TestPageState();
}

class _TestPageState extends State<TestPage> {
  @override
  void initState() {
    super.initState();
    // EasyLoading.show();
  }

  @override
  void deactivate() {
    EasyLoading.dismiss();
    super.deactivate();
  }

  void loadData() async {
    try {
      EasyLoading.show();
      Response response = await Dio().get('https://github.com');
      print(response);
      EasyLoading.dismiss();
    } catch (e) {
      EasyLoading.showError(e.toString());
      print(e);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter EasyLoading'),
      ),
      body: Center(
        child: FlatButton(
          textColor: Colors.blue,
          child: Text('loadData'),
          onPressed: () {
            loadData();
            // await Future.delayed(Duration(seconds: 2));
            // EasyLoading.show(status: 'loading...');
            // await Future.delayed(Duration(seconds: 5));
            // EasyLoading.dismiss();
          },
        ),
      ),
    );
  }
}

insira a descrição da imagem aqui


Onde está a classe de animação personalizada? Precisamos incluí-lo.
Nayas Subramanian

Não, você não precisa disso e, se quiser, vá para: github.com/huangjianke/flutter_easyloading/blob/develop/example/…
Paresh Mangukiya

1

Você pode usar o widget FutureBuilder. Isso requer um argumento que deve ser um futuro. Em seguida, você pode usar um instantâneo que é o estado no momento da chamada assíncrona ao fazer login, uma vez que termina o estado de retorno da função assíncrona será atualizado e o futuro construtor se reconstruirá para que você possa solicitar o novo Estado.

FutureBuilder(
  future:  myFutureFunction(),
  builder: (context, AsyncSnapshot<List<item>> snapshot) {
    if (!snapshot.hasData) {
      return Center(
        child: CircularProgressIndicator(),
      );
    } else {
     //Send the user to the next page.
  },
);

Aqui você tem um exemplo de como construir um futuro

Future<void> myFutureFunction() async{
 await callToApi();}

1

Você pode fazer isso para o indicador de progresso transparente central

Future<Null> _submitDialog(BuildContext context) async {
  return await showDialog<Null>(
      context: context,
      barrierDismissible: false,
      builder: (BuildContext context) {
        return SimpleDialog(
          elevation: 0.0,
          backgroundColor: Colors.transparent,
          children: <Widget>[
            Center(
              child: CircularProgressIndicator(),
            )
          ],
        );
      });
}

0
class Loader extends StatefulWidget {
      @override
      State createState() => LoaderState();
    }

    class LoaderState extends State<Loader> with SingleTickerProviderStateMixin {
      AnimationController controller;
      Animation<double> animation;

      @override
      void initState() {
        super.initState();
        controller = AnimationController(
            duration: Duration(milliseconds: 1200), vsync: this);
        animation = CurvedAnimation(parent: controller, curve: Curves.elasticOut);
        animation.addListener(() {
          this.setState(() {});
        });
        animation.addStatusListener((AnimationStatus status) {});
        controller.repeat();
      }

      @override
      void dispose() {
        controller.dispose();
        super.dispose();
      }

      @override
      Widget build(BuildContext context) {
        return Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Container(
              color: Colors.blue,
              height: 3.0,
              width: animation.value * 100.0,
            ),
            Padding(
              padding: EdgeInsets.only(bottom: 5.0),
            ),
            Container(
              color: Colors.blue[300],
              height: 3.0,
              width: animation.value * 75.0,
            ),
            Padding(
              padding: EdgeInsets.only(bottom: 5.0),
            ),
            Container(
              color: Colors.blue,
              height: 3.0,
              width: animation.value * 50.0,
            )
          ],
        );
      }
    }


    Expanded(
                        child: Padding(
                          padding:
                              EdgeInsets.only(left: 20.0, right: 5.0, top:20.0),
                          child: GestureDetector(
                            onTap: () {
                              Navigator.push(
                                  context,
                                  MaterialPageRoute(
                                      builder: (context) => FirstScreen()));
                            },
                            child: Container(
                                alignment: Alignment.center,
                                height: 45.0,
                                decoration: BoxDecoration(
                                    color: Color(0xFF1976D2),
                                    borderRadius: BorderRadius.circular(9.0)),
                                child: Text('Login',
                                    style: TextStyle(
                                        fontSize: 20.0, color: Colors.white))),
                          ),
                        ),
                      ),

Como posso combinar uma classe que cria um indicador de carregamento com meu botão, de modo que, quando pressiono, o indicador acende e vira para a próxima página?
Max Zubko

0
{
isloading? progressIos:Container()

progressIos(int i) {
    return Container(
        color: i == 1
            ? AppColors.liteBlack
            : i == 2 ? AppColors.darkBlack : i == 3 ? AppColors.pinkBtn : '',
        child: Center(child: CupertinoActivityIndicator()));
  }
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.