【问题标题】:how to add CircularProgressIndicator using provider with firebase如何使用带有 firebase 的提供程序添加 CircularProgressIndicator
【发布时间】:2021-11-13 18:22:09
【问题描述】:

我使用provider 使用provider 完成flutter firebasegoogle code lab 封装所有工作正常,如codelab 中所述我喜欢他们设计Authentication 小部件从中传递函数的方式,在下面的代码中我想添加CircularProgressIndicator等待状态,我不明白我在哪里添加条件 isLoading 等于 true 然后 wait 否则 dosomething 函数通过 Authentication 小部件传递。

ma​​in.dart

import 'package:firebase_core/firebase_core.dart'; // new
import 'package:firebase_auth/firebase_auth.dart'; // new
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:provider/provider.dart'; // new

import 'src/authentication.dart'; // new
import 'src/widgets.dart';

void main() {
  // Modify from here
  runApp(
    ChangeNotifierProvider(
      create: (context) => ApplicationState(),
      builder: (context, _) => App(),
    ),
  );
  // to here.
}

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Firebase Meetup',
      theme: ThemeData(
        buttonTheme: Theme.of(context).buttonTheme.copyWith(
              highlightColor: Colors.deepPurple,
            ),
        primarySwatch: Colors.deepPurple,
        textTheme: GoogleFonts.robotoTextTheme(
          Theme.of(context).textTheme,
        ),
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  HomePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Firebase Meetup'),
      ),
      body: ListView(
        children: <Widget>[
          Image.asset('assets/codelab.png'),
          SizedBox(height: 8),
          IconAndDetail(Icons.calendar_today, 'October 30'),
          IconAndDetail(Icons.location_city, 'San Francisco'),
          // Add from here
          Consumer<ApplicationState>(
            builder: (context, appState, _) => Authentication(
              email: appState.email,
              loginState: appState.loginState,
              startLoginFlow: appState.startLoginFlow,
              verifyEmail: appState.verifyEmail,
              signInWithEmailAndPassword: appState.signInWithEmailAndPassword,
              cancelRegistration: appState.cancelRegistration,
              registerAccount: appState.registerAccount,
              signOut: appState.signOut,
            ),
          ),
          // to here
          Divider(
            height: 8,
            thickness: 1,
            indent: 8,
            endIndent: 8,
            color: Colors.grey,
          ),
          Header("What we'll be doing"),
          Paragraph(
            'Join us for a day full of Firebase Workshops and Pizza!',
          ),
        ],
      ),
    );
  }
}

class ApplicationState extends ChangeNotifier {
  ApplicationState() {
    init();
  }

  Future<void> init() async {
    await Firebase.initializeApp();

    FirebaseAuth.instance.userChanges().listen((user) {
      if (user != null) {
        _loginState = ApplicationLoginState.loggedIn;
      } else {
        _loginState = ApplicationLoginState.loggedOut;
      }
      notifyListeners();
    });
  }

  ApplicationLoginState _loginState = ApplicationLoginState.loggedOut;
  ApplicationLoginState get loginState => _loginState;

  String? _email;
  String? get email => _email;

  void startLoginFlow() {
    _loginState = ApplicationLoginState.emailAddress;
    notifyListeners();
  }

  void verifyEmail(
    String email,
    void Function(FirebaseAuthException e) errorCallback,
  ) async {
    try {
      var methods = await FirebaseAuth.instance.fetchSignInMethodsForEmail(email);
      if (methods.contains('password')) {
        _loginState = ApplicationLoginState.password;
      } else {
        _loginState = ApplicationLoginState.register;
      }
      _email = email;
      notifyListeners();
    } on FirebaseAuthException catch (e) {
      errorCallback(e);
    }
  }

  void signInWithEmailAndPassword(
    String email,
    String password,
    void Function(FirebaseAuthException e) errorCallback,
  ) async {
    try {
      await FirebaseAuth.instance.signInWithEmailAndPassword(
        email: email,
        password: password,
      );
    } on FirebaseAuthException catch (e) {
      errorCallback(e);
    }
  }

  void cancelRegistration() {
    _loginState = ApplicationLoginState.emailAddress;
    notifyListeners();
  }

  void registerAccount(String email, String displayName, String password,
      void Function(FirebaseAuthException e) errorCallback) async {
    try {
      var credential = await FirebaseAuth.instance
          .createUserWithEmailAndPassword(email: email, password: password);
      await credential.user!.updateProfile(displayName: displayName);
    } on FirebaseAuthException catch (e) {
      errorCallback(e);
    }
  }

  void signOut() {
    FirebaseAuth.instance.signOut();

    /// here is not notifylistener();
  }
}

authentication.dart

import 'package:flutter/material.dart';

import 'widgets.dart';

enum ApplicationLoginState {
  loggedOut,
  emailAddress,
  register,
  password,
  loggedIn,
}

class Authentication extends StatelessWidget {
  const Authentication({
    required this.loginState,
    required this.email,
    required this.startLoginFlow,
    required this.verifyEmail,
    required this.signInWithEmailAndPassword,
    required this.cancelRegistration,
    required this.registerAccount,
    required this.signOut,
  });

  final ApplicationLoginState loginState;
  final String? email;
  final void Function() startLoginFlow;
  final void Function(
    String email,
    void Function(Exception e) error,
  ) verifyEmail;
  final void Function(
    String email,
    String password,
    void Function(Exception e) error,
  ) signInWithEmailAndPassword;
  final void Function() cancelRegistration;
  final void Function(
    String email,
    String displayName,
    String password,
    void Function(Exception e) error,
  ) registerAccount;
  final void Function() signOut;

  @override
  Widget build(BuildContext context) {
    switch (loginState) {
      case ApplicationLoginState.loggedOut:
        return Row(
          children: [
            Padding(
              padding: const EdgeInsets.only(left: 24, bottom: 8),
              child: StyledButton(
                onPressed: () {
                  startLoginFlow();
                },
                child: const Text('RSVP'),
              ),
            ),
          ],
        );
      case ApplicationLoginState.emailAddress:
        return EmailForm(
            callback: (email) =>
                verifyEmail(email, (e) => _showErrorDialog(context, 'Invalid email', e)));
      case ApplicationLoginState.password:
        return PasswordForm(
          email: email!,
          login: (email, password) {
            print("CONTEXT $context");
            signInWithEmailAndPassword(
                email, password, (e) => _showErrorDialog(context, 'Failed to sign in', e));
          },
        );
      case ApplicationLoginState.register:
        return RegisterForm(
          email: email!,
          cancel: () {
            cancelRegistration();
          },
          registerAccount: (
            email,
            displayName,
            password,
          ) {
            registerAccount(email, displayName, password,
                (e) => _showErrorDialog(context, 'Failed to create account', e));
          },
        );
      case ApplicationLoginState.loggedIn:
        return Row(
          children: [
            Padding(
              padding: const EdgeInsets.only(left: 24, bottom: 8),
              child: StyledButton(
                onPressed: () {
                  signOut();
                },
                child: const Text('LOGOUT'),
              ),
            ),
          ],
        );
      default:
        return Row(
          children: const [
            Text("Internal error, this shouldn't happen..."),
          ],
        );
    }
  }

  void _showErrorDialog(BuildContext context, String title, Exception e) {
    print("CONTEXT $context");
    showDialog<void>(
      context: context,
      builder: (context) {
        return AlertDialog(
          title: Text(
            title,
            style: const TextStyle(fontSize: 24),
          ),
          content: SingleChildScrollView(
            child: ListBody(
              children: <Widget>[
                Text(
                  '${(e as dynamic).message}',
                  style: const TextStyle(fontSize: 18),
                ),
              ],
            ),
          ),
          actions: <Widget>[
            StyledButton(
              onPressed: () {
                Navigator.of(context).pop();
              },
              child: const Text(
                'OK',
                style: TextStyle(color: Colors.deepPurple),
              ),
            ),
          ],
        );
      },
    );
  }
}

class EmailForm extends StatefulWidget {
  const EmailForm({required this.callback});
  final void Function(String email) callback;
  @override
  _EmailFormState createState() => _EmailFormState();
}

class _EmailFormState extends State<EmailForm> {
  final _formKey = GlobalKey<FormState>(debugLabel: '_EmailFormState');
  final _controller = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        const Header('Sign in with email'),
        Padding(
          padding: const EdgeInsets.all(8.0),
          child: Form(
            key: _formKey,
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 24),
                  child: TextFormField(
                    controller: _controller,
                    decoration: const InputDecoration(
                      hintText: 'Enter your email',
                    ),
                    validator: (value) {
                      if (value!.isEmpty) {
                        return 'Enter your email address to continue';
                      }
                      return null;
                    },
                  ),
                ),
                Row(
                  mainAxisAlignment: MainAxisAlignment.end,
                  children: [
                    Padding(
                      padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 30),
                      child: StyledButton(
                        onPressed: () async {
                          if (_formKey.currentState!.validate()) {
                            widget.callback(_controller.text);
                          }
                        },
                        child: const Text('NEXT'),
                      ),
                    ),
                  ],
                ),
              ],
            ),
          ),
        ),
      ],
    );
  }
}

class RegisterForm extends StatefulWidget {
  const RegisterForm({
    required this.registerAccount,
    required this.cancel,
    required this.email,
  });
  final String email;
  final void Function(String email, String displayName, String password) registerAccount;
  final void Function() cancel;
  @override
  _RegisterFormState createState() => _RegisterFormState();
}

class _RegisterFormState extends State<RegisterForm> {
  final _formKey = GlobalKey<FormState>(debugLabel: '_RegisterFormState');
  final _emailController = TextEditingController();
  final _displayNameController = TextEditingController();
  final _passwordController = TextEditingController();

  @override
  void initState() {
    super.initState();
    _emailController.text = widget.email;
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        const Header('Create account'),
        Padding(
          padding: const EdgeInsets.all(8.0),
          child: Form(
            key: _formKey,
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 24),
                  child: TextFormField(
                    controller: _emailController,
                    decoration: const InputDecoration(
                      hintText: 'Enter your email',
                    ),
                    validator: (value) {
                      if (value!.isEmpty) {
                        return 'Enter your email address to continue';
                      }
                      return null;
                    },
                  ),
                ),
                Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 24),
                  child: TextFormField(
                    controller: _displayNameController,
                    decoration: const InputDecoration(
                      hintText: 'First & last name',
                    ),
                    validator: (value) {
                      if (value!.isEmpty) {
                        return 'Enter your account name';
                      }
                      return null;
                    },
                  ),
                ),
                Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 24),
                  child: TextFormField(
                    controller: _passwordController,
                    decoration: const InputDecoration(
                      hintText: 'Password',
                    ),
                    obscureText: true,
                    validator: (value) {
                      if (value!.isEmpty) {
                        return 'Enter your password';
                      }
                      return null;
                    },
                  ),
                ),
                Padding(
                  padding: const EdgeInsets.symmetric(vertical: 16),
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.end,
                    children: [
                      TextButton(
                        onPressed: widget.cancel,
                        child: const Text('CANCEL'),
                      ),
                      const SizedBox(width: 16),
                      StyledButton(
                        onPressed: () {
                          if (_formKey.currentState!.validate()) {
                            widget.registerAccount(
                              _emailController.text,
                              _displayNameController.text,
                              _passwordController.text,
                            );
                          }
                        },
                        child: const Text('SAVE'),
                      ),
                      const SizedBox(width: 30),
                    ],
                  ),
                ),
              ],
            ),
          ),
        ),
      ],
    );
  }
}

class PasswordForm extends StatefulWidget {
  const PasswordForm({
    required this.login,
    required this.email,
  });
  final String email;
  final void Function(String email, String password) login;
  @override
  _PasswordFormState createState() => _PasswordFormState();
}

class _PasswordFormState extends State<PasswordForm> {
  final _formKey = GlobalKey<FormState>(debugLabel: '_PasswordFormState');
  final _emailController = TextEditingController();
  final _passwordController = TextEditingController();

  @override
  void initState() {
    super.initState();
    _emailController.text = widget.email;
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        const Header('Sign in'),
        Padding(
          padding: const EdgeInsets.all(8.0),
          child: Form(
            key: _formKey,
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 24),
                  child: TextFormField(
                    controller: _emailController,
                    decoration: const InputDecoration(
                      hintText: 'Enter your email',
                    ),
                    validator: (value) {
                      if (value!.isEmpty) {
                        return 'Enter your email address to continue';
                      }
                      return null;
                    },
                  ),
                ),
                Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 24),
                  child: TextFormField(
                    controller: _passwordController,
                    decoration: const InputDecoration(
                      hintText: 'Password',
                    ),
                    obscureText: true,
                    validator: (value) {
                      if (value!.isEmpty) {
                        return 'Enter your password';
                      }
                      return null;
                    },
                  ),
                ),
                Padding(
                  padding: const EdgeInsets.symmetric(vertical: 16),
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.end,
                    children: [
                      const SizedBox(width: 16),
                      StyledButton(
                        onPressed: () {
                          if (_formKey.currentState!.validate()) {
                            widget.login(
                              _emailController.text,
                              _passwordController.text,
                            );
                          }
                        },
                        child: const Text('SIGN IN'),
                      ),
                      const SizedBox(width: 30),
                    ],
                  ),
                ),
              ],
            ),
          ),
        ),
      ],
    );
  }
}

widgets.dart

import 'package:flutter/material.dart';

class Header extends StatelessWidget {
  const Header(this.heading);
  final String heading;

  @override
  Widget build(BuildContext context) => Padding(
        padding: const EdgeInsets.all(8.0),
        child: Text(
          heading,
          style: const TextStyle(fontSize: 24),
        ),
      );
}

class Paragraph extends StatelessWidget {
  const Paragraph(this.content);
  final String content;
  @override
  Widget build(BuildContext context) => Padding(
        padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
        child: Text(
          content,
          style: const TextStyle(fontSize: 18),
        ),
      );
}

class IconAndDetail extends StatelessWidget {
  const IconAndDetail(this.icon, this.detail);
  final IconData icon;
  final String detail;

  @override
  Widget build(BuildContext context) => Padding(
        padding: const EdgeInsets.all(8.0),
        child: Row(
          children: [
            Icon(icon),
            const SizedBox(width: 8),
            Text(
              detail,
              style: const TextStyle(fontSize: 18),
            )
          ],
        ),
      );
}

class StyledButton extends StatelessWidget {
  const StyledButton({required this.child, required this.onPressed});
  final Widget child;
  final void Function() onPressed;

  @override
  Widget build(BuildContext context) => OutlinedButton(
        style: OutlinedButton.styleFrom(
            side: const BorderSide(color: Colors.deepPurple)),
        onPressed: onPressed,
        child: child,
      );
}

pubspec.yaml(发布时的版本号)

 cloud_firestore: ^1.0.0 # new
  firebase_auth: ^1.0.0   # new
  google_fonts: ^2.0.0
  provider: ^5.0.0   

【问题讨论】:

    标签: firebase flutter provider


    【解决方案1】:

    我回答我的问题,您可以通过在ApplicationState 类中添加bool isLoading 变量来做到这一点,并从ApplicationState 中存在的任何方法(signInWithEmailAndPassword)在条件基础上设置其值并将isLoading 传递给@ 987654326@ 小部件并检查build 方法中的条件,例如如果isLoading 为真,则显示CircularProgressIndicator,请查看以下代码以获取更多详细信息:

    ma​​in.dart

        import 'package:firebase_core/firebase_core.dart'; // new
        import 'package:firebase_auth/firebase_auth.dart'; // new
        import 'package:flutter/material.dart';
        import 'package:google_fonts/google_fonts.dart';
        import 'package:provider/provider.dart'; // new
        
        import 'src/authentication.dart'; // new
        import 'src/widgets.dart';
        
        void main() {
          // Modify from here
          runApp(
            ChangeNotifierProvider(
              create: (context) => ApplicationState(),
              builder: (context, _) => App(),
            ),
          );
          // to here.
        }
        
        class App extends StatelessWidget {
          @override
          Widget build(BuildContext context) {
            return MaterialApp(
              title: 'Firebase Meetup',
              theme: ThemeData(
                buttonTheme: Theme.of(context).buttonTheme.copyWith(
                      highlightColor: Colors.deepPurple,
                    ),
                primarySwatch: Colors.deepPurple,
                textTheme: GoogleFonts.robotoTextTheme(
                  Theme.of(context).textTheme,
                ),
                visualDensity: VisualDensity.adaptivePlatformDensity,
              ),
              home: HomePage(),
            );
          }
        }
        
        class HomePage extends StatelessWidget {
          HomePage({Key? key}) : super(key: key);
        
          @override
          Widget build(BuildContext context) {
            return Scaffold(
              appBar: AppBar(
                title: Text('Firebase Meetup'),
              ),
              body: ListView(
                children: <Widget>[
                  Image.asset('assets/codelab.png'),
                  SizedBox(height: 8),
                  IconAndDetail(Icons.calendar_today, 'October 30'),
                  IconAndDetail(Icons.location_city, 'San Francisco'),
                  // Add from here
                  Consumer<ApplicationState>(
                    builder: (context, appState, _) => Authentication(
    isLoading: appState.isLoading,
                      email: appState.email,
                      loginState: appState.loginState,
                      startLoginFlow: appState.startLoginFlow,
                      verifyEmail: appState.verifyEmail,
                      signInWithEmailAndPassword: appState.signInWithEmailAndPassword,
                      cancelRegistration: appState.cancelRegistration,
                      registerAccount: appState.registerAccount,
                      signOut: appState.signOut,
                    ),
                  ),
                  // to here
                  Divider(
                    height: 8,
                    thickness: 1,
                    indent: 8,
                    endIndent: 8,
                    color: Colors.grey,
                  ),
                  Header("What we'll be doing"),
                  Paragraph(
                    'Join us for a day full of Firebase Workshops and Pizza!',
                  ),
                ],
              ),
            );
          }
        }
        
        class ApplicationState extends ChangeNotifier {
          ApplicationState() {
            init();
          }
        
          Future<void> init() async {
            await Firebase.initializeApp();
        
            FirebaseAuth.instance.userChanges().listen((user) {
              if (user != null) {
                _loginState = ApplicationLoginState.loggedIn;
              } else {
                _loginState = ApplicationLoginState.loggedOut;
              }
              notifyListeners();
            });
          }
        
          ApplicationLoginState _loginState = ApplicationLoginState.loggedOut;
          ApplicationLoginState get loginState => _loginState;
    bool get isLoading => _isLoading;
        
    
          String? _email;
          String? get email => _email;
    bool _isLoading = false;
        
          void startLoginFlow() {
            _loginState = ApplicationLoginState.emailAddress;
            notifyListeners();
          }
        
          void verifyEmail(
            String email,
            void Function(FirebaseAuthException e) errorCallback,
          ) async {
            try {
              var methods = await FirebaseAuth.instance.fetchSignInMethodsForEmail(email);
              if (methods.contains('password')) {
                _loginState = ApplicationLoginState.password;
              } else {
                _loginState = ApplicationLoginState.register;
              }
              _email = email;
              notifyListeners();
            } on FirebaseAuthException catch (e) {
              errorCallback(e);
            }
          }
        
          void signInWithEmailAndPassword(
            String email,
            String password,
            void Function(FirebaseAuthException e) errorCallback,
          ) async {
            try {
    if (!this.isLoading) {
            this._isLoading = true;
            notifyListeners();
          }
              await FirebaseAuth.instance.signInWithEmailAndPassword(
                email: email,
                password: password,
              );
            } on FirebaseAuthException catch (e) {
              errorCallback(e);
    this._isLoading = false;
          notifyListeners();
            }
          }
        
          void cancelRegistration() {
            _loginState = ApplicationLoginState.emailAddress;
            notifyListeners();
          }
        
          void registerAccount(String email, String displayName, String password,
              void Function(FirebaseAuthException e) errorCallback) async {
            try {
              var credential = await FirebaseAuth.instance
                  .createUserWithEmailAndPassword(email: email, password: password);
              await credential.user!.updateProfile(displayName: displayName);
            } on FirebaseAuthException catch (e) {
              errorCallback(e);
            }
          }
        
          void signOut() {
            FirebaseAuth.instance.signOut();
        
            /// here is not notifylistener();
          }
        }
    

    authentication.dart

        import 'package:flutter/material.dart';
        
        import 'widgets.dart';
        
        enum ApplicationLoginState {
          loggedOut,
          emailAddress,
          register,
          password,
          loggedIn,
        }
        
        class Authentication extends StatelessWidget {
          const Authentication({
    required this.isLoading,
            required this.loginState,
            required this.email,
            required this.startLoginFlow,
            required this.verifyEmail,
            required this.signInWithEmailAndPassword,
            required this.cancelRegistration,
            required this.registerAccount,
            required this.signOut,
          });
    
    final bool isLoading;    
          final ApplicationLoginState loginState;
          final String? email;
          final void Function() startLoginFlow;
          final void Function(
            String email,
            void Function(Exception e) error,
          ) verifyEmail;
          final void Function(
            String email,
            String password,
            void Function(Exception e) error,
          ) signInWithEmailAndPassword;
          final void Function() cancelRegistration;
          final void Function(
            String email,
            String displayName,
            String password,
            void Function(Exception e) error,
          ) registerAccount;
          final void Function() signOut;
        
          @override
          Widget build(BuildContext context) {
    if (this.isLoading) {
          return Stack(
            children: [Center(child: CircularProgressIndicator(value: null))],
          );
        }
            switch (loginState) {
              case ApplicationLoginState.loggedOut:
                return Row(
                  children: [
                    Padding(
                      padding: const EdgeInsets.only(left: 24, bottom: 8),
                      child: StyledButton(
                        onPressed: () {
                          startLoginFlow();
                        },
                        child: const Text('RSVP'),
                      ),
                    ),
                  ],
                );
              case ApplicationLoginState.emailAddress:
                return EmailForm(
                    callback: (email) =>
                        verifyEmail(email, (e) => _showErrorDialog(context, 'Invalid email', e)));
              case ApplicationLoginState.password:
                return PasswordForm(
                  email: email!,
                  login: (email, password) {
                    print("CONTEXT $context");
                    signInWithEmailAndPassword(
                        email, password, (e) => _showErrorDialog(context, 'Failed to sign in', e));
                  },
                );
              case ApplicationLoginState.register:
                return RegisterForm(
                  email: email!,
                  cancel: () {
                    cancelRegistration();
                  },
                  registerAccount: (
                    email,
                    displayName,
                    password,
                  ) {
                    registerAccount(email, displayName, password,
                        (e) => _showErrorDialog(context, 'Failed to create account', e));
                  },
                );
              case ApplicationLoginState.loggedIn:
                return Row(
                  children: [
                    Padding(
                      padding: const EdgeInsets.only(left: 24, bottom: 8),
                      child: StyledButton(
                        onPressed: () {
                          signOut();
                        },
                        child: const Text('LOGOUT'),
                      ),
                    ),
                  ],
                );
              default:
                return Row(
                  children: const [
                    Text("Internal error, this shouldn't happen..."),
                  ],
                );
            }
          }
        
          void _showErrorDialog(BuildContext context, String title, Exception e) {
            print("CONTEXT $context");
            showDialog<void>(
              context: context,
              builder: (context) {
                return AlertDialog(
                  title: Text(
                    title,
                    style: const TextStyle(fontSize: 24),
                  ),
                  content: SingleChildScrollView(
                    child: ListBody(
                      children: <Widget>[
                        Text(
                          '${(e as dynamic).message}',
                          style: const TextStyle(fontSize: 18),
                        ),
                      ],
                    ),
                  ),
                  actions: <Widget>[
                    StyledButton(
                      onPressed: () {
                        Navigator.of(context).pop();
                      },
                      child: const Text(
                        'OK',
                        style: TextStyle(color: Colors.deepPurple),
                      ),
                    ),
                  ],
                );
              },
            );
          }
        }
        
        class EmailForm extends StatefulWidget {
          const EmailForm({required this.callback});
          final void Function(String email) callback;
          @override
          _EmailFormState createState() => _EmailFormState();
        }
        
        class _EmailFormState extends State<EmailForm> {
          final _formKey = GlobalKey<FormState>(debugLabel: '_EmailFormState');
          final _controller = TextEditingController();
        
          @override
          Widget build(BuildContext context) {
            return Column(
              children: [
                const Header('Sign in with email'),
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Form(
                    key: _formKey,
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: <Widget>[
                        Padding(
                          padding: const EdgeInsets.symmetric(horizontal: 24),
                          child: TextFormField(
                            controller: _controller,
                            decoration: const InputDecoration(
                              hintText: 'Enter your email',
                            ),
                            validator: (value) {
                              if (value!.isEmpty) {
                                return 'Enter your email address to continue';
                              }
                              return null;
                            },
                          ),
                        ),
                        Row(
                          mainAxisAlignment: MainAxisAlignment.end,
                          children: [
                            Padding(
                              padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 30),
                              child: StyledButton(
                                onPressed: () async {
                                  if (_formKey.currentState!.validate()) {
                                    widget.callback(_controller.text);
                                  }
                                },
                                child: const Text('NEXT'),
                              ),
                            ),
                          ],
                        ),
                      ],
                    ),
                  ),
                ),
              ],
            );
          }
        }
        
        class RegisterForm extends StatefulWidget {
          const RegisterForm({
            required this.registerAccount,
            required this.cancel,
            required this.email,
          });
          final String email;
          final void Function(String email, String displayName, String password) registerAccount;
          final void Function() cancel;
          @override
          _RegisterFormState createState() => _RegisterFormState();
        }
        
        class _RegisterFormState extends State<RegisterForm> {
          final _formKey = GlobalKey<FormState>(debugLabel: '_RegisterFormState');
          final _emailController = TextEditingController();
          final _displayNameController = TextEditingController();
          final _passwordController = TextEditingController();
        
          @override
          void initState() {
            super.initState();
            _emailController.text = widget.email;
          }
        
          @override
          Widget build(BuildContext context) {
            return Column(
              children: [
                const Header('Create account'),
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Form(
                    key: _formKey,
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: <Widget>[
                        Padding(
                          padding: const EdgeInsets.symmetric(horizontal: 24),
                          child: TextFormField(
                            controller: _emailController,
                            decoration: const InputDecoration(
                              hintText: 'Enter your email',
                            ),
                            validator: (value) {
                              if (value!.isEmpty) {
                                return 'Enter your email address to continue';
                              }
                              return null;
                            },
                          ),
                        ),
                        Padding(
                          padding: const EdgeInsets.symmetric(horizontal: 24),
                          child: TextFormField(
                            controller: _displayNameController,
                            decoration: const InputDecoration(
                              hintText: 'First & last name',
                            ),
                            validator: (value) {
                              if (value!.isEmpty) {
                                return 'Enter your account name';
                              }
                              return null;
                            },
                          ),
                        ),
                        Padding(
                          padding: const EdgeInsets.symmetric(horizontal: 24),
                          child: TextFormField(
                            controller: _passwordController,
                            decoration: const InputDecoration(
                              hintText: 'Password',
                            ),
                            obscureText: true,
                            validator: (value) {
                              if (value!.isEmpty) {
                                return 'Enter your password';
                              }
                              return null;
                            },
                          ),
                        ),
                        Padding(
                          padding: const EdgeInsets.symmetric(vertical: 16),
                          child: Row(
                            mainAxisAlignment: MainAxisAlignment.end,
                            children: [
                              TextButton(
                                onPressed: widget.cancel,
                                child: const Text('CANCEL'),
                              ),
                              const SizedBox(width: 16),
                              StyledButton(
                                onPressed: () {
                                  if (_formKey.currentState!.validate()) {
                                    widget.registerAccount(
                                      _emailController.text,
                                      _displayNameController.text,
                                      _passwordController.text,
                                    );
                                  }
                                },
                                child: const Text('SAVE'),
                              ),
                              const SizedBox(width: 30),
                            ],
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
              ],
            );
          }
        }
        
        class PasswordForm extends StatefulWidget {
          const PasswordForm({
            required this.login,
            required this.email,
          });
          final String email;
          final void Function(String email, String password) login;
          @override
          _PasswordFormState createState() => _PasswordFormState();
        }
        
        class _PasswordFormState extends State<PasswordForm> {
          final _formKey = GlobalKey<FormState>(debugLabel: '_PasswordFormState');
          final _emailController = TextEditingController();
          final _passwordController = TextEditingController();
        
          @override
          void initState() {
            super.initState();
            _emailController.text = widget.email;
          }
        
          @override
          Widget build(BuildContext context) {
            return Column(
              children: [
                const Header('Sign in'),
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Form(
                    key: _formKey,
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: <Widget>[
                        Padding(
                          padding: const EdgeInsets.symmetric(horizontal: 24),
                          child: TextFormField(
                            controller: _emailController,
                            decoration: const InputDecoration(
                              hintText: 'Enter your email',
                            ),
                            validator: (value) {
                              if (value!.isEmpty) {
                                return 'Enter your email address to continue';
                              }
                              return null;
                            },
                          ),
                        ),
                        Padding(
                          padding: const EdgeInsets.symmetric(horizontal: 24),
                          child: TextFormField(
                            controller: _passwordController,
                            decoration: const InputDecoration(
                              hintText: 'Password',
                            ),
                            obscureText: true,
                            validator: (value) {
                              if (value!.isEmpty) {
                                return 'Enter your password';
                              }
                              return null;
                            },
                          ),
                        ),
                        Padding(
                          padding: const EdgeInsets.symmetric(vertical: 16),
                          child: Row(
                            mainAxisAlignment: MainAxisAlignment.end,
                            children: [
                              const SizedBox(width: 16),
                              StyledButton(
                                onPressed: () {
                                  if (_formKey.currentState!.validate()) {
                                    widget.login(
                                      _emailController.text,
                                      _passwordController.text,
                                    );
                                  }
                                },
                                child: const Text('SIGN IN'),
                              ),
                              const SizedBox(width: 30),
                            ],
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
              ],
            );
          }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-25
      • 2021-11-04
      • 2021-11-21
      • 1970-01-01
      • 1970-01-01
      • 2023-03-22
      • 1970-01-01
      • 2022-07-01
      相关资源
      最近更新 更多