Flutter: Comment créer une connexion utilisateur avec Firebase

Libération

25/12/18 - Mise à jour du dernier extrait de code après refactoring et nettoyage.

24/01/19 - Lien dupliqué vers github en haut de l'article.

23/07/19 - Ajout de la méthode de découpe à l'email et au mot de passe

Code source

Si vous voulez ignorer le charabia entier, vous pouvez récupérer le code source ici

https://github.com/tattwei46/flutter_login_demo

Mise à jour

Voici une suite de ce post qui est Comment faire du CRUD avec Firebase RTDB. Vérifiez-le!

Qu'est-ce que Flutter?

Flutter est un SDK mobile open source développé par Google pour créer des applications de haute qualité pour Android et iOS. Il permet aux développeurs de créer des applications avec un design magnifique, une animation fluide et des performances rapides, mais également en mesure d'intégrer rapidement de nouvelles fonctionnalités. Flutter offre un développement à haute vélocité avec son rechargement à chaud et son redémarrage à chaud. Avec une seule base de code à gérer, vous économisez beaucoup en comparant la gestion de projets Android et iOS puisque Flutter le compile en code ARM natif. Flutter utilise le langage de programmation Dart, également développé par Google.

Pourquoi Dart?

  • Un langage laconique, fortement typé et orienté objet.
  • Prend en charge la compilation juste-à-temps et en avance.
  • JIT permet à flutter de recompiler le code directement sur l'appareil pendant que l'application est toujours en cours d'exécution.
  • Activer le développement rapide et permet un rechargement à chaud stable en moins d'une seconde.
  • AOT permet de compiler le code directement en code ARM natif, ce qui permet un démarrage rapide et des performances prévisibles.

Qu'est-ce que Firebase?

Firebase est une plate-forme de développement Web et mobile offrant aux développeurs une large gamme de produits. Aujourd'hui, nous étudierons comment construire notre première application flottante avec l'authentification Firebase et la base de données en temps réel. Cette application permet à l'utilisateur de s'inscrire ou de se connecter et d'effectuer des tâches à exécuter CRUD avec Firebase. Sur ce post, nous allons nous concentrer uniquement sur la partie inscription et connexion de l'utilisateur.

Comment configurer l'environnement

  • Suivez les instructions dans ce lien
  • Obtenez le SDK Flutter
  • Lancer le docteur Flutter pour installer toutes les dépendances
docteur flottant
  • Utilisez la commande ci-dessous pour ouvrir le simulateur iOS.
ouvrir un simulateur
  • Pour ouvrir l'émulateur Android, lancez Android Studio> Outils> Gestionnaire AVD et sélectionnez Créer un périphérique virtuel.

App Flutter de bâtiment

Vous pouvez obtenir le code source complet dans le lien GitHub au bas de la publication. Ce qui suit montre comment dériver d'un exemple de projet Flutter pour compléter le code source dans GitHub.

Etape 1: créez une nouvelle démo de connexion flutter par un appel de projet flutter. Lancer le simulateur et exécuter le projet en utilisant le flutter. Vous pouvez utiliser Android Studio ou VSCode comme votre IDE préféré. Les étapes pour configurer votre éditeur ici.

course flottante

Si vous avez à la fois l'émulateur Android et iOS Simulator en cours d'exécution, exécutez la commande suivante pour les exécuter.

flutter run -d tous

Vous devriez voir des écrans similaires sur l'émulateur Android et le simulateur iOS.

À gauche: Android, à droite: iOS
Si vous êtes intéressé à savoir comment obtenir des captures d'écran sur vos simulateurs;
Pour Android: Cliquez simplement sur l'icône de caméra sur le côté gauche du volet d'outils. L'image sera enregistrée sur le bureau
Pour iOS: [Option 1] Maintenez et appuyez sur commande + Maj + 4. Appuyez sur la barre d'espacement pour changer le pointeur de la souris sur l'icône de l'appareil photo. Pointez sur le simulateur iOS, cliquez pour prendre une capture d'écran. L'image sera enregistrée sur le bureau.

[Option 2] Sélectionnez Simulator et appuyez sur commande + S. Merci JerryZhou pour le partage de cette information.

Etape 2: Dans main.dart, effacez tout le contenu et ajoutez le passe-partout suivant à votre fichier. Nous allons créer un nouveau fichier appelé login_page.dart qui a la classe LoginPage. Sur votre terminal, appuyez sur la touche R pour effectuer le rechargement à chaud. Vous devriez voir «Hello World» à l'écran.

Main.dart

importer 'package: flutter / material.dart';
importer 'login_signup_page.dart';

void main () => runApp (new MyApp ());

La classe MyApp étend StatelessWidget {
  
  @passer outre
  Construction du widget (contexte BuildContext) {
    renvoyer un nouveau MaterialApp (
      titre: 'Flutter Login Demo',
      thème: nouveau ThemeData (
        primarySwatch: Colors.blue,
      ),
      home: nouveau LoginSignUpPage ()
    )
  }
}

login_signup_page.dart

importer 'package: flutter / material.dart';

class LoginSignUpPage étend StatelessWidget {

  @passer outre
  Construction du widget (contexte BuildContext) {
    retourne un nouvel échafaudage (
      appBar: nouvelle AppBar (
        titre: nouveau texte ("Démo de connexion Flutter"),
      ),
      body: nouveau conteneur (
        child: nouveau texte ("Hello World"),
      ),
    )
  }
}

Etape 3: Passage de l'état sans état à l'étatful.

login_signup_page.dart

importer 'package: flutter / material.dart';

class LoginSignUpPage étend StatefulWidget {

  @passer outre
  Etat  createState () => new _LoginSignUpPageState ();

}

La classe _LoginSignUpPageState étend l'état  {

  @passer outre
  Construction du widget (contexte BuildContext) {
    retourne un nouvel échafaudage (
      appBar: nouvelle AppBar (
        titre: nouveau texte ("Démo de connexion Flutter"),
      ),
      body: nouveau conteneur (
        child: nouveau texte ("Hello World"),
      ),
    )
  }
}

Etape 4: Dans le corps d’échafaudage, remplacez le texte Hello Word par un formulaire et insérez un ListView à l’intérieur de celui-ci. Un ListView prend un tableau de widgets. Nous allons restructurer chaque composant de l'interface utilisateur dans un widget séparé.

Lorsque vous utilisez la saisie de texte, il est préférable de l'enrouler autour d'un ListView pour éviter les erreurs de rendu lorsque le clavier logiciel apparaît en raison d'un dépassement de pixels.

login_signup_page.dart

@passer outre
Construction du widget (contexte BuildContext) {
  _isIos = Theme.of (context) .platform == TargetPlatform.iOS;
  retourne un nouvel échafaudage (
      appBar: nouvelle AppBar (
        titre: new Text ('Flutter login demo'),
      ),
      corps: pile (
        enfants:  [
          _showBody (),
          _showCircularProgress (),
        ],
      ));
}

Etape 5: Construction de chaque composant de l'interface utilisateur

Notez que dans le corps d'échafaudage, nous avons un widget Stack comme corps. Ce que je veux faire, en gros, est de montrer à l’utilisateur un indicateur de chargement circulaire, lorsqu’une activité de connexion ou d’inscription est en cours. Pour ce faire, nous devons superposer un CircularProgressIndicator (heureusement, Flutter a déjà ce widget, donc pour l'utiliser, appelez-le simplement) avec notre présentation de widget principale (le formulaire de connexion / inscription). C'est la fonction du widget Stack, qui permet à un widget de se superposer à un autre widget. Pour contrôler l'affichage ou non de CircularProgressIndicator, nous vérifions sur bool _isLoading si l'écran est en cours de chargement ou non.

Widget _showCircularProgress () {
  si (_isLoading) {
    Centre de retour (enfant: CircularProgressIndicator ());
  } return Container (height: 0.0, width: 0.0,);

}

Pour le logo, nous allons utiliser un widget héros et également importer l'image en ajoutant la ligne suivante dans votre fichier pubspec.yaml. Puis lancez get packages pour importer votre image.

les atouts:
  - assets / flutter-icon.png

login_signup_page.dart

Widget _showLogo () {
  retourne le nouveau héros (
    tag: 'héros',
    enfant: Rembourrage (
      remplissage: EdgeInsets.fromLTRB (0.0, 70.0, 0.0, 0.0),
      enfant: CircleAvatar (
        backgroundColor: Colors.transparent,
        rayon: 48,0,
        child: Image.asset ('assets / flutter-icon.png'),
      ),
    ),
  )
}

[Mise à jour] Auparavant, nous utilisons un widget d'espacement flexible utilisant SizedBox, qui prend en entrée de hauteur un espacement vertical entre les 2 widgets. Maintenant, nous venons de placer un widget dans un widget de rembourrage et d’utiliser padding: EdgeInsets.fromLTRB (), ce qui signifie de gauche à droite, en haut, à droite et en bas et entrer la valeur de padding à la position correcte en conséquence.

Vient ensuite notre champ de texte de courrier électronique et mot de passe Avis pour chaque champ, nous avons validateur et onSaved. Ces 2 rappels seront déclenchés lorsque form.validate () et form.save () seront appelés. Ainsi, par exemple, si form.save () est appelé, la valeur du champ de texte est copiée dans une autre variable locale.

Nous allons également introduire un validateur dans nos champs pour vérifier si les champs sont vides, puis montrer un avertissement à l'utilisateur en rouge. Nous devons également créer les variables _email et _password pour stocker les valeurs. Pour mot de passe, nous définissons obsecureText: true pour masquer le mot de passe de l'utilisateur.

Mise à jour: j'ai ajouté la méthode de rognage aux adresses email et mot de passe pour supprimer les espaces non voulus.

Widget _showEmailInput () {
  retourner Padding (
    remplissage: const EdgeInsets.fromLTRB (0.0, 100.0, 0.0, 0.0),
    child: new TextFormField (
      maxLines: 1,
      keyboardType: TextInputType.emailAddress,
      autofocus: faux,
      décoration: nouvelle InputDecoration (
          hintText: 'Email',
          icon: nouvelle icône (
            Icons.mail,
            couleur: Colors.grey,
          )),
      validateur: (valeur) => valeur.isEmpty? 'Email ne peut pas être vide': null,
      onSaved: (valeur) => _email = valeur.trim (),
    ),
  )
}

Widget _showPasswordInput () {
  retourner Padding (
    remplissage: const EdgeInsets.fromLTRB (0.0, 15.0, 0.0, 0.0),
    child: new TextFormField (
      maxLines: 1,
      obscureText: true,
      autofocus: faux,
      décoration: nouvelle InputDecoration (
          hintText: 'Mot de passe',
          icon: nouvelle icône (
            Icons.lock,
            couleur: Colors.grey,
          )),
      validateur: (valeur) => valeur.isEmpty? 'Le mot de passe ne peut pas être vide': null,
      onSaved: (value) => _password = value.trim (),
    ),
  )
}

Ensuite, nous devons ajouter le bouton principal mais il devrait pouvoir afficher le texte correct selon que l'utilisateur souhaite créer un nouveau compte ou se connecter avec un compte existant. Pour cela, nous devons créer une énumération afin de savoir si le formulaire sert à la connexion ou à l'inscription.

enum FormMode {LOGIN, SIGNUP}

Nous attribuerons une méthode à la fonction de rappel du bouton. Pour cela, nous allons créer une méthode appelée _validateAndSubmit qui passera à la fois par email et par mot de passe pour l'authentification Firebase. Plus sur cela plus tard dans ce post.

Widget _showPrimaryButton () {
  retourne un nouveau Padding (
      remplissage: EdgeInsets.from LTRB (0.0, 45.0, 0.0, 0.0),
      child: new MaterialButton (
        altitude: 5.0,
        largeur minimale: 200.0,
        hauteur: 42,0
        couleur: Colors.blue,
        enfant: _formMode == FormMode.LOGIN
            ? nouveau texte ('Login',
                style: new TextStyle (fontSize: 20.0, color: Colors.white))
            : nouveau texte ('Créer un compte',
                style: new TextStyle (fontSize: 20.0, color: Colors.white)),
        onPressed: _validateAndSubmit,
      ));
}

Nous devons maintenant ajouter un bouton secondaire pour que l’utilisateur puisse basculer entre le formulaire d’inscription et le formulaire de connexion. Sur la méthode onPressed, nous aimerions basculer l'état du formulaire entre LOGIN et SIGNUP. Remarquez pour le bouton secondaire, nous utilisons FlatButton au lieu de RaisedButton comme le bouton de soumission précédent. La raison en est que si vous avez 2 boutons et que vous souhaitez en créer un plus distinctif, RaisedButton est le bon choix car il attire immédiatement l’attention des utilisateurs par rapport à FlatButton.

login_page.dart

Widget _showSecondaryButton () {
  retourne un nouveau FlatButton (
    enfant: _formMode == FormMode.LOGIN
        ? new Text ('Créer un compte',
            style: new TextStyle (fontSize: 18.0, fontWeight: FontWeight.w300))
        : new Text ('Vous avez un compte? Connectez-vous',
            style:
                new TextStyle (fontSize: 18.0, fontWeight: FontWeight.w300)),
    onPressed: _formMode == FormMode.LOGIN
        ? _changeFormToSignUp
        : _changeFormToLogin,
  )
}

Sur la méthode pour basculer en mode formulaire, il est crucial de l'envelopper autour de setState car nous devons dire à Flutter de rendre à nouveau l'écran avec la valeur mise à jour du FormMode.

void _changeFormToSignUp () {
  _formKey.currentState.reset ();
  _errorMessage = "";
  setState (() {
    _formMode = FormMode.SIGNUP;
  });
}

void _changeFormToLogin () {
  _formKey.currentState.reset ();
  _errorMessage = "";
  setState (() {
    _formMode = FormMode.LOGIN;
  });
}

Ensuite, nous allons avoir un _showErrorMessage () qui transmettra le message d'erreur à l'utilisateur du côté de Firebase lorsqu'ils essaieront de se connecter ou de s'inscrire. Ce message d'erreur pourrait être quelque chose comme: «Il existe déjà un compte d'utilisateur». Nous allons donc avoir un String _errorMessage pour stocker le message d'erreur de Firebase.

Widget _showErrorMessage () {
  if (_errorMessage.length> 0 && _errorMessage! = null) {
    renvoyer un nouveau texte (
      _Message d'erreur,
      style: TextStyle (
          fontSize: 13.0,
          couleur: Colors.red,
          hauteur: 1.0,
          fontWeight: FontWeight.w300),
    )
  } autre {
    retourne le nouveau conteneur (
      hauteur: 0.0,
    )
  }
}

Enfin, organisons ces composants d’interface utilisateur individuels et remettons-les à notre liste.

Widget _showBody () {
  retourne le nouveau conteneur (
      remplissage: EdgeInsets.all (16.0),
      enfant: nouveau formulaire (
        clé: _formKey,
        child: new ListView (
          shrinkWrap: true,
          enfants:  [
            _showLogo (),
            _showEmailInput (),
            _showPasswordInput (),
            _showPrimaryButton (),
            _showSecondaryButton (),
            _showErrorMessage (),
          ],
        ),
      ));
}
Validateur TextFormField en action

Etape 6: Enregistrer un nouveau projet avec Firebase

Accédez à la page https://console.firebase.google.com et enregistrez un nouveau projet.

Pour Android, cliquez sur l'icône Android. Entrez votre nom de package qui peut être trouvé dans android / app / src / main / AndroidManifest.xml

Téléchargez le fichier de configuration qui est google-services.json (Android).

Faites glisser le fichier google-services.json dans le dossier de l'application en mode projet

Nous devons ajouter le plugin Google Services Gradle pour lire google-services.json. Dans /android/app/build.gradle, ajoutez ce qui suit à la dernière ligne du fichier.

appliquer le plugin: 'com.google.gms.google-services'

Dans android / build.gradle, dans la balise buildscript, ajoutez une nouvelle dépendance.

buildscript {
   référentiels {
      // ...
}
dépendances {
   // ...
   classpath 'com.google.gms: google-services: 3.2.1'
}

Pour iOS, ouvrez ios / Runner.xcworkspace pour lancer Xcode. Le nom du paquet peut être trouvé dans l'identifiant de paquet dans la vue Runner.

Téléchargez le fichier de configuration GoogleService-info.plist (iOS).

Faites glisser GoogleService-info.plist dans le sous-dossier Runner de Runner, comme indiqué ci-dessous.

Etape 7: Ajouter des dépendances dans pubspec.yaml
Ensuite, nous devons ajouter la dépendance firebase_auth dans pubspec.yaml. Pour obtenir le numéro de version le plus récent, rendez-vous sur https://pub.dartlang.org/ et recherchez firebase auth.

firebase_auth: ^ 0.6.6

Etape 8: Importer une autorisation Firebase

importer 'package: firebase_auth / firebase_auth.dart';

Etape 9: Activer l'inscription à l'aide d'un email et d'un mot de passe sur Firebase

Etape 10: connexion à Firebase

Firebase signInWithEmailAndPassword est une méthode qui renvoie une valeur future. Par conséquent, la méthode doit avoir attendu et la fonction wrapper externe doit avoir async. Nous joignons donc les méthodes de connexion et d’inscription à try block. En cas d'erreur, notre bloc catch devrait pouvoir capturer le message d'erreur et l'afficher à l'utilisateur.

Il y a une différence dans la manière dont le message réel est stocké dans l'erreur renvoyée par Firebase. Dans IOS, le message est dans e.details alors que pour Android, dans e.message. Vous pouvez facilement vérifier la plate-forme en utilisant _isIos = Theme.of (context) .platform == TargetPlatform.iOS et il devrait figurer dans l'une des méthodes du widget de génération car il nécessite un contexte.

_validateAndSubmit () async {
  setState (() {
    _errorMessage = "";
    _isLoading = true;
  });
  if (_validateAndSave ()) {
    String userId = "";
    essayer {
      if (_formMode == FormMode.LOGIN) {
        userId = wait widget.auth.signIn (_email, _password);
        print ('Connecté dans: $ userId');
      } autre {
        userId = wait widget.auth.signUp (_email, _password);
        print ('Utilisateur inscrit: $ userId');
      }
      if (userId.length> 0 && userId! = null) {
        widget.onSignedIn ();
      }
    } catch (e) {
      print ('Erreur: $ e');
      setState (() {
        _isLoading = false;
        si (_isIos) {
          _errorMessage = e.details;
        } autre
          _errorMessage = e.message;
      });
    }
  }
}

Etape 11: Effacer le champ du formulaire lors du basculement

Nous devons ajouter la ligne suivante dans _changeFormToSignUp et _changeFormToLogin pour réinitialiser le champ du formulaire à chaque fois que l'utilisateur bascule entre le formulaire de connexion et le formulaire d'inscription.

formKey.currentState.reset ();

Etape 12: essayez d'inscrire un utilisateur

Essayons d’inscrire un utilisateur en entrant un email et un mot de passe.

Si vous rencontrez quelque chose comme ci-dessous, c'est qu'il y a un espacement supplémentaire à la fin de votre courrier électronique.
I / flutter (14294): Erreur PlatformException (exception, l'adresse électronique est mal formatée., Null)
Si vous rencontrez quelque chose comme ci-dessous, changez votre mot de passe pour qu'il comporte au moins 6 caractères.
I / flutter (14294): Erreur PlatformException (exception, le mot de passe fourni n'est pas valide. [Le mot de passe doit comporter au moins 6 caractères], null)

Enfin, une fois le succès obtenu, vous devriez pouvoir voir dans votre terminal la ligne suivante. La chaîne aléatoire est l'ID utilisateur.

I / flutter (14294): inscrit JSwpKsCFxPZHEqeuIO4axCsmWuP2

De même, si nous essayons de nous connecter au même utilisateur que nous, nous devrions obtenir quelque chose comme ceci:

I / flutter (14294): signé dans JSwpKsCFxPZHEqeuIO4axCsmWuP2

Etape 13: implémenter la classe Auth

Créer un nouveau fichier, appelé authentication.dart. Nous allons également implémenter la classe abstraite BaseAuth. Le but de cette classe abstraite est qu’elle agit comme une couche intermédiaire entre nos composants d’interface utilisateur et la classe d’implémentation réelle, qui dépend du cadre que nous avons choisi. Dans tous les cas, nous avons décidé de permuter Firebase à quelque chose comme PostgreSQL, cela n’aurait alors aucun impact sur les composants de l’UI.

importer 'dart: async';
importer 'package: firebase_auth / firebase_auth.dart';

classe abstraite BaseAuth {
  Future  signIn (chaîne email, mot de passe chaîne);
  Future  signUp (Chaîne email, Mot de passe Chaîne);
  Future  getCurrentUser ();
  Future  signOut ();
}

La classe Auth implémente BaseAuth {
  FirebaseAuth final _firebaseAuth = FirebaseAuth.instance;

  Connexion future  (email String, mot de passe String) async {
    FirebaseUser user = wait _firebaseAuth.signInWithEmailAndPassword (email: email, mot de passe: mot de passe);
    return user.uid;
  }

  Future  signUp (Chaîne email, Mot de passe Chaîne) async {
    FirebaseUser user = wait _firebaseAuth.createUserWithEmailAndPassword (email: email, mot de passe: mot de passe);
    return user.uid;
  }

  Future  getCurrentUser () async {
    FirebaseUser user = wait _firebaseAuth.currentUser ();
    return user.uid;
  }

  Future  signOut () async {
    return _firebaseAuth.signOut ();
  }
}

Dans login_page.dart

class LoginSignUpPage étend StatefulWidget {
LoginSignUpPage ({this.auth});
final BaseAuth auth;
@passer outre
Etat  createState () => new _LoginPageState ();
}

Dans main.dart

home: new LoginSignUpPage (auth: nouvelle Auth ())

De retour dans login_page.dart, permutons notre signature signInWithEmailAndPassword

String userId = wait widget.auth.signIn (_email, _password);
String userId = wait widget.auth.signUp (_email, _password);

Etape 14: Racine et maison avec VoidCallback

Créons un nouveau fichier appelé home_page.dart. Cela affichera vide à faire la liste après que l'utilisateur s'est connecté ou enregistré avec succès. Comme d'habitude, nous implémentons Scaffold avec AppBar mais cette fois, nous allons avoir un FlatButton dans AppBar pour la fonction de déconnexion. Cette déconnexion appelle la méthode de déconnexion Firebase dans la classe BaseAuth.

Nous devons également créer un fichier appelé root_page.dart. Cela remplacera home: LoginSignUpPage (auth: new Auth ()) dans notre main.dart.

home: new RootPage (auth: new Auth ())

Lorsque l'application démarre, il convient de naviguer vers cette page. Cette page agit en tant que gestionnaire pour vérifier l'ID utilisateur Firebase valide et les dirige vers la page appropriée en fonction. Par exemple, si l'ID utilisateur est présent, cela signifie que l'utilisateur est déjà connecté et que la page home_page doit être affichée à la place de la page login_signup_page. Cela sera fait dans initState qui est la fonction qui sera exécutée en premier dans le fichier.

Dans la root_page, il y aura 2 méthodes qui sont _onLoggedIn et _onSignedOut. Dans _onLoggedIn, nous essayons d'obtenir l'ID utilisateur et setstate authStatus à l'utilisateur est déjà connecté. Dans _onSignedOut, nous effaçons l'identifiant utilisateur stocké et setstate authStatus à l'utilisateur n'est pas connecté.

Dans la root_page, nous passons 2 paramètres dans login_page, l’une est la classe Auth que nous implémentons plus facilement (nous l’instancions dans main.dart) et la méthode _onLoggedIn). Dans la page login_signup_page, nous créons 2 variables qui sont auth de type BaseAuth et onSignedIn de type VoidCallback. Nous pouvons facilement récupérer les 2 paramètres passés dans login_signup_page dans nos variables locales en utilisant la ligne suivante.

LoginSignUpPage ({this.auth, this.onSignedIn});

final BaseAuth auth;
final VoidCallback onSignedIn;

VoidCallback permet à login_signup_page d'appeler la méthode située dans root_page, qui est _onSignedIn lorsque l'utilisateur se connecte. Lorsque _onSignedIn est appelé, il définit l'authStatus sur LOGGED_IN et setState pour redessiner l'application. Lorsque l'application est redessinée, initState vérifie l'authStatus et, comme il s'agit de LOGGED_IN, il affichera home_page, en passant auth et voidcallback de _signOut.

root_page.dart

@passer outre
Construction du widget (contexte BuildContext) {
  commutateur (authStatus) {
    case AuthStatus.NOT_DETERMINED:
      return _buildWaitingScreen ();
      Pause;
    case AuthStatus.NOT_LOGGED_IN:
      retourne une nouvelle LoginSignUpPage (
        auth: widget.auth,
        onSignedIn: _onLoggedIn,
      )
      Pause;
    case AuthStatus.LOGGED_IN:
      if (_userId.length> 0 && _userId! = null) {
        retourne la nouvelle page d'accueil (
          userId: _userId,
          auth: widget.auth,
          onSignedOut: _onSignedOut,
        )
      } else return _buildWaitingScreen ();
      Pause;
    défaut:
      return _buildWaitingScreen ();
  }
}

Notez le ruban de débogage dans le coin supérieur droit de l'application. Vous pouvez facilement le supprimer en ajoutant la ligne suivante à l'intérieur du widget MaterialApp dans main.dart.

Écran de connexion de démonstration
debugShowCheckedModeBanner: false,
Bannière de débogage supprimée

Vous pouvez obtenir le code source complet dans le lien github ci-dessous

Si vous trouvez cet article utile, donnez

Référence:

Le Flutter Pub est une publication de taille moyenne qui vous apporte les ressources les plus récentes et les plus étonnantes, telles que des articles, des vidéos, des codes, des podcasts, etc., sur cette technologie formidable qui vous apprendra à créer de belles applications avec. Vous pouvez nous trouver sur Facebook, Twitter et Medium ou en savoir plus sur nous ici. Nous aimerions nous connecter! Et si vous êtes un écrivain intéressé à écrire pour nous, vous pouvez le faire grâce à ces directives.