onPressed按钮时如何从ListView中删除TextField?

Thi*_*URE 3 dart flutter

当用户单击“清除图标”按钮时如何删除 TextField?(不仅仅是清除TextField的Text)

用户故事
用户点击一个按钮来添加玩家。(技术上这个按钮添加了TextField)
用户可以在TextField 上写上玩家的名字。
用户单击“清除图标”按钮以删除当前的 TextField(与添加功能相反)。

在此处输入图片说明

new ListView.builder(
                     padding: EdgeInsets.all(0),
                      shrinkWrap: true,
                      physics: NeverScrollableScrollPhysics(),
                      itemCount: 5,
                      itemBuilder: (context, index) {
                        print(index);
                        return TextField(
                          maxLength: 20,
                          decoration: InputDecoration(
                            labelText: "Player ${index+1}",
                            counterText: "",
                            prefixIcon: const Icon(Icons.person),
                            suffixIcon: new IconButton(
                                icon: Icon(Icons.clear),
                                onPressed: () =>
                                  setState(() {
                                    this.dispose(); // -----Doesn't work----
                                  })
                                ),
                          ),
                        );
                      }
                    ),
Run Code Online (Sandbox Code Playgroud)

例如,如果用户单击“清除按钮”,则用户在 Player 4 上设置了“John”,则 Player 4 TextField 将被删除。它将只剩下 4 个 TextField

在此处输入图片说明

小智 8

我假设的事实:

  1. 您希望能够从(到)列表中删除(或添加)一个字段
  2. 您希望在删除字段时保留剩余字段的值
  3. 列表可以大于 5

解决方案:

如果您希望以上所有内容都为真,那么您实际上需要跟踪TextEditingControllerTextFields的s,而不是文本字段本身。这是因为 TextField 的值实际上存储在 TextEditingController 中(如果您不为每个小部件提供它,则会动态地重新创建)。看一下这个:

import 'package:flutter/material.dart';

// needs to be StatefulWidget, so we can keep track of the count of the fields internally
class PlayerList extends StatefulWidget {
  const PlayerList({
    this.initialCount = 5,
  });

  // also allow for a dynamic number of starting players
  final int initialCount;

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

class _PlayerListState extends State<PlayerList> {
  int fieldCount = 0;
  int nextIndex = 0;
  // you must keep track of the TextEditingControllers if you want the values to persist correctly
  List<TextEditingController> controllers = <TextEditingController>[];

  // create the list of TextFields, based off the list of TextControllers
  List<Widget> _buildList() {
    int i;
    // fill in keys if the list is not long enough (in case we added one)
    if (controllers.length < fieldCount) {
      for (i = controllers.length; i < fieldCount; i++) {
        controllers.add(TextEditingController());
      }
    }

    i = 0;
    // cycle through the controllers, and recreate each, one per available controller
    return controllers.map<Widget>((TextEditingController controller) {
      int displayNumber = i + 1;
      i++;
      return TextField(
        controller: controller,
        maxLength: 20,
        decoration: InputDecoration(
          labelText: "Player $displayNumber",
          counterText: "",
          prefixIcon: const Icon(Icons.person),
          suffixIcon: IconButton(
            icon: Icon(Icons.clear),
            onPressed: () {
              // when removing a TextField, you must do two things:
              // 1. decrement the number of controllers you should have (fieldCount)
              // 2. actually remove this field's controller from the list of controllers
              setState(() {
                fieldCount--;
                controllers.remove(controller);
              });
            },
          ),
        ),
      );
    }).toList(); // convert to a list
  }


  @override
  Widget build(BuildContext context) {
    // generate the list of TextFields
    final List<Widget> children = _buildList();

    // append an 'add player' button to the end of the list
    children.add(
      GestureDetector(
        onTap: () {
          // when adding a player, we only need to inc the fieldCount, because the _buildList()
          // will handle the creation of the new TextEditingController
          setState(() {
            fieldCount++;
          });
        },
        child: Container(
          color: Colors.blue,
          child: Padding(
            padding: const EdgeInsets.all(16),
            child: Text(
              'add player',
              style: TextStyle(
                color: Colors.white,
              ),
            ),
          ),
        ),
      ),
    );

    // build the ListView
    return ListView(
      padding: EdgeInsets.all(0),
      shrinkWrap: true,
      physics: NeverScrollableScrollPhysics(),
      children: children,
    );
  }

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

    // upon creation, copy the starting count to the current count
    fieldCount = widget.initialCount;
  }

  @override
  void dispose() {
    super.dispose();
  }

  @override
  void didUpdateWidget(PlayerList oldWidget) {
    super.didUpdateWidget(oldWidget);
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
  }
}
Run Code Online (Sandbox Code Playgroud)

通过以上,您可以:

  • 启动应用程序
  • 将玩家 2 更改为“鲍勃”
  • 将玩家 3 更改为“史蒂夫”
  • 将玩家 4 更改为“查尔斯”
  • 删除玩家 3
  • 观察玩家 2 是“bob”,新玩家 3 是“charles”

我认为这就是你在这里寻找的东西。

  • 如果控制器被移除,是否还需要进行 Dispose() 处理? (2认同)