Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/flutter/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Flutter 当按下按钮时,如何从ListView中删除文本字段?_Flutter_Dart - Fatal编程技术网

Flutter 当按下按钮时,如何从ListView中删除文本字段?

Flutter 当按下按钮时,如何从ListView中删除文本字段?,flutter,dart,Flutter,Dart,当用户单击“清除图标”按钮时,如何删除文本字段?(不仅仅是清除TextField的文本) 用户故事 用户单击按钮添加播放器。(从技术上讲,此按钮添加文本字段) 用户可以在文本字段中写入播放器的名称。 用户点击“清除图标”按钮删除当前文本字段(与添加功能相反) 例如,用户在播放器4上设置“John”,如果用户单击“清除按钮”,则播放器4文本字段将被删除。它将只保留4个文本字段 您可以使用一个属性来检查用户是否单击了该按钮,这取决于显示/隐藏文本字段的值。下面我只使用一个布尔属性,如果用户单击X按

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

用户故事
用户单击按钮添加播放器。(从技术上讲,此按钮添加文本字段)
用户可以在文本字段中写入播放器的名称。
用户点击“清除图标”按钮删除当前文本字段(与添加功能相反)

例如,用户在播放器4上设置“John”,如果用户单击“清除按钮”,则播放器4文本字段将被删除。它将只保留4个文本字段


您可以使用一个属性来检查用户是否单击了该按钮,这取决于显示/隐藏
文本字段的值。下面我只使用一个布尔属性,如果用户单击X按钮,那么我将
hideField
设置为true,并且
TextField
将替换为零大小的小部件

 new ListView.builder(
                    padding: EdgeInsets.all(0),
                    shrinkWrap: true,
                    physics: NeverScrollableScrollPhysics(),
                    itemCount: 5,
                    itemBuilder: (context, index) {
                      print(index);
                      bool hideField = false; // I added it here

                      return hideField ? SizedBox.shrink() : TextField(
                        maxLength: 20,
                        decoration: InputDecoration(
                          labelText: "Player ${index + 1}",
                          counterText: "",
                          prefixIcon: const Icon(Icons.person),
                          suffixIcon: new IconButton(
                              icon: Icon(Icons.clear),
                              onPressed: () =>
                                  setState(() {
                                    hideField = true; // Now it works
                                  })
                          ),
                        ),
                      );
                    }
                )

我假设的事实:

  • 您希望能够从列表中删除(或添加)字段
  • 您希望在删除字段时保留其余字段的值
  • 列表可以大于5
  • 解决方案:

    如果您希望上述所有内容都为真,那么您实际上需要跟踪文本字段的
    TextEditingController
    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();
      }
    }
    
    导入“包装:颤振/材料.省道”;
    //需要是StatefulWidget,以便我们可以在内部跟踪字段的计数
    类PlayerList扩展StatefulWidget{
    康斯特剧作家({
    这个.initialCount=5,
    });
    //同时考虑到起始球员的动态数量
    最终整数初始计数;
    @凌驾
    _PlayerListState createState()=>PlayerListState();
    }
    类_PlayerListState扩展状态{
    int fieldCount=0;
    int-nextIndex=0;
    //如果希望值正确持久,则必须跟踪TextEditingController
    列表控制器=[];
    //根据TextController列表创建TextFields列表
    列表_buildList(){
    int i;
    //如果列表不够长,请填写关键字(如果我们添加了一个)
    if(controllers.length
    通过以上步骤,您可以:

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

    我想这就是您在这里要找的。

    这将有两个问题。1.您只能有5个文本字段,2个。删除其中一个字段时,其他字段的值将不会以正确的顺序保留。不,不会有问题。1.注意,我只是更新当前文本字段2的状态。其他人的价值将持续存在,因为我没有重建whilelistview,我只是用一个大小为零的小部件替换TextField。将它插入模拟器。我指出的两个问题是实际问题。非常感谢您的帮助,您的答案解释得很好:)我尝试过这样做:当用户单击“添加播放器”按钮时,自动滚动到底部页面。我添加了一个ScrollController,但不起作用
    ScrollController\u ScrollController
    
    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();
      }
    }