回到昨天留下的問題
TextFiled
送出後怎麼清除裡面的字其實只要將 SingleChildScrollView
wrap住 center
就可以,SingleChildScrollView
可以讓widget超出容器尺寸(以這個例子來說是裝置高度)時將它變成一個滾動式的元件。
從名字上也看得出來他只接受一個child,所以大部分時候都是用在元件較小的情況下使用,但其實還是可以像這次用結合 Column
來接受複數的widgets,但實際上還是有其他widget可以達成這些需求像是 ListView
。
至於TextFiled
送出後怎麼清除裡面的字,在TextFiled
中有一個參數是 controller
。在 flutter 中蠻多互動的元件都有這個參數,來方便我們對一些互動行為有更多細節的操作,我覺得可以想像成類似 react 的 ref 的感覺。那我們就直接原本的 _MyHomePageState
裡宣告我們的控制器。
final TextEditingController _textEditingController = TextEditingController();
然後將這個 _textEditingController
給我們的 TextFiled
TextField(
decoration: const InputDecoration(labelText: '待辦事項'),
onSubmitted: (input) {
_handleAddNewTodo(input);
},
controller: _textEditingController,
),
接下來回到 _handleAddNewTodo
這個function裡
void _handleAddNewTodo(String input) {
setState(() {
_todoList = [..._todoList, input];
_textEditingController.text = '';
});
}
這時我只要在更新完 _todoList
後將 _textEditingController.text = ''
即可。
那接下來我們就來擴充這個TodoList的功能,為了之後著想所以我們的Todo應該不能只是一個 String
,所以我們先建立一個 class
來表示 Todo 。
首先先建立一個檔案 todo_model.dart
class TodoModel {
final String content;
TodoModel({required this.content});
}
然後將原本的 _todoList
改成 List<TodoModel>
List<TodoModel> _todoList = [TodoModel(content: '123')];
然後將剩下的部分都改為使用這個 class
// 迴圈渲染部分
TodoCard(
todoContent: entity.value.content,
index: entity.key,
),
// setState的部分
_todoList = [..._todoList, TodoModel(content: input)];
然後接下來先來新增移除按鈕的UI
..._todoList.asMap().entries.map(
(entity) => Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TodoCard(
todoContent: entity.value.content,
index: entity.key,
),
GestureDetector(
child: const Icon(Icons.remove),
)
],
),
),
我們將原本迴圈裡改用 Row
然後新增一個 GestureDetector
包住 Icon
GestureDetector
就是將他的child新增一些事件監聽的功能。Icon
則是一個顯示icon的widget, Icons
則是material 提供的一些常用Icon圖案。
接下來我們就來實作刪除功能
void _handleRemoveTodo(int hashCode) {
setState(() {
_todoList =
_todoList.while((value) => value.hashCode != hashCode).toList();
});
}
hashCode
是每個 instance 都有的屬性所以我們就直接拿來當作唯一識別的id。
while
類似於JS的 array.filter
當裡面的function是 ture
時則會回傳這個 value
所以整行的意思就是當 hashCode
不等於我傳入的 hashCode
都要回傳,也就是不回傳我要刪除的那個instance 。
只後再回到 GestureDetector
GestureDetector(
child: const Icon(Icons.remove),
onTap: () {
_handleRemoveTodo(entity.value.hashCode);
},
)
這樣我們就能完成了刪除功能了~
現在的程式碼開始變得有點複雜,所以還是上傳到github 供大家參考。
https://github.com/zxc469469/flutter_todo_list/tree/Day19