Flutter TextField使用setState失去焦点

时间:2019-02-05 12:30:09

标签: flutter keyboard focus textfield

我有一个自定义的有状态小部件,当键入一个空字段时,它将在下面自动添加一个新的空字段,以便用户可以继续添加数据。

但是,当我在setState中使用onChanged添加新字段时,键盘将关闭,焦点将丢失在当前聚焦的字段上。

如何防止这种情况发生?

 TextField(
          hintText: widget.newEntryHint,
          text: data[index].value,
          onChanged: (val) {
            setState(() {
              data[index].value = val;

              //if last item in list, add an extra field below
              if (val.length > 0 && index == (data.length -1)) {
                data.add(TextListItem(value: ""));
              }
            });
          },
        )

自定义文本字段以供参考:

class MyTextField extends StatefulWidget {
  MyTextField({
    this.text,
    this.hintText = "",
    this.onChanged,
    this.onSubmitted,
    this.textAlign = TextAlign.left,
    this.focusNode,
    this.autofocus = false,
    this.obscureText = false,
    this.padding = const EdgeInsets.all(0.0),
    this.keyboardType = TextInputType.text,
    this.canEdit = true,
    this.isDarkMode = false,
    this.textCapitalization = TextCapitalization.sentences,
    this.key,
  });

  final String text;
  final String hintText;
  final ValueChanged<String> onChanged;
  final ValueChanged<String> onSubmitted;
  final TextAlign textAlign;
  final FocusNode focusNode;
  final bool autofocus;
  final bool obscureText;
  final EdgeInsets padding;
  final TextInputType keyboardType;
  final TextCapitalization textCapitalization;
  final Key key;

  final bool canEdit;

  final isDarkMode;

  @override
  _MyTextFieldState createState() => _MyTextFieldState();
}

class _MyTextFieldState extends State<MyTextField> {
  static const double textFieldPadding = 12.0;
  TextEditingController editingController;

  @override
  void initState() {
    super.initState();
    editingController = TextEditingController(text: widget.text);
  }

  @override
  Widget build(BuildContext context) {
    return IgnorePointer(
      ignoring: !widget.canEdit,
      child: Column(
        children: <Widget>[
          new Padding(
            padding: EdgeInsets.only(
                top: textFieldPadding + widget.padding.top, bottom: textFieldPadding + widget.padding.bottom, left: widget.padding.left, right: widget.padding.right),
            child: new TextField(
              key: widget.key,
              maxLines: null,
              textCapitalization: widget.textCapitalization,
              keyboardType: widget.keyboardType,
              keyboardAppearance: widget.isDarkMode ? Brightness.dark : Brightness.light,
              controller: editingController,
              onSubmitted: widget.onSubmitted,
              onChanged: widget.onChanged,
              style: new TextStyle(
                  color: widget.isDarkMode ? Colors.white : MyColors.textBlue,
                  fontSize: 16.0,
                  fontWeight: FontWeight.w500),
              autofocus: widget.autofocus,
              focusNode: widget.focusNode,
              textAlign: widget.textAlign,
              obscureText: widget.obscureText,
              decoration: new InputDecoration(
                hintText: widget.hintText,
                hintStyle: new TextStyle(
                    color: widget.isDarkMode ? MyColors.black[700] : MyColors.grey,
                    fontSize: 16.0,
                    fontWeight: FontWeight.w500),
                border: InputBorder.none,
              ),
            ),
          ),
          Divider(
            color: widget.isDarkMode ? MyColors.black : MyColors.grey[150],
            height: 1.0,
          ),
        ],
      ),
    );
  }
}

3 个答案:

答案 0 :(得分:1)

我遇到了同样的问题。我发现我在容器中使用了key: UniqueKey()。它在每个setState上生成uniqueKey并更新子级。检查密钥。

答案 1 :(得分:0)

我知道已经有一段时间了,也许从那以后已经解决了一些问题,但是我再也看不到您的问题了。至少以我设置窗口小部件的方式(您的data.add()与我的fields.add() 之间的细微差别)。

List<Widget> _fields;
ScrollController controller = new ScrollController();

_buildData() {
  _fields = new List();
  for (int i = 0; i < 3; i++) {
    _fields.add(_createMyTextField('hello$i', i));
  }
}

Widget _createMyTextField(String text, int index) {
  return MyTextField(
    text: text,
    hintText: 'hello hint$index',
    onChanged: (val) {
      setState(() {
        //if last item in list, add an extra field below
        if (val.length > 0 && index == (_fields.length-1)) {
          _fields.add(_createMyTextField("", index+1));
        }
      });
    },
  );
}

@override
void initState() {
  super.initState();
  _buildData();
}

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(title: Text(widget.title)),
    body: ListView(
      controller: controller,
      children: _fields.toList()
    )
  );
}

enter image description here

答案 2 :(得分:0)

我最近遇到了同样的问题。在我的情况下,问题是由树中的 Container 引起的,该树具有可选的 margin,该 TextFormField 由子树中的焦点控制。当点击 const useArray = [Bootstrap-Vue, Vue Analytics]; useArray.forEach((item)=>{ Vue.use(item) }) 时,键盘会上下弹出并且该字段没有焦点。但是,由于焦点,容器的边距已正确更改。

通过将容器的边距改为 0 而不是 null,它解决了这个问题。它也可能适用于填充等其他属性。