Flutter : comment afficher un progress indicator (indicateur de progression de chargement) ?

Le framework Flutter utilise un système de widget pour créer l'interface de votre application, en utilisant le langage Dart. Une fois l’interface prête, le code sera converti pour pouvoir fonctionner sur le système d'exploitation Android mais aussi sur iOS. Si vous souhaitez ajouter un indicateur visuel de chargement, pour par exemple effectuer les vérifications nécessaires avant de connecter un utilisateur, Flutter vous permet d'utiliser plusieurs méthodes.

Pour afficher un widget invitant à patienter, vous pouvez utiliser la classe "CircularProgressIndicator". Il s'agit d'un cercle qui tourne afin d'indiquer qu'un traitement est en cours et d'empêcher l'utilisateur d'effectuer des manipulations. La méthode la plus facile à implémenter consiste à créer une fenêtre modale qui va venir se superposer par-dessus votre écran. La fonction "showDialog" va afficher la fenêtre modale. Vous pouvez ensuite utiliser la classe "Future.delayed". Cette classe permet de faire un traitement qui ne sera effectué qu'au bout de la durée précisée dans le premier paramètre. Dans ce traitement, la fonction "Navigator.pop()" va permettre de revenir à l'écran précédent, vous pourrez ensuite appeler votre méthode pour charger l'écran suivant.

void _onLoading() {
  //Affichage de la modale
  showDialog(
    context: context,
    barrierDismissible: false,
    builder: (BuildContext context) {
      return Dialog(
        child: new Row(
          mainAxisSize: MainAxisSize.min,
          children: [
            new CircularProgressIndicator(),
            new Text("Chargement"),
          ],
        ),
      );
    },
  );
//Après 3 secondes, on effectue la connexion
  new Future.delayed(new Duration(seconds: 3), () {
    Navigator.pop(context); //pop dialog
    _login();
  });
}

Une méthode plus précise consiste à utiliser directement une classe que l'on a créée soi-même, par l'exemple la classe utilisateur, et à contrôler si elle a des données dans la méthode "FutureBuilder". Cette méthode ne sera appelée que lorsque l'utilisateur qu'on lui transmettra sera modifié. Voici un exemple de code à modifier pour intégrer cette fonctionnalité dans votre application.

@immutable
class Utilisateur {
  final String nom;

  Utilisateur(this.nom);
}

class MonApplication extends StatelessWidget {
  // Il s'agit du widget qui va contenir l'application en elle-même
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Mon application',
      home: new Accueil(title: "Page d'accueil"),
    );
  }
}

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

  final String title;

  @override
  _AccueilState createState() => new _ AccueilState();
}

class _ AccueilState extends State<Accueil> {
  Future<Utilisateur> utilisateur;

  void _logIn() {
   //C'est dans cette fonction que vous devez écrire le code qui vérifie les informations de connexion de l'utilisateur
    setState(() {
      utilisateur = new Future.delayed(const Duration(seconds: 3), () {
        return new Utilisateur("Jean");
      });
    });
  }

  Widget _buildForm(AsyncSnapshot<Utilisateur> snapshot) {
    //Widget contenant le formulaire de connexion et le widget de chargement
    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) {
    //Widget affiché après la connexion
    return new FutureBuilder(
      future: utilisateur,
      builder: (context, AsyncSnapshot<Utilisateur> snapshot) {
        if (snapshot.hasData) {
          //On entre ici si la connexion a réussi
          return new Scaffold(
            appBar: new AppBar(
              title: new Text("Hello ${snapshot.data.name}"),
            ),
          );
        } else {
          //On entre ici si la connexion a échoué
          return new Scaffold(
            appBar: new AppBar(
              title: new Text("Connection"),
            ),
            body: _buildForm(snapshot),
          );
        }
      },
    );
  }
}

Android