基于TextFormField内容的Flutter启用/禁用按钮

时间:2018-12-28 20:57:48

标签: button keyboard flutter textfield flutter-layout

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

我想确保如果TextFormField有10个输入的数字(如果是手机号码),则用户只能按ButtonX。

谢谢!

5 个答案:

答案 0 :(得分:7)

可以在窗体的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.
  ...

答案 1 :(得分:1)

一种简单的方法是将TextFormField的autovalidate属性设置为true。这将自动检测TextFormField小部件上的更改。然后,我们可以尝试检查我们的TextFormField的值是否在validateator属性上具有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 :(得分:0)

使用最新的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 :(得分:0)

您可以使用Flutter Reactive Forms。这是一种由模型驱动的方法来处理Forms输入和验证,这在Angular的Reactive Forms中受到了极大的启发。

使用libray非常简单,并且在文档中有一节说明了如何基于整个表单(而不只是字段)的有效性来启用/禁用“提交”按钮。

答案 4 :(得分:-1)

获取错误“在构建期间调用setState()或markNeedsBuild()”。与可接受的答案。只需添加Future.delayed(Duration.zero).then(....)作为一个技巧解决方案,它就可以在Flutter 1.12.13上运行

$ cat tst.awk
BEGIN {
    RS=ORS=";\n"
    IGNORECASE=1
}
/^pattern1/ {
    $0 = gensub(/\((.*)\)/,"\\1",1)
    gsub(/[[:space:]]+/," ")
}
{ print }

$ awk -f tst.awk file
    not (this line);
pattern1 some text, some other text (5), some other text (6);
pattern1 this text that text (6), that text (7), ;
not this text either;