颤动多个电子邮件TextField

时间:2020-07-03 10:30:38

标签: flutter textfield textformfield

出于学习目的,我正在尝试进行gmail克隆,我正在努力编辑新邮件时输入的多电子邮件。我需要笨拙地听“ ENTER”或“ SPACE”,以便我可以用电子邮件“ block”修改输入(验证后):

enter image description here

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

controller.text = Container();

但是“文本”仅接受String(这似乎是逻辑)。

目标是做完全相同的inputField,在其中将“标记”放在StackOverflow上。

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

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

2 个答案:

答案 0 :(得分:1)

这里的窍门是显示如下所示的理想UI,InputDecoration.collapsed()帮助我们将TextField最小化,您可以在主列的最后一个小部件中添加Divider()描绘所有这些都在TextField

内部进行

我试图模拟您要实现的行为。 我使用TextField方法检查onChange中的字符串输入末尾是否有空格,对于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 = '';
                    });
                  },
                ),
              )
            ],
          ),
        )),
      ),
    );
  }
}

答案 1 :(得分:0)

如果有人来这里需要我提供的模板所具有的相同功能,则可以将其粘贴到新文件中,然后在需要时调用EmailInput()。您只想使用带有功能的setList属性来更新您的List<String>,以将数据返回到您的父组件中:)它还检查输入的字符串是否是有效的电子邮件。

它看起来像这样:

enter image description here

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);
}