如何在 Flutter 中一次只在屏幕上显示一个表单域?

Posted

技术标签:

【中文标题】如何在 Flutter 中一次只在屏幕上显示一个表单域?【英文标题】:How can I only show one form field on the screen at a time in Flutter? 【发布时间】:2020-11-17 22:46:05 【问题描述】:

我正在尝试创建一个一次只显示一个 textFormField 的表单。我创建了一个Form 和一个key: 和一个Container() 作为孩子。 Container() 调用了一个方法,该方法基于一个计数器返回一个 TextFormField 小部件,该计数器在我每次单击下一步按钮时都会递增。除了我在字段中输入的文本保留在每个字段更改之间之外,一切正常。这是我的相关代码:

...              
 Form(
   key: _formkey,
     child: Column(
         children: <Widget>[
             SizedBox(
                height: _height * .10,
                ),
             if (pageCount > 0 && pageCount <= 2)
             _createField(pageCount),
             RaisedButton(onPressed: ()=> _next()),

...

void _next() 
    if (pageCount < 10) 
      setState(() 
        pageCount++;
      );
    
  

...

Widget _createField(int count) 
    switch (count) 
      case 1:
        return TextFormField(
          textAlign: TextAlign.center,
          decoration: textInputDecoration.copyWith(
            hintText: 'name',
            hintStyle: TextStyle(
              color: Colors.grey[500],
              fontStyle: FontStyle.italic,
            ),
          ),
          validator: (val) => val.isEmpty ? 'enter your display name' : null,
          onChanged: (val) 
            setState(() => displayName = val);
          ,
        );
        break;
      case 2:
        return TextFormField(
          textAlign: TextAlign.center,
          decoration: textInputDecoration.copyWith(
            hintText: 'email',
            hintStyle: TextStyle(
              color: Colors.grey[500],
              fontStyle: FontStyle.italic,
            ),
          ),
          validator: (val) => val.isEmpty ? 'enter an email' : null,
          onChanged: (val) 
            setState(() => email = val);
          ,
        );
        break;
 
...

      default:
        return null;
    
  

提示文本和验证有效,唯一的问题是我输入的任何内容都会留在下一个字段中。我尝试使用TextEditingController 清除该字段,但也许我没有正确使用它,因为它要么不起作用,要么有时我收到一个错误,即控制器被调用为空。我不确定我会把它放在哪里。我的最终目标是在填写表格时保留屏幕空间。我愿意接受有关其他方式来实现此目的的建议。

【问题讨论】:

【参考方案1】:
final TextEditingController _controller = TextEditingController();

@override
void dispose() 
  _controller.dispose(); // DO NOT FORGET TO DISPOSE THE CONTROLLER
  super.dispose();


void _next() 
if (pageCount < 10) 
  setState(() 
    if (_formkey.currentState.validate()) 
      // update the variable by saving the form
      _formkey.currentState.save();
      pageCount++;
    
  );


Widget _createField(int count) 
    switch (count) 
      case 1:
        // set the text to the correct variable
        _controller.text = displayName ?? '';
        return Center(
          child: TextFormField(
            textAlign: TextAlign.center,
            decoration: InputDecoration().copyWith(
              hintText: 'name',
              hintStyle: TextStyle(
                color: Colors.grey[500],
                fontStyle: FontStyle.italic,
              ),
            ),
            autovalidateMode: AutovalidateMode.onUserInteraction,
            controller: _controller,
            validator: (val) => val.isEmpty ? 'enter your display name' : null,
            // update the variable as the user navigates through the form
            onSaved: (val) => displayName = val,
          ),
        );
        break;
      case 2:
        _controller.text = email ?? '';
        return TextFormField(
          textAlign: TextAlign.center,
          decoration: InputDecoration().copyWith(
            hintText: 'email',
            hintStyle: TextStyle(
              color: Colors.grey[500],
              fontStyle: FontStyle.italic,
            ),
          ),
          autovalidateMode: AutovalidateMode.onUserInteraction,
          controller: _controller,
          validator: (val) => val.isEmpty ? 'enter an email' : null,
          onSaved: (val) => email = val,
        );
        break;
...
          default:
            _controller.text = '';
            setState(() => pageCount = 1);
            return null;
        
      

【讨论】:

感谢 Lee3,现在将 _controller 传递给该方法会清除该字段。但是我的验证器现在不工作。我还刚刚注意到,当我返回以前的字段时,它会将验证器错误保留在该字段下。有什么可以做的吗? 我已更新我的答案,以验证 _next() 方法中的当前字段,然后允许用户进入下一个字段。我希望这会有所帮助。 另外,使用您的解决方案,返回编辑字段也会将其清除 您的编辑修复了验证。我标记为答案。谢谢!我想我可以忍受回去清理场地。除非你认为有办法解决这个问题? 在您的 switch 案例中,将TextField 的当前值设置为相应变量的值,如果不为空。

以上是关于如何在 Flutter 中一次只在屏幕上显示一个表单域?的主要内容,如果未能解决你的问题,请参考以下文章

UITableview如何一次只显示一个单元格

如何在swift中一次只选择两个UITableview单元格

Lodash - 如何从嵌套的json中一次只选择一项?

在反应jsx中一次遍历一个数组

想拿起工具或枪支,但想在统一 c# 中一次只选择一个

如何在 Flutter 中一段时间​​后切换小部件?