Come lavorare con l'indicatore di progresso in flutter?


86

Sono un principiante in flutter e volevo sapere qual è il modo migliore per aggiungere CircularProgressIndicatornel mio layout. Ad esempio, la mia vista di accesso. Questa vista ha nome utente, password e pulsante di accesso. Volevo creare un layout di sovrapposizione (con Opacity) che, durante il caricamento, mostri l'indicatore di avanzamento come uso in NativeScript, ma sono poco confuso con come farlo e anche se è il modo migliore. Su NativeScript, ad esempio, aggiungo IndicatorActivity nel layout principale e imposto occupato su true o false, in modo che si sovrapponga a tutti i componenti della vista durante il caricamento.

Modificare:

Sono riuscito a raggiungere questo risultato:

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

risultato della schermata dell'app

Mi sto ancora adattando all'idea degli stati. Questo codice rientra nel previsto quando si lavora con flutter?

Grazie!


1
come disabilitare il backpress mentre viene visualizzata la finestra di dialogo?
Studente veloce

Risposte:


77

In flutter, ci sono alcuni modi per gestire le azioni asincrone.

Un modo pigro per farlo può essere usare un modal. Che bloccherà l'input dell'utente, impedendo così qualsiasi azione indesiderata. Ciò richiederebbe pochissime modifiche al codice. Sto solo modificando il tuo _onLoadingin qualcosa di simile:

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

Il modo più ideale per farlo è usare FutureBuildere un widget stateful. Che è quello che hai iniziato. Il trucco è che, invece di avere un file boolean loading = falsenel tuo stato, puoi usare direttamente un fileFuture<MyUser> user

E poi FutureBuilderpassalo come argomento a , che ti darà alcune informazioni come "hasData" o l'istanza di MyUserquando completato.

Questo porterebbe a qualcosa del genere:

@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
Fantastico, entrambi gli esempi saranno utili al login e in altre situazioni. Il progresso del gestore con la finestra di dialogo sembra migliore della mia versione e FutureBuilder è anche più elegante della mia soluzione. grazie per l'aiuto!
Ricardo Bocchi

una domanda fuori tema .. ad ogni TextField ho bisogno di un TextEditingController unico?
Ricardo Bocchi

@RicardoBocchi Sì
aziza

Non penso che la finestra di dialogo funzionerà con l'esempio reale, è fonte di confusione come verrà reindirizzato l'utente dopo che viene restituito _login (). Il tuo secondo esempio però sembra molto più conveniente. Ben cotto.
aziza

1
Bene, il dialogo è funzionale e richiede pochissime modifiche al suo codice originale. Ad esempio, potrebbe seguire la chiusura del dialogo con un file Navigator.pushNamed("/home").
Rémi Rousselet

38

Per me, un modo accurato per farlo è mostrare un SnackBarin basso durante il processo di accesso, questo è un esempio di ciò che intendo:

inserisci qui la descrizione dell'immagine

Ecco come configurare il file SnackBar.

Definisci una chiave globale per il tuo Scaffold

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

Aggiungilo al tuo Scaffold keyattributo

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

Richiamata pulsante My SignIn 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")
                  );
                }

Dipende davvero da come vuoi costruire il tuo layout e non sono sicuro di cosa hai in mente.

modificare

Probabilmente lo vuoi in questo modo, ho usato uno Stack per ottenere questo risultato e mostrare o nascondere il mio indicatore in base a onPressed

inserisci qui la descrizione dell'immagine

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,),

      ],));
  }

}

Ciao, è quello che volevo fare, ma non stavo ottenendo il layout di cui avevo bisogno. Stack è la risposta. Informazioni su StatefulWidget, è corretto costruire tutta la vista quando lo stato di avanzamento cambia?
Ricardo Bocchi

Ehi, non capisco la tua domanda?
aziza

Nel mio codice, quando _loadingcambia, tutte le visualizzazioni vengono ricostruite. È così?
Ricardo Bocchi

1
L'uso di un modale è probabilmente molto più semplice e intuitivo allo stesso tempo. Puoi semplicemente premere una finestra di dialogo di caricamento all'inizio o alla tua richiesta e visualizzarla al termine. Ha anche il vantaggio di impedire ulteriori input da parte dell'utente.
Rémi Rousselet

2
Okey, fammi cuocere qualcosa.
Rémi Rousselet

34

Crea un bool isLoadinge impostalo su false. Con l'aiuto di operatore ternario, quando l'utente fa clic sul pulsante di accesso Stato set di isLoadinga true. Otterrai un indicatore di caricamento circolare al posto del pulsante di accesso

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

Puoi vedere gli screenshot come appaiono mentre fai clic prima del login inserisci qui la descrizione dell'immagine

Dopo aver fatto clic sul login inserisci qui la descrizione dell'immagine

Nel frattempo è possibile eseguire il processo di accesso e il login dell'utente. Se le credenziali utente sono sbagliate poi di nuovo si setStatedi isLoadinga false, in modo tale che l'indicatore di caricamento diventerete pulsante invisibile ed effettuare il login visibile all'utente. A proposito, il primaryButton utilizzato nel codice è il mio pulsante personalizzato. Puoi fare lo stesso con OnPressedin button.


In realtà è abbastanza intelligente! Non c'è bisogno di gestire il doppio clic, ecc. Grazie.
Benobab

come gestire il doppio clic in flutter come questo scenario?

Non ho mai avuto quella situazione per gestire il doppio tocco poiché al tocco singolo cambia in indicatore di caricamento. Secondo la mia comprensione del tuo commento, penso che possiamo avvolgere il pulsante personalizzato con il rilevatore di gesti e quindi puoi lavorare con un doppio tocco lì.
Harsha pulikollu

Dove usare l'operatore ternario? Il tuo esempio sembra intelligente ma non sei sicuro di come implementarlo.
Bikram Pahi

Usa il frammento di codice sopra menzionato nel metodo di compilazione in cui desideri avere un pulsante (login). Quando l'utente fa clic su quel pulsante, bool (isLoading) diventa vero e mostra l'indicatore di caricamento circolare invece del pulsante.
Harsha pulikollu

20

1. Senza 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. Con plugin

controlla questo plugin progress_hud

aggiungere la dipendenza nel file pubspec.yaml

dev_dependencies:
  progress_hud: 

importa il pacchetto

import 'package:progress_hud/progress_hud.dart';

Di seguito viene fornito un codice di esempio per mostrare e nascondere l'indicatore

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
Non votarlo, alcune persone non vogliono gestire i dettagli
essenziali

3
la barra di avanzamento in api è abbastanza corretta l'aggiunta di dipendenza aumenta la dimensione della build. già la costruzione svolazzante è eccessiva.
prashant0205

Dovresti davvero aggiungerlo come dipendenza dagli sviluppatori?
George


1
@MohammadMeshkani usa Navigator.pop (contesto); prima di passare alla schermata successiva
Shyju M

13

Passaggio 1: crea la finestra di dialogo

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

Passaggio 2: chiamalo

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

Esempio con finestra di dialogo e modulo di accesso

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

inserisci qui la descrizione dell'immagine


2
Aggiungi solo un po 'più di contesto alla tua risposta.
Death Waltz

10

Ho adottato il seguente approccio, che utilizza un semplice widget indicatore di avanzamento modale che racchiude tutto ciò che si desidera rendere modale durante una chiamata asincrona.

L'esempio nel pacchetto spiega anche come gestire la convalida del modulo mentre si effettuano chiamate asincrone per convalidare il modulo (vedere flutter / issues / 9688 per i dettagli di questo problema). Ad esempio, senza lasciare il modulo, questo metodo di convalida del modulo asincrono può essere utilizzato per convalidare un nuovo nome utente rispetto a nomi esistenti in un database durante la registrazione.

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

Ecco la demo dell'esempio fornito con il pacchetto (con codice sorgente):

convalida del modulo asincrono con indicatore di avanzamento modale

L'esempio potrebbe essere adattato ad altri comportamenti degli indicatori di progresso modali (come animazioni diverse, testo aggiuntivo in modalità modale, ecc.).


2

Questa è la mia soluzione con stack

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

Suggerisco di utilizzare questo plugin flutter_easyloading

flutter_easyloading è un widget di caricamento pulito e leggero per l'app Flutter, facile da usare senza contesto, supporta iOS e Android

Aggiungi questo al pubspec.yamlfile del tuo pacchetto :

dependencies:
  flutter_easyloading: ^2.0.0

Ora nel tuo codice Dart puoi usare:

import 'package:flutter_easyloading/flutter_easyloading.dart';

Per utilizzare First, inizializza FlutterEasyLoadingin 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();
}

Quindi, utilizzare in base alle proprie esigenze

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

inserisci qui la descrizione dell'immagine


Dov'è la classe di animazione personalizzata? Dobbiamo includerlo.
Nayas Subramanian


1

Puoi invece utilizzare il widget FutureBuilder. Questo richiede un argomento che deve essere un futuro. Quindi puoi utilizzare un'istantanea che è lo stato al momento della chiamata asincrona al momento dell'accesso, una volta terminato lo stato della funzione di ritorno asincrono verrà aggiornato e il generatore futuro si ricostruirà da solo in modo che tu possa quindi chiedere il nuovo stato.

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

Ecco un esempio su come costruire un futuro

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

1

Puoi farlo per l'indicatore di avanzamento trasparente centrale

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))),
                          ),
                        ),
                      ),

Come posso combinare una classe che crea un indicatore di caricamento con il mio pulsante, in modo che quando lo premo, l'indicatore si accenda e passi alla pagina successiva?
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()));
  }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.