Comment travailler avec l'indicateur de progression en flutter?


86

Je suis novice en flutter et je voulais savoir quelle est la meilleure façon d'ajouter CircularProgressIndicatordans ma mise en page. Par exemple, ma vue de connexion. Cette vue a un nom d'utilisateur, un mot de passe et un bouton de connexion. Je voulais créer une mise en page de superposition (avec Opacity) qui, lors du chargement, affiche un indicateur de progression comme j'utilise dans NativeScript, mais je suis peu confus avec comment faire et aussi si c'est la meilleure façon. Sur NativeScript, par exemple, j'ajoute IndicatorActivity dans la mise en page principale et définit busy sur true ou false, de sorte qu'il superpose tous les composants de la vue lors du chargement.

Éditer:

J'ai pu atteindre ce résultat:

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

résultat de l'écran de l'application

Je m'adapte toujours à l'idée des États. Ce code est conforme aux attentes lorsque vous travaillez avec le flutter?

Merci!


1
comment désactiver le backpressé pendant que la boîte de dialogue s'affiche?
rapide

Réponses:


77

Dans le flutter, il existe plusieurs façons de gérer les actions asynchrones.

Une façon paresseuse de le faire peut être d'utiliser un modal. Ce qui bloquera l'entrée de l'utilisateur, empêchant ainsi toute action indésirable. Cela nécessiterait très peu de modifications de votre code. Modifiez simplement votre _onLoadingpour quelque chose comme ceci:

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

La manière la plus idéale de le faire est d'utiliser FutureBuilderun widget avec état. C'est ce que vous avez commencé. L'astuce est qu'au lieu d'avoir un boolean loading = falsedans votre état, vous pouvez directement utiliser unFuture<MyUser> user

Et puis passez-le comme argument à FutureBuilder, ce qui vous donnera des informations telles que "hasData" ou l'instance de une MyUserfois terminé.

Cela conduirait à quelque chose comme ceci:

@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
Cool, les deux exemples seront utiles lors de la connexion et dans d'autres situations. La progression du gestionnaire avec le dialogue est meilleure que ma version et FutureBuilder Elle est aussi plus élégante que ma solution. Merci pour l'aide!
Ricardo Bocchi

une question hors sujet .. à chaque TextField j'ai besoin d'un TextEditingController unique?
Ricardo Bocchi

@RicardoBocchi Yes
aziza

Je ne pense pas que le dialogue fonctionnera avec l'exemple réel, il est difficile de savoir comment l'utilisateur sera redirigé après le retour de _login (). Votre deuxième exemple semble bien plus pratique. Bien cuit.
aziza

1
Eh bien, le Dialogue est fonctionnel et nécessite très peu de modification de son code d'origine. Il pourrait par exemple suivre le dialogue de près avec un Navigator.pushNamed("/home").
Rémi Rousselet

38

Pour moi, une façon intéressante de le faire est d'afficher un SnackBaren bas pendant le processus de connexion, ceci est un exemple de ce que je veux dire:

entrez la description de l'image ici

Voici comment configurer le SnackBar.

Définissez une clé globale pour votre Scaffold

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

Ajoutez-le à votre Scaffold keyattribut

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

Rappel de mon bouton de connexion 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")
                  );
                }

Cela dépend vraiment de la façon dont vous souhaitez créer votre mise en page et je ne suis pas sûr de ce que vous avez en tête.

Éditer

Vous le souhaitez probablement de cette façon, j'ai utilisé une pile pour obtenir ce résultat et simplement afficher ou masquer mon indicateur en fonction de onPressed

entrez la description de l'image ici

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

      ],));
  }

}

Salut, c'est ce que je voulais faire, mais je n'obtenais pas la mise en page dont j'avais besoin. Stack est la réponse. À propos de StatefulWidget, est-il correct de créer toutes les vues lorsque l'état de progression change?
Ricardo Bocchi

Hé, je ne comprends pas ta question?
aziza

Dans mon code, lors du _loadingchangement, toutes les vues sont reconstruites. Est-ce vrai?
Ricardo Bocchi

1
Utiliser un modal est probablement beaucoup plus facile et plus intuitif à la fois. Vous pouvez simplement pousser une boîte de dialogue de chargement au début ou votre demande, et l'afficher lorsque vous avez terminé. Il présente également l'avantage d'empêcher toute entrée supplémentaire de l'utilisateur.
Rémi Rousselet

2
Okey, laisse-moi cuisiner quelque chose.
Rémi Rousselet

34

Créez un booléen isLoadinget définissez-le sur false. Avec l'aide de l'opérateur ternaire, lorsque l'utilisateur clique sur le bouton de connexion, définissez l'état isLoadingsur true. Vous obtiendrez un indicateur de chargement circulaire à la place du bouton de connexion

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

Vous pouvez voir les captures d'écran à quoi il ressemble avant de cliquer sur la connexion entrez la description de l'image ici

Après avoir cliqué sur la connexion entrez la description de l'image ici

En attendant, vous pouvez exécuter le processus de connexion et vous connecter à l'utilisateur. Si les informations d' identification de l' utilisateur sont erronés puis de nouveau vous setStatede isLoadingla falsesorte que l' indicateur de chargement deviendras bouton invisible et visible connexion à l' utilisateur. À propos, primaryButton utilisé dans le code est mon bouton personnalisé. Vous pouvez faire de même avec OnPressedin button.


C'est en fait assez intelligent! Pas besoin de gérer un double clic, etc. Merci.
Benobab

comment gérer le double-clic dans le flutter comme ce scénario?

Je n'ai jamais eu cette situation à gérer un double tap, car en un seul clic, il se transforme en indicateur de chargement. Selon ma compréhension de votre commentaire, je pense que nous pouvons envelopper le bouton personnalisé avec un détecteur de geste, puis vous pouvez y travailler en double tapant.
Harsha pulikollu

Où utiliser l'opérateur ternaire? Votre exemple semble intelligent mais vous ne savez pas comment le mettre en œuvre.
Bikram Pahi

Utilisez l'extrait de code mentionné ci-dessus dans la méthode de construction où vous souhaitez avoir un bouton (connexion). Lorsque l'utilisateur clique sur ce bouton, le booléen (isLoading) devient vrai et affiche l'indicateur de chargement circulaire au lieu du bouton.
Harsha pulikollu

20

1. Sans 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. Avec plugin

vérifier ce plugin progress_hud

ajouter la dépendance dans le fichier pubspec.yaml

dev_dependencies:
  progress_hud: 

importer le package

import 'package:progress_hud/progress_hud.dart';

Un exemple de code est donné ci-dessous pour afficher et masquer l'indicateur

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
Ne votez pas contre cela, certaines personnes ne veulent pas gérer les détails de l'interface utilisateur et je suis l'un d'entre eux, donc ce plugin est utile
Vladtn

3
la barre de progression dans l'api est assez juste l'ajout de dépendance augmente la taille de la construction. déjà la construction de flutter est excessive.
prashant0205

Devriez-vous vraiment l'ajouter en tant que dépendance de développement?
George


1
@MohammadMeshkani utilise Navigator.pop (contexte); avant de
passer

13

Étape 1: Créer une boîte de dialogue

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

Étape 2: Appelez-le

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

Exemple avec boîte de dialogue et formulaire de connexion

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

entrez la description de l'image ici


2
Veuillez ajouter un peu plus de contexte à votre réponse.
Death Waltz

10

J'ai adopté l'approche suivante, qui utilise un simple widget indicateur de progression modale qui encapsule tout ce que vous voulez rendre modal lors d'un appel asynchrone.

L'exemple du package explique également comment gérer la validation de formulaire tout en effectuant des appels asynchrones pour valider le formulaire (voir flutter / issues / 9688 pour plus de détails sur ce problème). Par exemple, sans quitter le formulaire, cette méthode de validation de formulaire asynchrone peut être utilisée pour valider un nouveau nom d'utilisateur par rapport aux noms existants dans une base de données lors de l'inscription.

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

Voici la démo de l'exemple fourni avec le package (avec le code source):

validation de formulaire asynchrone avec indicateur de progression modale

L'exemple pourrait être adapté à d'autres comportements d'indicateur de progression modale (comme différentes animations, texte supplémentaire en modal, etc.).


2

C'est ma solution avec 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

Je suggère d'utiliser ce plugin flutter_easyloading

flutter_easyloading est un widget de chargement propre et léger pour l'application Flutter, facile à utiliser sans contexte, prend en charge iOS et Android

Ajoutez ceci au pubspec.yamlfichier de votre package :

dependencies:
  flutter_easyloading: ^2.0.0

Maintenant, dans votre code Dart, vous pouvez utiliser:

import 'package:flutter_easyloading/flutter_easyloading.dart';

Pour utiliser First, initialisez FlutterEasyLoadingdans 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();
}

Ensuite, utilisez selon vos besoins

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

entrez la description de l'image ici


Où est la classe d'animation personnalisée? Avons-nous besoin de l'inclure.
Nayas Subramanian

Non, vous n'avez pas besoin de cela, et si vous le souhaitez, rendez-vous sur: github.com/huangjianke/flutter_easyloading/blob/develop/example/…
Paresh Mangukiya

1

Vous pouvez utiliser le widget FutureBuilder à la place. Cela prend un argument qui doit être un avenir. Ensuite, vous pouvez utiliser un instantané qui est l'état au moment de l'appel asynchrone lors de la connexion, une fois qu'il se termine, l'état du retour de la fonction async sera mis à jour et le futur constructeur se reconstruira afin que vous puissiez alors demander le nouveau Etat.

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

Ici, vous avez un exemple sur la façon de construire un avenir

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

1

Vous pouvez le faire pour l'indicateur de progression transparent du centre

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

Comment puis-je combiner une classe qui crée un indicateur de chargement avec mon bouton, de sorte que lorsque j'appuie dessus, l'indicateur s'allume et passe à la page suivante?
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()));
  }
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.