【问题标题】:How to edit a selected item from a list in flutter如何在颤动中编辑列表中的选定项目
【发布时间】:2020-12-03 20:06:51
【问题描述】:

我一直在尝试向我的待办事项列表添加一个编辑功能,用户可以在其中选择用户想要编辑的项目,然后应该会弹出一个对话框,其中有一个文本字段来输入所选的新值项目和保存更改的按钮。目前我有一个函数调用存储任务的数组,然后它应该使用索引触发所选项目,以便最后在 onPressed 时可以为所选值赋予一个新值,将此编辑功能视为 instagrams 之一,除了它编辑文本。

在对话框的编辑按钮中调用该函数时出现问题,因为我正在这样做 onPressed: () => _editToDoItem(_controller.text, index) 并且因为我必须在那里传递 2 个参数,所以我得到的错误是 Undefined name 'index'。如何解决此问题以使此编辑功能起作用?顺便说一句,由于这个错误,我还没有尝试编辑功能,所以如果功能或代码的任何部分不正确,请纠正我。

与下面的编辑功能有关。

  List<ToDoElement> _toDoItems = [];
  TextEditingController _controller = TextEditingController();

  // this function adds a task to the list
  void _addToDoItem(String task) {
    if(task.isNotEmpty) {
      setState(() {  
        _toDoItems.add(ToDoElement(task, DateTime.now()));
      });
    }
  }

  // this is the function that is supposed to edit the selected index from the _toDoItems array
  void _editToDoItem(String newText, int index) {
    setState(() {
      _toDoItems[index].task = newText;
    });
  }

  _editDialog(BuildContext context) {
    return showDialog(context: context, builder: (context) {
      return Dialog(
        child: Container(
          height: 180,
          width: 100,
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
                Container(
                  height: 60, 
                  child: TextField(
                    controller: _controller,
                    autofocus: true,
                    style: TextStyle(fontSize: 18,),
                  )
                ), 
                Container(
                  height: 65,
                  width: double.infinity,
                  margin: EdgeInsets.only(top: 5,),
                  child: RaisedButton(
                    textColor: Colors.white,
                    color: Colors.red,
                    child: Text('EDIT'),
                    onPressed: () {
                      _editToDoItem(_controller.text, index); // error on index, Undefined name 'index'
                      FocusScope.of(context).requestFocus(FocusNode());
                    },
                  ),
                ),                                          
            ],
          ),
        ),
      );
    });
  }

完整的 main.dart 文件

class ToDoElement {
  String task;
  final DateTime timeOfCreation;

  ToDoElement(this.task, this.timeOfCreation);
}

void main() => runApp(MaterialApp(home: MyApp()));

class MyApp extends StatefulWidget {
  @override
  createState() => MyAppState();
}



class MyAppState extends State<MyApp> {
  List<ToDoElement> _toDoItems = [];
  TextEditingController _controller = TextEditingController();

  void _addToDoItem(String task) {
    if(task.isNotEmpty) {
      setState(() {  
        _toDoItems.add(ToDoElement(task, DateTime.now()));
      });
    }
  }

  void _editToDoItem(String newText, int index) {
    setState(() {
      _toDoItems[index].task = newText;
    });
  }

  void _removeTodoItem(int index) {
    setState(() => _toDoItems.removeAt(index));
  }

  _editDialog(BuildContext context) {
    return showDialog(context: context, builder: (context) {
      return Dialog(
        backgroundColor: Colors.transparent,
        child: Container(
          decoration: BoxDecoration(
            color: Colors.white,
            borderRadius: BorderRadius.all(Radius.circular(20.0)),
          ),
          padding: EdgeInsets.all(20),
          height: 180,
          width: 100,
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
                Container(
                  height: 60, 
                  child: TextField(
                    controller: _controller,
                    autofocus: true,
                    /*onSubmitted: (val) {
                      _addToDoItem(val);
                      _controller.clear();
                    },*/
                    style: TextStyle(fontSize: 18,),
                    decoration: InputDecoration(
                      hintText: 'Add a task here...',
                      enabledBorder: OutlineInputBorder(
                        borderRadius: BorderRadius.all(Radius.circular(12.0)),
                        borderSide: BorderSide(color: Colors.red, width: 2),
                      ),
                      focusedBorder: OutlineInputBorder(
                        borderRadius: BorderRadius.all(Radius.circular(12.0)),
                        borderSide: BorderSide(color: Colors.red, width: 2),
                      ),
                      
                    ),
                  )
                ),

              
                   
                Container(
                  height: 65,
                  width: double.infinity,
                  margin: EdgeInsets.only(top: 5,),
                  child: RaisedButton(
                    textColor: Colors.white,
                    color: Colors.red,
                    child: Text('EDIT', style: TextStyle(fontSize: 18)),
                    
                    shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.all(Radius.circular(12)),
                    ),
                    onPressed: () {
                      _editToDoItem(_controller.text, index);
                      FocusScope.of(context).requestFocus(FocusNode());
                    },
                  ),
                ),                                          
            ],
          ),
        ),
      );
    });
  }

  Widget _buildToDoItem(String toDoText, int index) {
    return SizedBox(
      child: Container(
        height: 58,
        margin: EdgeInsets.only(left: 22.0, right: 22.0, bottom: 12,),
        decoration: BoxDecoration(
          border: Border.all(width: 1.5, color: Colors.red),
          borderRadius: BorderRadius.all(Radius.circular(18)),
        ),
        child: Row(
          crossAxisAlignment: CrossAxisAlignment.center,
          children:[
            Expanded(
              child: ListTile(
                title: Text(
                  toDoText,
                  style: TextStyle(fontSize: 18),
                ),
                onTap: () => null,
              ),
            ),
            FlatButton(
              child: Text('Edit', style: TextStyle(color: Colors.red, fontSize: 16.5),),
              onPressed: () => _editDialog(context),
            ),
            FlatButton(
              child: Text('Delete', style: TextStyle(color: Colors.red, fontSize: 16.5),),
              onPressed: () => _removeTodoItem(index),
            ),
          ],
        ),
      ),
    );
  }

  int compareElement(ToDoElement a, ToDoElement b) =>
      a.timeOfCreation.isAfter(b.timeOfCreation) ? -1 : 1;

  Widget _buildToDoList() {
    _toDoItems.sort(compareElement);
    return Expanded(
      child: ListView.builder(
        itemCount: _toDoItems.length,
        itemBuilder: (context, index) {
          if (index < _toDoItems.length) {
            return _buildToDoItem(_toDoItems[index].task, index);
          }
        },
      ),
    );
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: PreferredSize(
          preferredSize: Size.fromHeight(50),
          child: AppBar(
            centerTitle: true,
            backgroundColor: Colors.red,
            title: Text('To Do List', style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold,),),
          )
        ),
        backgroundColor: Colors.white,
        body: GestureDetector(
          onTap: () {
            FocusScope.of(context).requestFocus(FocusNode());
          },
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              Container(
                height: 60,
                margin: EdgeInsets.all(22),
                child: Row(
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: [
                    Expanded(
                      flex: 10,
                      child: Container(
                        height: double.infinity,
                        child: TextField(
                          controller: _controller,
                          autofocus: true,
                          onSubmitted: (val) {
                            _addToDoItem(val);
                            _controller.clear();
                          },
                          style: TextStyle(fontSize: 18,),
                          
                          decoration: InputDecoration(
                            hintText: 'Add a task here...',
                            enabledBorder: OutlineInputBorder(
                              borderRadius: BorderRadius.all(Radius.circular(12.0)),
                              borderSide: BorderSide(color: Colors.red, width: 2),
                            ),
                            focusedBorder: OutlineInputBorder(
                              borderRadius: BorderRadius.all(Radius.circular(12.0)),
                              borderSide: BorderSide(color: Colors.red, width: 2),
                            ),
                            
                          ),
                        ),
                      ),
                      
                    ),
                    Expanded(
                      flex: 4,    
                      child: Container(
                        height: double.infinity,
                        margin: EdgeInsets.only(left: 12),
                        child: RaisedButton(
                          textColor: Colors.white,
                          color: Colors.red,
                          child: Text('ADD', style: TextStyle(fontSize: 18)),
                          
                          shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.all(Radius.circular(12)),
                          ),
                          onPressed: () {
                            _addToDoItem(_controller.text);
                            _controller.clear();
                            FocusScope.of(context).requestFocus(FocusNode());
                          },
                        ),
                      ),                                          
                    ),
                  ],
                ),
              ), 
              _buildToDoList()
            ]
          ), 
                 
        ),
    );
  }
}

如果您有任何问题,请在 cmets 中告诉我;)

【问题讨论】:

    标签: flutter dart flutter-layout


    【解决方案1】:

    您可以在下面复制粘贴运行完整代码
    您可以将index 提供给_editDialog 然后_editToDoItem 可以得到index
    代码sn-p

    _editDialog(BuildContext context, int index)
    ...
    FlatButton(
          child: Text(
            'Edit',
            style: TextStyle(color: Colors.red, fontSize: 16.5),
          ),
          onPressed: () => _editDialog(context, index),
        ),
    

    工作演示

    完整代码

    import 'package:flutter/material.dart';
    
    class ToDoElement {
      String task;
      final DateTime timeOfCreation;
    
      ToDoElement(this.task, this.timeOfCreation);
    }
    
    void main() => runApp(MaterialApp(home: MyApp()));
    
    class MyApp extends StatefulWidget {
      @override
      createState() => MyAppState();
    }
    
    class MyAppState extends State<MyApp> {
      List<ToDoElement> _toDoItems = [];
      TextEditingController _controller = TextEditingController();
      TextEditingController _controller1 = TextEditingController();
    
      void _addToDoItem(String task) {
        if (task.isNotEmpty) {
          setState(() {
            _toDoItems.add(ToDoElement(task, DateTime.now()));
          });
        }
      }
    
      void _editToDoItem(String newText, int index) {
        setState(() {
          _toDoItems[index].task = newText;
        });
      }
    
      void _removeTodoItem(int index) {
        setState(() => _toDoItems.removeAt(index));
      }
    
      _editDialog(BuildContext context, int index) {
        return showDialog(
            context: context,
            builder: (context) {
              return Dialog(
                backgroundColor: Colors.transparent,
                child: Container(
                  decoration: BoxDecoration(
                    color: Colors.white,
                    borderRadius: BorderRadius.all(Radius.circular(20.0)),
                  ),
                  padding: EdgeInsets.all(20),
                  height: 180,
                  width: 100,
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Container(
                          height: 60,
                          child: TextField(
                            controller: _controller,
                            autofocus: true,
                            /*onSubmitted: (val) {
                          _addToDoItem(val);
                          _controller.clear();
                        },*/
                            style: TextStyle(
                              fontSize: 18,
                            ),
                            decoration: InputDecoration(
                              hintText: 'Add a task here...',
                              enabledBorder: OutlineInputBorder(
                                borderRadius:
                                    BorderRadius.all(Radius.circular(12.0)),
                                borderSide: BorderSide(color: Colors.red, width: 2),
                              ),
                              focusedBorder: OutlineInputBorder(
                                borderRadius:
                                    BorderRadius.all(Radius.circular(12.0)),
                                borderSide: BorderSide(color: Colors.red, width: 2),
                              ),
                            ),
                          )),
                      Container(
                        height: 65,
                        width: double.infinity,
                        margin: EdgeInsets.only(
                          top: 5,
                        ),
                        child: RaisedButton(
                          textColor: Colors.white,
                          color: Colors.red,
                          child: Text('EDIT', style: TextStyle(fontSize: 18)),
                          shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.all(Radius.circular(12)),
                          ),
                          onPressed: () {
                            _editToDoItem(_controller.text, index);
                            FocusScope.of(context).requestFocus(FocusNode());
                          },
                        ),
                      ),
                    ],
                  ),
                ),
              );
            });
      }
    
      Widget _buildToDoItem(String toDoText, int index) {
        return SizedBox(
          child: Container(
            height: 58,
            margin: EdgeInsets.only(
              left: 22.0,
              right: 22.0,
              bottom: 12,
            ),
            decoration: BoxDecoration(
              border: Border.all(width: 1.5, color: Colors.red),
              borderRadius: BorderRadius.all(Radius.circular(18)),
            ),
            child: Row(
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                Expanded(
                  child: ListTile(
                    title: Text(
                      toDoText,
                      style: TextStyle(fontSize: 18),
                    ),
                    onTap: () => null,
                  ),
                ),
                FlatButton(
                  child: Text(
                    'Edit',
                    style: TextStyle(color: Colors.red, fontSize: 16.5),
                  ),
                  onPressed: () => _editDialog(context, index),
                ),
                FlatButton(
                  child: Text(
                    'Delete',
                    style: TextStyle(color: Colors.red, fontSize: 16.5),
                  ),
                  onPressed: () => _removeTodoItem(index),
                ),
              ],
            ),
          ),
        );
      }
    
      int compareElement(ToDoElement a, ToDoElement b) =>
          a.timeOfCreation.isAfter(b.timeOfCreation) ? -1 : 1;
    
      Widget _buildToDoList() {
        _toDoItems.sort(compareElement);
        return Expanded(
          child: ListView.builder(
            itemCount: _toDoItems.length,
            itemBuilder: (context, index) {
              if (index < _toDoItems.length) {
                return _buildToDoItem(_toDoItems[index].task, index);
              }
            },
          ),
        );
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: PreferredSize(
              preferredSize: Size.fromHeight(50),
              child: AppBar(
                centerTitle: true,
                backgroundColor: Colors.red,
                title: Text(
                  'To Do List',
                  style: TextStyle(
                    fontSize: 24,
                    fontWeight: FontWeight.bold,
                  ),
                ),
              )),
          backgroundColor: Colors.white,
          body: GestureDetector(
            onTap: () {
              FocusScope.of(context).requestFocus(FocusNode());
            },
            child: Column(crossAxisAlignment: CrossAxisAlignment.center, children: [
              Container(
                height: 60,
                margin: EdgeInsets.all(22),
                child: Row(
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: [
                    Expanded(
                      flex: 10,
                      child: Container(
                        height: double.infinity,
                        child: TextField(
                          controller: _controller1,
                          autofocus: true,
                          onSubmitted: (val) {
                            _addToDoItem(val);
                            _controller1.clear();
                          },
                          style: TextStyle(
                            fontSize: 18,
                          ),
                          decoration: InputDecoration(
                            hintText: 'Add a task here...',
                            enabledBorder: OutlineInputBorder(
                              borderRadius: BorderRadius.all(Radius.circular(12.0)),
                              borderSide: BorderSide(color: Colors.red, width: 2),
                            ),
                            focusedBorder: OutlineInputBorder(
                              borderRadius: BorderRadius.all(Radius.circular(12.0)),
                              borderSide: BorderSide(color: Colors.red, width: 2),
                            ),
                          ),
                        ),
                      ),
                    ),
                    Expanded(
                      flex: 4,
                      child: Container(
                        height: double.infinity,
                        margin: EdgeInsets.only(left: 12),
                        child: RaisedButton(
                          textColor: Colors.white,
                          color: Colors.red,
                          child: Text('ADD', style: TextStyle(fontSize: 18)),
                          shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.all(Radius.circular(12)),
                          ),
                          onPressed: () {
                            _addToDoItem(_controller1.text);
                            _controller1.clear();
                            FocusScope.of(context).requestFocus(FocusNode());
                          },
                        ),
                      ),
                    ),
                  ],
                ),
              ),
              _buildToDoList()
            ]),
          ),
        );
      }
    }
    

    【讨论】:

    • 嘿!您的代码有效,是否有其他方法可以调用 _controller.text 以便它不会更改 addtoDoItem 输入?因为在编辑时它也会更改文本字段值,而它应该保持为空
    • 可以使用两个TextEditingController,见更新完整代码
    • 原因是两个TextField使用同一个TextEditController。
    • 我刚刚想通了,要使所选元素的编辑文本字段中包含所选元素的文本,我该怎么办?我一直在考虑使用 TextEditingController ......
    • 我尝试在对话框文本字段的提示文本中使用hintText: '${_toDoItem[index]}',我得到“ToDoElement 实例”作为输出,你有什么想法可以解决这个问题吗?
    猜你喜欢
    • 2014-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-12
    • 1970-01-01
    • 2020-12-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多