Day 20 | 万年范例-TodoList(3)

那今天就继续来扩充这个小专案的功能,我们现在可以新增及删除了,那今天就来实作更换卡片的状态好了。

首先我们来新增一个值 isDone 来表示todo是否被完成了

class TodoModel {
  final String content;
  bool isDone;

  TodoModel({required this.content, this.isDone = false});
  void toggleStatus() {
    isDone = !isDone;
  }
}

因为每次新增一个todo时应该都会是未完成的,所以这边就直接带入预设值,然後写一个method toggleStatus 方便我们切换状态时不用每次写 todo.isDone = !todo.isDone

然後来实作改变这个值的function

void _handleToggleStatus(int hashCode) {
    setState(() {
      _todoList = _todoList.map((todo) {
        if (todo.hashCode == hashCode) {
          todo.toggleStatus();
          return todo;
        } else {
          return todo;
        }
      }).toList();
    });
  }

这段程序码因为是使用 hashcode 来access,而且外面是一个 List 所以这段才会看起来如此复杂。

然後来修改 TodoCard 的样式,首先新增一个参数 isDone ,然後记得在constructor 新增这个参数,之後到我们widget这里,我是采用 Opacity 这个widget来让我们来表示完成时卡片会变半透明。

Padding(
      padding: const EdgeInsets.all(8.0),
      child: Opacity(
        opacity: isDone ? 0.2 : 1.0,
        child: Container(
          alignment: Alignment.centerLeft,
          constraints: const BoxConstraints(minHeight: 48),
          width: 300,
          padding: const EdgeInsets.fromLTRB(16.0, 8.0, 16.0, 8.0),
          child: Text(
            '#$index: $todoContent',
          ),
          decoration: BoxDecoration(
            border: Border.all(),
            borderRadius: BorderRadius.circular(8),
          ),
        ),
      ),
    );

然後记得到回圈那边,多传入 isDone ,这边我是利用点击卡片本身来切换完成状态,所以这边直接多包一层 GestureDetector

GestureDetector(
    child: TodoCard(
        todoContent: entity.value.content,
        index: entity.key,
        isDone: entity.value.isDone),
    onTap: () {
      handleToggleStatus(entity.value.hashCode);
    },
  ),

既然我们有两种状态的卡片了那就来做一个简单筛选器的功能,为了方便扩充筛选器的功能这边就直接新增一个class

class TodoFliterModel {
  bool isDone;
  TodoFliterModel({this.isDone = false});
}

然後实例化它及实作这个功能

final TodoFliterModel _todoFilter = TodoFliterModel();

void _handleFilteTodoStatue() {
    setState(() {
      _todoFilter.isDone = !_todoFilter.isDone;
    });
  }

再来新增这颗切换的按钮

GestureDetector(
    child: Padding(
      padding: const EdgeInsets.all(8.0),
      child: Container(
        alignment: Alignment.center,
        width: 120,
        height: 36,
        child: const Text('切换完成状态'),
        decoration: BoxDecoration(
          border: Border.all(),
          borderRadius: BorderRadius.circular(4),
        ),
      ),
    ),
    onTap: () {
      _handleFilteTodoStatue();
    },
  ),

然後再将我们的标题改为

Text(
  '目前' + (_todoFilter.isDone ? '已完成' : '未完成') + '的Todo:',
  style: Theme.of(context).textTheme.headline5,
),

https://ithelp.ithome.com.tw/upload/images/20211003/20112906qO6aCdeQ89.png

今天的程序码

https://github.com/zxc469469/flutter_todo_list/tree/Day20

感觉功能都差不多了,明天来试着运用装态管理的套件看看好了。


<<:  [day29] - Angular Component to Web Component

>>:  自动化 End-End 测试 Nightwatch.js 之踩雷笔记:iframe

Day34. 范例:歌曲排行(迭代器模式)

本文同步更新於blog 需求一:KTV系统要按照新增到系统的时间,由旧到新,实作歌曲排行 定义系统...

【17】训练到一半遇到 nan 吗? 梯度爆炸与梯度消失的测试实验

Colab连结 今天大家介绍 Gradient Exploding (梯度爆炸) 与 Gradien...

香港政府旗下的创科生活基金,如何申请,申请资格细观

fundable.hk 实测创科局旗下创科生活基金 (FBL)开发 ”人工智能” App睇真D 资料...

第 08 天 再接再厉坚持不懈( leetcode 300 347 )

https://leetcode.com/problems/longest-increasing-...

Dungeon Mizarka 002

测试场景设定 传统的FP Dungeon Crawler(FPDC)撇开玩家的视角,玩家的移动实际上...