传递到另一个小部件时,Flutter formKey currentstate为空

igetnqfo  于 2023-05-23  发布在  Flutter
关注(0)|答案(3)|浏览(219)

我正在尝试创建一个Textbutton小部件,它的disabled属性如下所示:

class AppTextButton extends StatelessWidget {
  final String title;
  final void Function(BuildContext context) onPress;
  final EdgeInsetsGeometry margin;
  final EdgeInsetsGeometry padding;
  final double borderRadius;
  final Color backgroundColor;
  final Image? leadingIcon;
  final Image? trailingIcon;
  final TextStyle? textStyle;
  final bool disabled;

  AppTextButton(this.title, this.onPress,
      {this.margin = const EdgeInsets.all(0),
      this.padding = const EdgeInsets.all(12),
      this.borderRadius = 0,
      this.leadingIcon,
      this.trailingIcon,
      this.textStyle,
      this.disabled = false,
      this.backgroundColor = const Color(0xFFFFFFFF)});

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: margin,
      child: TextButton(
        style: ButtonStyle(
            shape: MaterialStateProperty.all<RoundedRectangleBorder>(
                RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(borderRadius))),
            backgroundColor: MaterialStateProperty.all(backgroundColor)),
        child: Row(
          children: [
            if (this.leadingIcon != null) ...[this.leadingIcon!],
            Expanded(
              child: Padding(
                padding: padding,
                child:
                    Text(title, textAlign: TextAlign.center, style: textStyle),
              ),
            ),
            if (this.trailingIcon != null) ...[this.trailingIcon!]
          ],
        ),
        onPressed: () => !disabled ? onPress(context) : null,
      ),
    );
  }
}

在我的屏幕中,我声明了我的formKey和表单如下:

class LoginScreen extends AppBaseScreen {
  LoginScreen({Key? key}) : super(key: key);

  final _formKey = GlobalKey<FormState>();

@override
  Widget build(BuildContext context) {
              Form(
                  key: _formKey,
                  child: Obx(
                    () => AppTextInput(
                      "Please input passcode",
                      _passwordController,
                      borderRadius: 8,
                      fillColor: Color(0xFFF6F4F5),
                      keyboardType: TextInputType.number,
                      errorMessage: _c.errorLoginConfirm.value,
                      isObscure: true,
                      onChange: _onInputChange,
                      maxLength: 6,
                      margin: EdgeInsets.only(top: 12, left: 20, right: 20),
                      validator: (text) {
                        if (text != null && text.length > 0) {
                          if (text.length < 6) {
                            return "Passcode must have at least 6 digits";
                          }
                        }
                      },
                    ),
                  )),

我将在屏幕底部有一个按钮,我在禁用字段中传递!_formKey.currentState!.validate()

AppTextButton("Login", _onLogin,
                  margin: EdgeInsets.fromLTRB(24, 24, 24, 8),
                  backgroundColor: Color(0xFFFF353C),
                  disabled: !_formKey.currentState!.validate(),
                  textStyle: TextStyle(color: Colors.white),
                  borderRadius: 8),

但是,formKey.currentState为null,并且每次打开屏幕时都会抛出以下错误。Null check operator used on a null value
我做错了什么?感谢您的评分

hm2xizp9

hm2xizp91#

传递之前需要保存表单状态,

final FormState formState = _formKey.currentState;
formState.save();

onPressed: () {
                FocusScope.of(context).requestFocus(FocusNode());
                final FormState formState = _formKey.currentState;
                if (formState.validate()) {
                  formState.save();
                  onPress(context);
                }
              },
nwnhqdif

nwnhqdif2#

我认为这个问题是因为所有的小部件都是同时创建的,所以当AppTextButton调用它时,_formKey.currentState仍然是null。
您需要创建一个单独的控制器来控制按钮的状态,并将其添加到验证器中,如下所示:

validator: (text) {

                     if (text != null && text.length > 0) {
                        if (text.length < 6) {
                           buttonDisableController = true;
                           return "Passcode must have at least 6 digits";
                        }
                     }
                     buttonDisableController = false;
                     return null;
                  },
xnifntxz

xnifntxz3#

在你的例子中,你应该知道小部件是如何构建的(假设你有Botton小部件和Input小部件):

  1. BottonInput是构建初始状态。这两种状态都尚未准备好读取和使用
    1.构建了BottonInput。各国准备阅读。
    1.用户与Input交互。如果值通过验证程序,则Input必须调用Button来重建其状态
  2. Botton重建。
    对于这个过程,你应该像这样修改代码:
    1.在Input中获取并修改Button的状态
    1.通知Button重建
    有很多方法可以处理小部件之间的state management。我只是将AppTextButton更改为Statefultwidget来实现它。
...
final _buttonKey = GlobalKey<_AppTextButtonState>();
...
  AppTextButton(key: _buttonKey)
...

class AppTextButton extends StatefulWidget {
  final bool initDisable;

  AppTextButton({
    this.initDisable = false,
    Key? key,
  }) : super(key: key);

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

class _AppTextButtonState extends State<AppTextButton> {
  var disable;

  @override
  void initState() {
    disable = widget.initDisable;
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return TextButton(child: Text('Button'), onPressed: disable ? null : () {});
  }

  void enableButton() {
    setState(() {
      disable = false;
    });
  }

  void disableButton() {
    setState(() {
      disable = true;
    });
  }
}

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

  final _formKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    return Form(
      key: _formKey,
      child: TextFormField(
        autovalidateMode: AutovalidateMode.onUserInteraction,
        validator: (text) {
          if (text != null && text.length > 0) {
            if (text.length < 6) {
              return "Passcode must have at least 6 digits";
            }
          }
        },
        onChanged: (v) {
          if (_formKey.currentState?.validate() ?? false) {
            _buttonKey.currentState?.enableButton();
          } else {
            _buttonKey.currentState?.disableButton();
          }
        },
      ),
    );
  }
}

相关问题