Menu
CoddyTech

Danh sách việc cần làm: Công việc còn lại

Thuộc phần Dự án trong hành trình Flutter của Coddy. Bài học 4 trên 36.

Chỉ cần nhìn qua màn hình, bạn sẽ biết còn bao nhiêu việc cần làm. Câu trả lời là số việc chưa hoàn thành, và mỗi lần dựng màn hình, bạn có thể tính số đó từ danh sách.

Getter là nơi thích hợp để làm việc này. Getter trông giống thuộc tính nhưng chạy code mỗi khi bạn dùng, nên luôn cập nhật:

int get _left => _tasks.where((task) => !task.done).length;

Không cần thêm biến để giữ cho số liệu luôn khớp, cũng không cần setState riêng: khi đánh dấu một việc, ứng dụng đã gọi setState, màn hình được dựng lại và getter đếm lại.

Một chi tiết giúp câu chữ tự nhiên hơn: "1 task left" chứ không phải "1 tasks left". Câu lệnh điều kiện sẽ chọn cách diễn đạt phù hợp.

challenge icon

Thử thách

Trung bình

Hiển thị số việc còn lại:

  • thêm getter _left để đếm số việc chưa hoàn thành
  • giữa trường nhập liệu và danh sách, hiển thị số việc còn lại bằng Text, chẳng hạn như 3 tasks left, trong một Row có phần đệm 16 pixel ở hai bên và 8 pixel ở phía trên lẫn phía dưới
  • nếu chỉ còn đúng một việc, hiển thị 1 task left

Tự làm thử

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.teal),
      ),
      home: const TodoScreen(),
    );
  }
}

class Task {
  Task(this.title);

  final String title;
  bool done = false;
}

class TodoScreen extends StatefulWidget {
  const TodoScreen({super.key});

  @override
  State<TodoScreen> createState() => _TodoScreenState();
}

class _TodoScreenState extends State<TodoScreen> {
  final List<Task> _tasks = [Task('Buy milk'), Task('Walk the dog'), Task('Read a book')];
  final _controller = TextEditingController();

  void _addTask() {
    setState(() {
      _tasks.add(Task(_controller.text));
    });
    _controller.clear();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('My Tasks')),
      body: Column(
        children: [
          Padding(
            padding: const EdgeInsets.fromLTRB(16, 16, 16, 8),
            child: Row(
              children: [
                Expanded(
                  child: TextField(
                    controller: _controller,
                    decoration: const InputDecoration(
                      labelText: 'New task',
                      border: OutlineInputBorder(),
                    ),
                  ),
                ),
                const SizedBox(width: 8),
                IconButton.filled(
                  onPressed: _addTask,
                  icon: const Icon(Icons.add),
                ),
              ],
            ),
          ),
          Expanded(
            child: ListView.builder(
              itemCount: _tasks.length,
              itemBuilder: (context, index) {
                final task = _tasks[index];
                return ListTile(
                  leading: Checkbox(
                    value: task.done,
                    onChanged: (value) {
                      setState(() {
                        task.done = value!;
                      });
                    },
                  ),
                  title: Text(
                    task.title,
                    style: task.done
                        ? const TextStyle(
                            decoration: TextDecoration.lineThrough,
                            color: Colors.grey,
                          )
                        : null,
                  ),
                );
              },
            ),
          ),
        ],
      ),
    );
  }
}
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Dự án

Tự luyện tập: Trình biên dịch Flutter online