firebase - 在Firebase Authenticator Flutter之前验证用户输入

标签 firebase flutter dart flutter-layout

我想验证用户输入(应为电话号码)是否匹配以下正则表达式:r'^(?:[+]316)?[0-9]{8}$'

我做了一个函数来执行此操作,但是我的代码似乎首先与 Controller (这是Firebase身份验证器)一起使用,因此未在TextFormField中执行验证器。 Controller 在我的终端内返回一条打印语句,但我想向用户显示一条错误消息,然后首先由Firebase处理电话号码。任何帮助将不胜感激!

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:percent_indicator/percent_indicator.dart';
import 'package:firebase_auth/firebase_auth.dart';


void main() {
  runApp(MaterialApp(
    theme:
    ThemeData(accentColor: Colors.black87),
    home: NextPage(),
  ));
}

class NextPage extends StatefulWidget {
  final String value;

  NextPage({Key key, this.value}) : super(key: key);

  @override
  _NextPageState createState() => new _NextPageState();
}

class _NextPageState extends State<NextPage> {

  var _formKey = GlobalKey<FormFieldState>();

  TextEditingController _smsCodeController = TextEditingController();
  TextEditingController _phoneNumberController = TextEditingController();
  String verificationId;

  /// Sends the code to the specified phone number.
  Future<void> _sendCodeToPhoneNumber() async {
    final PhoneVerificationCompleted verificationCompleted = (AuthCredential phoneAuthCredential) {
      setState(() {
        print('Inside _sendCodeToPhoneNumber: signInWithPhoneNumber auto succeeded: user');
      });
    };

    // TODO: Below function works but user needs to see an alert box or something
    final PhoneVerificationFailed verificationFailed = (AuthException authException) {
      setState(() {
        print('Phone number verification failed. Code: ${authException.code}. Message: ${authException.message}');}
      );
    };

    final PhoneCodeSent codeSent =
        (String verificationId, [int forceResendingToken]) {
      this.verificationId = verificationId;
      smsCodeDialog(context).then((value) => print("Signed In"));
    };

    final PhoneCodeAutoRetrievalTimeout codeAutoRetrievalTimeout =
        (String verificationId) {
      this.verificationId = verificationId;
      print("time out");
    };

    await FirebaseAuth.instance.verifyPhoneNumber(
        phoneNumber: _phoneNumberController.text,
        timeout: const Duration(seconds: 5),
        verificationCompleted: verificationCompleted,
        verificationFailed: verificationFailed,
        codeSent: codeSent,
        codeAutoRetrievalTimeout: codeAutoRetrievalTimeout);
  }

// TODO: adjust below function
  void _signInWithPhoneNumber(String smsCode) async {
    final AuthCredential credential = PhoneAuthProvider.getCredential(
      verificationId: verificationId,
      smsCode: smsCode,
    );
    final FirebaseUser user = (await FirebaseAuth.instance.signInWithCredential(credential)).user;

    if(user!=null){
      if (_formKey.currentState.validate()) {
        Navigator.push(
          context,
          MaterialPageRoute(builder: (context) => ThirdRoute()),
        );
      }
    }else{
      showDialog(
        context: context,
        builder: (BuildContext context) {
          // return object of type Dialog
          return AlertDialog(
            title: new Text("Alert Dialog title"),
            content: new Text("Alert Dialog body"),
            actions: <Widget>[
              // usually buttons at the bottom of the dialog
              new FlatButton(
                child: new Text("Close"),
                onPressed: () {
                  Navigator.of(context).pop();
                },
              ),
            ],
          );
        },
      );
    }
    _smsCodeController.text = '';
  }

  Future<bool> smsCodeDialog(BuildContext context) {
    return showDialog(
        context: context,
        barrierDismissible: false,
        builder: (BuildContext context) {
          return AlertDialog(
            title: Text("Enter Verification Code"),
            content: TextField(
              style: TextStyle(
                color: Colors.black87,
                fontWeight: FontWeight.bold,
                fontSize: 16.0
              ),
              onChanged: (value) {
                this._smsCodeController.text = value;
              },
            ),
            contentPadding: EdgeInsets.all(10.0),
            actions: <Widget>[
              FlatButton(
                child: Text("Verify",
                  style: TextStyle(
                    fontSize: 20.0,
                    fontWeight: FontWeight.bold
                  ),
                ),
                onPressed: () => _signInWithPhoneNumber(_smsCodeController.text)
              )
            ],
          );
        }
    );
  }

  String telephoneValidator (String value) {
    Pattern pattern = r'^(?:[+]316)?[0-9]{8}$';
    RegExp regex = new RegExp(pattern);
    if (!regex.hasMatch(value)) {
      return 'Invalid phone number';
    } else {
      return null;
    }
  }

  @override
  Widget build(BuildContext context) {

//    Pattern pattern = r'^(?:[+]316)?[0-9]{8}$';
//    RegExp regex = new RegExp(pattern);

    return Scaffold(
      body: Stack(
        fit: StackFit.expand,
        children: <Widget>[
          Container(
            decoration: BoxDecoration(
                color: Color.fromRGBO(53, 73, 94, 0.9)),
          ),
          Positioned(
            top: 0.0,
            left: 0.0,
            right: 0.0,
            child: AppBar(
              backgroundColor: Colors.transparent,
              elevation: 0.0,
            ),
          ),

          Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              Padding(
                padding: EdgeInsets.symmetric(vertical: 50.0),
              ),
              Padding(
                padding: EdgeInsets.fromLTRB(20.0,16.0,0.0,0.0), // left, top, right, bottom
                child: LinearPercentIndicator(
                  width: MediaQuery.of(context).size.width - 50,
                  animation: true,
                  lineHeight: 20.0,
                  animationDuration: 2000,
                  percent: 0.50,
                  center: Text("50.0%"),
                  linearStrokeCap: LinearStrokeCap.roundAll,
                  progressColor: Colors.lightBlueAccent,
                ),
              ),
              Padding(
                padding: EdgeInsets.fromLTRB(20.0,16.0,0.0,0.0),
                child: Text('Hi ${widget.value}!\nWhat is your\nmobile number?'.trim(),
                  style: TextStyle(
                      fontSize: 35.0,
                      color: Colors.white,
                      fontWeight: FontWeight.w400),
                ),
              ),
              Padding(
                padding: EdgeInsets.fromLTRB(20.0,12.0,0.0,0.0),
                child: Text("We'll send you a verification code by text message\n"
                    "so you can confirm that it's really you".trim(),
                  style: TextStyle(
                      fontSize: 16.0,
                      color: Colors.white,
                      fontWeight: FontWeight.w400),
                ),
              ),
              Padding(
                padding: EdgeInsets.fromLTRB(20.0,24.0,0.0,12.0),
                child: TextFormField(
                  key: _formKey, // TODO: _formKey validation in onPressed()
                  maxLines: 1,
                  maxLength: 14,
                  style: TextStyle(
                      fontSize: 35.0,
                      color: Colors.black87,
                      fontWeight: FontWeight.bold
                  ),
                  decoration: InputDecoration(
                    hintText: "e.g. +31612345678",
                    border: InputBorder.none,
                  ),
                  controller: _phoneNumberController,
                  validator: telephoneValidator
                ),
              ),
            ],
          ),

          Positioned(
            bottom: 150.0,
            right: 20.0,
            child: ButtonTheme(
              minWidth: 150.0,
              child: RaisedButton(
                  padding: EdgeInsets.all(8.0),
                  child: Text('Send',
                    style: TextStyle(
                        fontSize: 24,
                        color: Colors.black87,
                        fontWeight: FontWeight.bold
                    ),
                  ),
                  shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(18.0)
                  ),
                  color: Colors.white,
                  splashColor: Colors.blueGrey,
                  onPressed: () => _sendCodeToPhoneNumber()
              ),
            ),
          ),
        ],
      ),
    );
  }

}

最佳答案

当用户按下按钮时,请执行以下操作

   onPressed: () {
                 if (_formKey.currentState.validate()) {
                                              _formKey.currentState.save();

                                             //do the firebase stuff here
                                          },

关于firebase - 在Firebase Authenticator Flutter之前验证用户输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58889694/

相关文章:

java.lang.IllegalStateException : Default FirebaseApp is not initialized in this process

android - 为什么我的 Flutter 应用的 ListView 滚动不如 Flutter Gallery 应用流畅?

firebase - 从 flutter 应用程序中的 fireStore 获取带有索引的列表

flutter - 需要帮助在 Flutter 中导入自定义图标

dart - 如果我完全不熟悉编程,如何开始使用 Google Dart?

android - Firebase runTransaction 不工作 - MutableData 为空

java - 从 firebase 检索数据时出现空指针异常

firebase - 导入 JSON 时如何绕过 Firebase 自动添加 ID

flutter - 如何访问容器中具有字符串,整数和图像的列表(数组)

dart - 找不到引用的源 : package:unittest/unittest. dart