Day 19 | 万年范例-TodoList(2)

回到昨天留下的问题

  1. card数太长要怎麽办
  2. 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);
    },
  )

这样我们就能完成了删除功能了~

https://ithelp.ithome.com.tw/upload/images/20211002/20112906zmxGY8JkXV.png

现在的程序码开始变得有点复杂,所以还是上传到github 供大家参考。
https://github.com/zxc469469/flutter_todo_list/tree/Day19


<<:  Day16【Web】网路攻击:连线劫持/Cookie 窃取

>>:  Day17 - Ruby 的阵列处理入门

Day 29 注册ASN必要的几个object

那今天呢,我们来讲解一下请LIR注册ASN需要几个重要的Object 首先,我们这边是以RIPE为例...

33岁转职者的前端笔记-DAY 21 英寸转公分单位转换器练习笔记

基本语法笔记 四舍五入: Math.round(); 无条件进位: Math.ceil(); 无条件...

[进阶指南] Fragments( Day23 )

React 其中一种常见的使用情况是在一个 component 中回传多个 element,fra...

近似最短路径 (9)

11.9 赋距空间与 L1 嵌入的 Bourgain 定理 图上的距离也满足赋距空间(metric ...

[第29天]理财达人Mx. Ada-布林通道(Bollinger Band)

前言 本文说明使用TA-Lib函式库计算及呈现布林通道。 布林通道 布林通道(Bollinger B...