【问题标题】:Flutter Enable/Disable Button based on TextFormField content基于 TextFormField 内容的 Flutter Enable/Disable Button
【发布时间】:2019-05-26 14:45:25
【问题描述】:

如何根据 TextFormField 的内容激活/停用按钮?

如果 TextFormField 输入了 10 个数字(如果它是手机号码),我想确保用户只能按下按钮 X。

谢谢!

【问题讨论】:

    标签: button keyboard flutter textfield flutter-layout


    【解决方案1】:

    一种简单的方法是将 TextFormField 的 autovalidate 属性设置为 true。这将自动检测 TextFormField 小部件上的更改。然后,我们可以尝试检查 TextFormField 的值是否在验证器属性上具有 10 个字符的字符串长度。之后我们可以调用 setState 来启用或禁用我们的按钮(在这个例子中我使用了 FlatButton)。

    bool _btnEnabled = false;
    
    ...
    
    @override
    Widget build(BuildContext context){
    
      ...
    
      TextFormField(
    
        ...
        autovalidate: true,
        validator: (String txt){
          if (txt.length == 10){
            setState((){
              _btnEnabled = true;
            });
          } else {
            setState((){
              _btnEnabled = false;
            });
          }
        }
    
        ...
    
      FlatButton(
        onPressed: _btnEnabled == true ? yourCallback : null,
        child: ...
    

    【讨论】:

    • 我们如何使用这种方法验证多个文本字段,在每个字段都验证后,按钮才会启用?
    【解决方案2】:

    接受的答案似乎不适用于最新的 Flutter v1.7.8(稳定),它给了我以下错误:

    这个TestForm小部件不能被标记为需要构建,因为框架已经在构建小部件的过程中

    工作版本如下所示:

    ...
    autovalidate: true,
    validator: (String txt){
          bool isValid = txt.length == 10;
          if (isValid != _btnEnabled) {
            WidgetsBinding.instance.addPostFrameCallback((_) {
              setState(() {
                _btnEnabled = txt.length == 10;
              });
            });
          } 
    }
    
    ...
    

    【讨论】:

      【解决方案3】:

      小部件的状态可以在表单的 onChanged 回调中更新,只要任何表单字段的值发生更改,就会调用该回调。在那里,您可以使用表单键来验证表单并设置标志以启用/禁用按钮。此解决方案允许您缩放以禁用具有多个字段的表单中的按钮。例如,

      /// Key used to reference the form.
      final _formKey = GlobalKey<FormState>();
      
      ...
      
      Form(
        key: _formKey,
        onChanged: () => setState(() => _enableBtn = _formKey.currentState.validate()),
        child: ListView(
          children: <Widget>[
            TextFormField(
              validator: (value) => value.length < 10 ?
                'Number must be at least 10 digits' : // return an error message
                null,
              ...
            ),
          ],
        ),
      )
      
      ...
      
      FlatButton(
        onPressed: _enableBtn ?
          () => _doSomething() :
          null, // setting onPressed to null disables the button.
        ...
      

      【讨论】:

        【解决方案4】:

        出现错误“在构建期间调用了 setState() 或 markNeedsBuild()。”接受的答案。只需添加 Future.delayed(Duration.zero).then(....) 作为一个技巧解决方案,它正在处理颤振 1.12.13

        TextFormField(
        
        ...
        autovalidate: true,
        validator: (String txt){
          if (txt.length == 10){
            Future.delayed(Duration.zero).then((_){
            setState((){
              _btnEnabled = true;
            });
          });
          } else {
            Future.delayed(Duration.zero).then((_){
            setState((){
              _btnEnabled = false;
            });
          });
          }
        }
        ....
        

        【讨论】:

          【解决方案5】:

          你可以使用 Flutter Reactive Forms。这是一种处理表单输入和验证的模型驱动方法,深受 Angular 的反应式表单的启发。

          使用 libray 非常简单,文档中有一节解释了如何根据整个表单的有效性启用/禁用提交按钮,而不仅仅是一个字段。

          【讨论】:

          • 谢谢 - 您的回答对我帮助很大。 Reactive Forms 看起来很棒,我正在尝试。它看起来与 Angular 的响应式表单非常相似。最好的部分(对我来说)是它们支持异步验证器,这是我需要的功能。
          【解决方案6】:

          你可以使用这个方法。

            bool isEnable = false;
          
          void validateButton() {
              bool isValid = true;
          
              isValid = userEmail.isNotEmpty &&
                  userPassword.isNotEmpty &&
                  validateEmail(userEmail) &&
                  userPassword.length >= 8;
          
              setState(() {
                isEnable = isValid;
              });
            }
          

          现在在你的 Textfield onChanged 方法中你必须调用这个函数

          喜欢这个

          onChanged: (email) {
                                  userEmail = email;
                                  setState(() {});
                                  validateButton();
                                },
          

          在您的登录按钮中

          isEnable?ActiveButton():DisableButton()
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2017-06-20
            • 1970-01-01
            • 2020-03-05
            • 1970-01-01
            • 2020-10-06
            • 1970-01-01
            • 2019-12-04
            相关资源
            最近更新 更多