Как отредактировать выбранный элемент из списка в flutter

#flutter #dart #flutter-layout

#flutter #dart #flutter-layout

Вопрос:

Я пытался добавить функцию редактирования в свой список дел, в котором пользователь может выбрать элемент, который он хочет отредактировать, затем должно появиться диалоговое окно, в котором есть текстовое поле для ввода нового значения выбранного элемента и кнопка, которая сохраняет изменения. В настоящее время у меня есть функция, которая вызывает массив, в котором хранятся задачи, затем предполагается, что она запускает выбранный элемент с использованием индекса, чтобы в конце этому выбранному значению можно было присвоить новое значение при нажатии, смотрите эту функцию редактирования как в instagrams one, за исключением того, что она редактирует текст.

Проблема возникает при вызове этой функции с помощью кнопки редактирования диалогового окна, потому что я делаю это следующим образом 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()
            ]
          ), 
                 
        ),
    );
  }
}

  

Если у вас есть какие-либо вопросы, пожалуйста, дайте мне знать в комментариях;)

Ответ №1:

Вы можете скопировать вставить запустить полный код ниже,
который вы можете предоставить index , чтобы _editDialog затем _editToDoItem получить index
фрагмент кода

 _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()
        ]),
      ),
    );
  }
}
  

Комментарии:

1. Привет!!! ваш код сработал, есть ли другой способ вызвать _controller.text, чтобы он не изменял ввод addtoDoItem?, потому что при редактировании он также изменяет значение текстового поля, когда оно должно оставаться пустым

2. вы можете использовать два TextEditingController, смотрите обновленный полный код

3. причина в том, что два текстовых поля используют один и тот же TextEditController.

4. Я только что понял, что для того, чтобы текстовое поле редактирования выбранного элемента содержало текст выбранного элемента внутри, что я должен сделать? Я думал об использовании TextEditingController для этого…

5. Я пытаюсь использовать hintText: '${_toDoItem[index]}' в hintText текстового поля диалогового окна и получаю на выходе «экземпляр ToDoElement», у вас есть какие-либо идеи по этому поводу?