【问题标题】:Flutter multiple email TextField颤振多个电子邮件TextField
【发布时间】:2020-10-24 01:37:57
【问题描述】:

出于学习目的,我正在尝试进行 gmail 克隆,当您编辑新邮件时,我正在努力处理您的多电子邮件输入。我需要能够听“ENTER”或“SPACE”,以便我可以使用这样的电子邮件“块”修改输入(验证后):

我想我可以使用“ENTER”键的 onFieldSubmitted 标记,但是如何更改输入文本?我试过了:

controller.text = Container();

但“文本”只接受字符串(这似乎是逻辑)。

目标是在您将“标签”放在 StackOverflow 上的地方执行完全相同类型的 inputField。

我也找到了 EmailInputElement 但我不知道如何正确使用它,它似乎不是一个小部件。

如果有人有任何想法,将不胜感激,谢谢。

【问题讨论】:

    标签: flutter textfield textformfield


    【解决方案1】:

    这里的技巧是如下所示显示令人讨厌的 UI,InputDecoration.collapsed() 帮助我们将TextField 最小化,你可以添加一个Divider() 作为主列的最后一个小部件来描绘所有这一切继续在TextField

    我试图模拟您想要实现的行为。 我使用onChange 方法检查TextField 中字符串输入末尾的空格,对于enter 按钮,我使用onEditingComplete 函数。 我已经对电子邮件行进行了限制,以使其仅增长到视口的特定宽度,您也可以使用不同的布局。

    class Test extends StatefulWidget {
      @override
      _TestState createState() => _TestState();
    }
    
    class _TestState extends State<Test> {
      List<String> emails = [];
      TextEditingController _emailController;
    
      @override
      void initState() {
        super.initState();
        _emailController = TextEditingController();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: SafeArea(
            child: Container(
                child: Center(
              child: Row(
                children: <Widget>[
                  Container(
                    constraints: BoxConstraints(maxWidth: 200, minWidth: 0),
                    child: SingleChildScrollView(
                      scrollDirection: Axis.horizontal,
                      child: Row(
                        mainAxisAlignment: MainAxisAlignment.start,
                        mainAxisSize: MainAxisSize.min,
                        crossAxisAlignment: CrossAxisAlignment.center,
                        children: <Widget>[
                          ...emails
                              .map((email) => Chip(label: Text(email)))
                              .toList(),
                        ],
                      ),
                    ),
                  ),
                  Expanded(
                    child: TextField(
                      decoration: InputDecoration.collapsed(hintText: 'EMail'),
                      controller: _emailController,
                      onChanged: (String val) {
                        if (val.endsWith(' '))
                          setState(() {
                            emails.add(_emailController.text);
                            _emailController.text = '';
                          });
                      },
                      onEditingComplete: () {
                        setState(() {
                          emails.add(_emailController.text);
                          _emailController.text = '';
                        });
                      },
                    ),
                  )
                ],
              ),
            )),
          ),
        );
      }
    }
    

    【讨论】:

    • 非常感谢@Aadiyaara,您的示例在对它进行了一些尝试之后变得很有意义,这确实是一个很好的起点,我会在此基础上继续感谢老兄!
    【解决方案2】:

    如果有人来这里是为了获得我所要求的相同功能,有我的模板,您可以将其粘贴到一个新文件中,然后在您需要的地方调用 EmailInput()。您只想使用 setList 属性和函数来更新您的 List&lt;String&gt; 以将数据返回到您的父组件:) 它还会检查输入的字符串是否是有效的电子邮件。

    看起来像这样:

    import 'package:flutter/material.dart';
    
    class EmailInput extends StatefulWidget {
      final Function setList;
      final String hint;
      final List<String> parentEmails;
    
      const EmailInput({Key key, this.setList, this.hint, this.parentEmails}) : super(key: key);
    
      @override
      _EmailInputState createState() => _EmailInputState();
    }
    
    class _EmailInputState extends State<EmailInput> {
      TextEditingController _emailController;
      String lastValue = '';
      List<String> emails = [];
      FocusNode focus = FocusNode();
      @override
      void initState() {
        super.initState();
        _emailController = TextEditingController();
    
        focus.addListener(() {
          if (!focus.hasFocus) {
            updateEmails();
          }
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return Container(
            child: Center(
          child: Column(
            children: <Widget>[
              Container(
                constraints: BoxConstraints(
                  minWidth: 0,
                ),
                child: SingleChildScrollView(
                  scrollDirection: Axis.horizontal,
                  child: Column(
                    children: <Widget>[
                      ...emails
                          .map(
                            (email) => Chip(
                              avatar: CircleAvatar(
                                backgroundColor: Colors.black,
                                child: Text(
                                  email.substring(0, 1),
                                  style: TextStyle(color: Colors.white),
                                ),
                              ),
                              labelPadding: EdgeInsets.all(4),
                              backgroundColor: Color.fromARGB(255, 39, 182, 192),
                              label: Text(
                                email,
                                style: TextStyle(fontSize: 16, color: Colors.white),
                              ),
                              onDeleted: () => {
                                setState(() {
                                  emails.removeWhere((element) => email == element);
                                })
                              },
                            ),
                          )
                          .toList(),
                    ],
                  ),
                ),
              ),
              TextField(
                keyboardType: TextInputType.emailAddress,
                decoration: InputDecoration.collapsed(hintText: widget.hint),
                controller: _emailController,
                focusNode: focus,
                onChanged: (String val) {
                  setState(() {
                    if (val != lastValue) {
                      lastValue = val;
                      if (val.endsWith(' ') && validateEmail(val.trim())) {
                        if (!emails.contains(val.trim())) {
                          emails.add(val.trim());
                          widget.setList(emails);
                        }
                        _emailController.clear();
                      } else if (val.endsWith(' ') && !validateEmail(val.trim())) {
                        _emailController.clear();
                      }
                    }
                  });
                },
                onEditingComplete: () {
                  updateEmails();
                },
              )
            ],
          ),
        ));
      }
    
      updateEmails() {
        setState(() {
          if (validateEmail(_emailController.text)) {
            if (!emails.contains(_emailController.text)) {
              emails.add(_emailController.text.trim());
              widget.setList(emails);
            }
            _emailController.clear();
          } else if (!validateEmail(_emailController.text)) {
            _emailController.clear();
          }
        });
      }
    
      setEmails(List<String> emails) {
        this.emails = emails;
      }
    }
    
    bool validateEmail(String value) {
      Pattern pattern =
          r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$';
      RegExp regex = new RegExp(pattern);
      return regex.hasMatch(value);
    }
    
    

    【讨论】:

      猜你喜欢
      • 2019-12-31
      • 2023-03-28
      • 2019-03-04
      • 2019-01-07
      • 2021-01-08
      • 2021-05-10
      • 1970-01-01
      • 2021-05-05
      • 1970-01-01
      相关资源
      最近更新 更多