首页 > 解决方案 > 在一个页面视图中管理多个表单验证,其中一个按下

问题描述

按下回调按钮时,我必须同时提交 4 个表单。但是,当按下此按钮时,使用 onpressed 调用的函数必须验证所有要求都在 textformfield 的字段验证中执行。我只使用一个 formkey 并使用 formkey.validate 来验证要求是否被接受,但它不起作用,我不知道如何以不同的方式尝试。

class CreateAccountPage extends StatefulWidget {
  CreateAccountPage({Key? key}) : super(key: key);

  @override
  _CreateAccountPageState createState() => _CreateAccountPageState();
}

class _CreateAccountPageState
    extends ModularState<CreateAccountPage, CreateAccountController> {
  static var _focusNode = FocusNode();
  GlobalKey<FormState> _formKey = GlobalKey<FormState>();
  bool? policy;
  int currentPage = 0;

  @override
  void initState() {
    super.initState();
    _focusNode.addListener(() {
      setState(() {});
      print('Has focus: $_focusNode.hasFocus');
    });
  }

  @override
  void dispose() {
    _focusNode.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: PageView(
        //physics: NeverScrollableScrollPhysics(),
        controller: controller.pageViewController,
        onPageChanged: (index) {
          currentPage = index;
        },
        children: [
          SafeArea(
            child: Scaffold(
              backgroundColor: AppColors.background,
              body: SingleChildScrollView(
                child: Stack(
                  children: <Widget>[
                    Positioned(
                      top: 74,
                      left: 48,
                      child: Image.asset(
                        'assets/images/logo_budget.png',
                        height: 53.85,
                        width: 100,
                      ),
                    ),
                    Positioned(
                      top: 144,
                      left: 48,
                      child: SizedBox(
                        width: 255.0,
                        height: 118.0,
                        child: Column(
                          mainAxisAlignment: MainAxisAlignment.spaceBetween,
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            Text(
                              'Bem-Vindo!',
                              style: TextStyles.h3HeadCreateAccount,
                            ),
                            Text(
                              "Por favor insira seus dados nos campos abaixo.",
                              style: TextStyles.h6HeadCreateAccount,
                            )
                          ],
                        ),
                      ),
                    ),
                    Container(
                      padding: EdgeInsets.only(top: 419, left: 48, right: 48),
                      child: Form(
                        key: formKey[0],
                        child: Column(
                          children: [
                            Padding(
                              padding: const EdgeInsets.all(16.0),
                              child: AppTextFormFieldWidget(
                                controller: controller.nameCreate,
                                hintText: 'Nome',
                                labelText: 'Nome',
                                //validator: (value) =>
                              ),
                            ),
                            Padding(
                              padding: const EdgeInsets.all(16.0),
                              child: AppTextFormFieldWidget(
                                controller: controller.emailCreate,
                                labelText: 'E-Mail',
                                hintText: 'E-Mail',
                                validator: (value) => InputValidators()
                                    .emailValidator(value ?? ""),
                              ),
                            ),
                          ],
                        ),
                      ),
                    ),
                  ],
                ),
              ),
            ),
          ),
          SafeArea(
            child: Scaffold(
              backgroundColor: AppColors.background,
              body: SingleChildScrollView(
                child: Stack(
                  children: <Widget>[
                    Positioned(
                      top: 74,
                      left: 48,
                      child: Image.asset(
                        'assets/images/logo_budget.png',
                        height: 53.85,
                        width: 100,
                      ),
                    ),
                    Positioned(
                      top: 144,
                      left: 48,
                      child: SizedBox(
                        width: 255.0,
                        height: 86.0,
                        child: Column(
                          mainAxisAlignment: MainAxisAlignment.spaceBetween,
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            Text(
                              'Bem-Vindo!',
                              style: TextStyles.h3HeadCreateAccount,
                            ),
                            Text(
                              "Mais alguns dados.",
                              style: TextStyles.h6HeadCreateAccount,
                            )
                          ],
                        ),
                      ),
                    ),
                    Container(
                      padding: EdgeInsets.only(top: 419, left: 48, right: 48),
                      child: Form(
                        key: _formKey,
                        child: Column(
                          children: [
                            Padding(
                              padding: const EdgeInsets.all(16.0),
                              child: AppTextFormFieldWidget(
                                controller: controller.telefoneCreate,
                                keyboardType: TextInputType.phone,
                                hintText: 'Telefone',
                                labelText: 'Telefone',
                                inputFormatters: [
                                  FilteringTextInputFormatter.digitsOnly,
                                  TelefoneInputFormatter(),
                                ],
                                validator: (value) => InputValidators()
                                    .emailValidator(value ?? ""),
                              ),
                            ),
                            Padding(
                              padding: const EdgeInsets.all(16.0),
                              child: AppTextFormFieldWidget(
                                controller: controller.cpfCreate,
                                labelText: 'CPF',
                                keyboardType: TextInputType.number,
                                inputFormatters: [
                                  FilteringTextInputFormatter.digitsOnly,
                                  CpfInputFormatter(),
                                ],
                                validator: (value) =>
                                    InputValidators().passwordValidator(value!),
                              ),
                            ),
                          ],
                        ),
                      ),
                    ),
                  ],
                ),
              ),
            ),
          ),
          SafeArea(
            child: Scaffold(
              backgroundColor: AppColors.background,
              body: SingleChildScrollView(
                child: Stack(
                  children: <Widget>[
                    Positioned(
                      top: 74,
                      left: 48,
                      child: Image.asset(
                        'assets/images/logo_budget.png',
                        height: 53.85,
                        width: 100,
                      ),
                    ),
                    Positioned(
                      top: 144,
                      left: 48,
                      child: SizedBox(
                        width: 255.0,
                        height: 86.0,
                        child: Column(
                          mainAxisAlignment: MainAxisAlignment.spaceBetween,
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            Text(
                              'Bem-Vindo!',
                              style: TextStyles.h3HeadCreateAccount,
                            ),
                            Text(
                              "Leia com atenção e aceite.",
                              style: TextStyles.h6HeadCreateAccount,
                            )
                          ],
                        ),
                      ),
                    ),
                    Container(
                      padding: EdgeInsets.only(top: 274, left: 27, right: 22),
                      child: Column(
                        children: [
                          Container(
                              height: 193.0,
                              width: 311.0,
                              child: Text(
                                "Lorem Ipsum neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit. Ipsum neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit. Nque porro  est qui dolorem ipsum quia dolor sit amet, , adipisci velit. Quisquam est qui dolorem ipsum.",
                                style: TextStyles.blackRoboto16400,
                              )),
                          SizedBox(
                            height: 30.0,
                          ),
                          Row(children: [
                            Container(
                              height: 48,
                              width: 48,
                              child: Radio<bool>(
                                value: policy ?? true,
                                groupValue: policy,
                                toggleable: true,
                                onChanged: (value) {
                                  setState(() {
                                    policy = value;
                                    print(policy);
                                  });
                                },
                              ),
                            ),
                            Container(
                              height: 48,
                              width: 272,
                              child: Text(
                                "Eu li e aceito os termos e condições e a Política de privacidade do budget.",
                                style: TextStyles.blackRoboto16400,
                              ),
                            )
                          ]),
                        ],
                      ),
                    ),
                  ],
                ),
              ),
            ),
          ),
          SafeArea(
            child: Scaffold(
              backgroundColor: AppColors.background,
              body: SingleChildScrollView(
                child: Stack(
                  children: <Widget>[
                    Positioned(
                      top: 74,
                      left: 48,
                      child: Image.asset(
                        'assets/images/logo_budget.png',
                        height: 53.85,
                        width: 100,
                      ),
                    ),
                    Positioned(
                      top: 144,
                      left: 48,
                      child: SizedBox(
                        width: 255.0,
                        height: 118.0,
                        child: Column(
                          mainAxisAlignment: MainAxisAlignment.spaceBetween,
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            Text(
                              'Bem-Vindo!',
                              style: TextStyles.h3HeadCreateAccount,
                            ),
                            Text(
                              "Agora crie sua senha contendo:",
                              style: TextStyles.h6HeadCreateAccount,
                            )
                          ],
                        ),
                      ),
                    ),
                    Positioned(
                      top: 320,
                      child: Container(
                        margin: EdgeInsets.only(left: 60, right: 48),
                        height: 72,
                        width: 267,
                        child: Column(
                          mainAxisAlignment: MainAxisAlignment.start,
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            Text(
                              "•  pelo menos oito caracteres",
                              style: TextStyles.blackRoboto16400,
                            ),
                            //TODO Verificar o campo com Bullet Point
                            Text(
                              "•  letras maiúscula, letras minúsculas, números e símbolos",
                              style: TextStyles.blackRoboto16400,
                            ),
                          ],
                        ),
                      ),
                    ),
                    Container(
                      padding: EdgeInsets.only(top: 419, left: 48, right: 48),
                      child: Form(
                        key: _formKey,
                        child: Column(
                          children: [
                            Padding(
                              padding: const EdgeInsets.all(16.0),
                              child: AppTextFormFieldWidget(
                                  controller: controller.passwordCreate,
                                  hintText: 'Crie uma senha',
                                  validator: (value) {
                                    InputValidators().passwordValidator(value!);
                                  }),
                            ),
                            Padding(
                              padding: const EdgeInsets.all(16.0),
                              child: AppTextFormFieldWidget(
                                  controller:
                                      controller.passwordCreateConfirmation,
                                  hintText: 'Confirme sua senha',
                                  validator: (value) {
                                    if (value !=
                                        controller.passwordCreate.text) {
                                      return "As senhas não coincidem";
                                    } else {
                                      InputValidators()
                                          .passwordValidator(value!);
                                    }
                                  }),
                            ),
                          ],
                        ),
                      ),
                    ),
                  ],
                ),
              ),
            ),
          ),
        ],
      ),
      bottomNavigationBar: Padding(
        padding: const EdgeInsets.only(bottom: 8),
        child: AnimatedBuilder(
          animation: controller.pageViewController,
          builder: (context, snapshot) {
            return Padding(
              padding: const EdgeInsets.only(left: 12),
              child: Container(
                color: Colors.white,
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: [
                    Container(
                      width: 116,
                      height: 48,
                      child: TextButton.icon(
                        icon: Icon(
                          Icons.arrow_back,
                          color: Color.fromRGBO(0, 0, 0, 0.26),
                        ),
                        label: Text(
                          "VOLTAR",
                          style: TextStyle(
                            fontStyle: FontStyle.normal,
                            fontSize: 16,
                            fontFamily: "Roboto",
                            fontWeight: FontWeight.w500,
                            letterSpacing: 0.4,
                            textBaseline: TextBaseline.alphabetic,
                            color: Color.fromRGBO(0, 0, 0, 0.26),
                          ),
                        ),
                        onPressed: () {
                          if (currentPage == 0) {
                            Modular.to.popAndPushNamed('/initial');
                          } else {
                            controller.pageViewController.previousPage(
                              duration: Duration(milliseconds: 400),
                              curve: Curves.easeInOut,
                            );
                          }
                        },
                      ),
                    ),
                    Text("${currentPage + 1}/4",
                        style: TextStyles
                            .createAccountTextStyleBottomNavigatorNumber),
                    Padding(
                      padding: const EdgeInsets.only(right: 12),
                      child: ElevatedButtonWidget(
                          mainAlign: MainAxisAlignment.spaceBetween,
                          fontSize: 14,
                          buttonText: "CONTINUAR ",
                          width: 116,
                          height: 32,
                          paddingValue: 4,
                          sufixicon: Icon(
                            Icons.arrow_forward,
                            size: 18,
                          ),
                          onpressed: () {
                            if (currentPage == 3 &&
                                _formKey.currentState!.validate() &&
                                policy == true) {
                              final user = User(
                                cpf: controller.cpfCreate.value.text,
                                name: controller.nameCreate.value.text,
                                email: controller.emailCreate.value.text,
                                password: controller.passwordCreate.value.text,
                                telephone: controller.telefoneCreate.value.text,
                                policyAccepted: policy!,
                              );

                              print(user);
                              // Modular.to.popAndPushNamed(
                              //   "create_account_module/onboard");

                            } else {
                              controller.pageViewController.nextPage(
                                duration: Duration(milliseconds: 400),
                                curve: Curves.easeInOut,
                              );
                            }
                          }),
                    )
                  ],
                ),
              ),
            );
          },
        ),
      ),
    );
  }
}

标签: flutterflutter-layoutflutter-pageviewflutter-textformfield

解决方案


_formKey 在 Widget 树中应该是唯一的。 https://api.flutter.dev/flutter/widgets/Widget/key.html

声明更多 GlobalKey() 并分配给每个 Form()


推荐阅读