Давайте настроим управление состоянием на нижнем листе Flutter.
Я работал над приложением Flutter to do, когда понял, что хочу переместить свой NewToDo
виджет в showModalBottomSheet
. Вот гифка текущего пользовательского интерфейса.
В идеале, когда пользователь вводит что-либо в поле title
, кнопка «Добавить к выполнению» должна быть включена.
Проблема, с которой я столкнулся, заключалась в том, что значение состояния для title
управлялось в виджете MyApp
(потому что я также разрешаю функции редактирования, а кнопка редактирования не является частью моего NewToDo
), и по какой-то причине NewToDo
не улавливал обновленное состояние. Я спросил об этом в StackOverflow и получил довольно лаконичное решение.
Вот код для FloatingActionButton
в MyApp
:
floatingActionButton: FloatingActionButton( onPressed: () { showModalBottomSheet<void>( context: context, builder: (BuildContext context) { return NewToDo(titleController, contentController, _addTodo, _clear, _todo); }); } }, child: const Icon(Icons.add), backgroundColor: Colors.deepPurple, ),
По сути, происходило то, что NewToDo
мог узнать, когда состояние изменилось с момента передачи.
Я знал это, потому что, хотя кнопка не включалась, когда вы что-то набирали в поле ввода текста заголовка, если я что-то набирал, а затем закрывал модальное окно и снова открывал его, кнопка была бы активна.
Проблема заключалась в том, что NewToDo
не знал, что нужно повторно выполнить рендеринг, потому что он заключен в showModalBottomSheet
и builder
.
builder
- это используемый обратный вызов, который в основном получает или строит дочерний виджет. Это свойство можно увидеть на многих виджетах, и его можно использовать для возврата дочернего виджета без необходимости импорта и создания экземпляра виджета без состояния.
Поскольку NewToDo
заключен в другой построитель и имеет другой контекст, чем родительский виджет, NewToDo
не перестраивается при обновлении состояния.
Итак, как я это обошел? Следует упомянуть, что в моем виджете NewToDo
я использую TextField
для захвата данных заголовка.
А в моем виджете TextField
используйте TextEditingController
, чтобы отслеживать значения, помещаемые в заголовок TextField
. Этот контроллер доступен для прослушивания, что означает, что его можно использовать, чтобы сообщить клиенту, что объект обновлен (т. Е. Состояние).
Подробнее о
TextField
иTextEditingController
и управлении состоянием читайте в моем предыдущем сообщении в блоге.
Так что все, что мне нужно сделать, это обернуть NewToDo
, это то, что называется ValueListenableBuilder
. Это означает, что этот builder
может перестроить своего дочернего элемента (в данном случае NewToDo
), если значение, которое он прослушивает, изменяется.
Вот как выглядит наш обновленный FloatingActionButton
:
floatingActionButton: FloatingActionButton( onPressed: () { showModalBottomSheet<void>( context: context, builder: (BuildContext context) { return ValueListenableBuilder( valueListenable: titleController, builder: (context, _content, child) { return NewToDo(titleController, contentController, _addTodo, _clear, _todo); }); }); }, child: const Icon(Icons.add), backgroundColor: Colors.deepPurple, ),
Эта обновленная часть нашего FloatingActionButton
оборачивает наш NewToDo
виджет в ValueListenableBuilder
, который имеет titleController
в качестве значения для свойства valueListenable
.
Это означает, что наш конструктор будет специально прислушиваться к обновлениям нашего titleController
, который является экземпляром TextEditingController
, присвоенным заголовку TextField
.
У меня также есть еще одно свойство builder
, которое позволяет нам создавать дочерний виджет внутри ValueListenableBuilder
, заключенного в слушатель. В нашем случае дочерний виджет NewToDo
.
Давайте посмотрим, как работает наше приложение, когда я использовал ValueListenableBuilder
:
Теперь у нас есть построитель, который ожидает обновления определенного значения и NewToDo
обновляет вместе со значением состояния MyApp
title
. Идеально!
Вы видели, как я решил одну из задач для приложения со списком дел. Следите за обновлениями, и я расскажу о некоторых других проблемах, с которыми я столкнулся, и о том, как я их решил!
Весь код этого руководства находится на GitHub.
Обновите бесплатную подписку на Medium до платной, и всего за 5 долларов в месяц вы получите неограниченное количество рассказов от тысяч писателей без рекламы. Это партнерская ссылка, и часть вашего членства помогает мне получать вознаграждение за контент, который я создаю. Спасибо!