1

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

在此处输入图像描述

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

controller.text = Container();

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

目标是在 StackOverflow 上放置“标签”的地方做完全相同的 inputField。

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

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

4

2 回答 2

2

这里的诀窍是如下所示显示可取的 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 = '';
                    });
                  },
                ),
              )
            ],
          ),
        )),
      ),
    );
  }
}
于 2020-07-03T11:30:44.110 回答
2

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

它看起来像这样:

在此处输入图像描述

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

于 2020-07-03T14:07:17.073 回答