Theo dõi thói quen: Tuần
Thuộc phần Dự án trong hành trình Flutter của Coddy. Bài học 29 trên 36.
Dưới mỗi cái tên là các ngày trong tuần: bảy vòng tròn nhỏ, từ thứ Hai đến Chủ nhật, được tô màu vào những ngày bạn đã thực hiện. Mỗi vòng tròn là một widget riêng, DayCircle, có nhãn và trạng thái hoàn thành.
Một vòng tròn là một Container có kích thước cố định và BoxDecoration có shape là BoxShape.circle. Màu của nó lấy từ giao diện, nên khớp với màu xanh lá của ứng dụng, và sau này trong chế độ tối, màu sẽ tự thay đổi:
final colors = Theme.of(context).colorScheme;
...
color: done ? colors.primary : colors.surfaceContainerHighest,Văn bản trên nền có màu sẽ dùng màu tương ứng trong bảng màu: onPrimary trên primary, onSurfaceVariant trên nền xám. Ghép các màu này với nhau để văn bản luôn dễ đọc.
Bảy vòng tròn nằm trong một Row với MainAxisAlignment.spaceBetween, nên chúng trải đều trên thẻ. Tạo chúng bằng vòng lặp đếm for: dayNames[i] là nhãn, còn habit.days[i] cho biết ngày đó đã hoàn thành hay chưa.
Thử thách
Trung bìnhHiển thị tuần:
- viết một widget
DayCirclevớilabelvàdonelà các thuộc tínhrequired: một hình tròn 40 x 40 dùng màuprimarykhi hoàn thành và màusurfaceContainerHighestkhi chưa hoàn thành, với nhãn căn giữa, in đậm, cỡ 11, dùng màuonPrimaryhoặconSurfaceVariant - trong
HabitCard, bên dưới tên và khoảng cách 12 pixel, thêm mộtRowphân bố đều vớispaceBetween, gồm bảyDayCircle
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.green),
),
home: const HabitScreen(),
);
}
}
const List<String> dayNames = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
class Habit {
Habit(this.name, this.days);
final String name;
final List<bool> days;
}
class HabitScreen extends StatefulWidget {
const HabitScreen({super.key});
@override
State<HabitScreen> createState() => _HabitScreenState();
}
class _HabitScreenState extends State<HabitScreen> {
final List<Habit> _habits = [
Habit('Drink water', [true, true, true, false, true, false, false]),
Habit('Read 10 pages', [true, false, true, true, false, false, false]),
Habit('Stretch', List.filled(7, false)),
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Habits')),
body: ListView(
padding: const EdgeInsets.fromLTRB(16, 8, 16, 88),
children: [
for (Habit habit in _habits) HabitCard(habit: habit),
],
),
);
}
}
class HabitCard extends StatelessWidget {
const HabitCard({super.key, required this.habit});
final Habit habit;
@override
Widget build(BuildContext context) {
final textTheme = Theme.of(context).textTheme;
return Card(
margin: const EdgeInsets.only(top: 12),
clipBehavior: Clip.antiAlias,
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(habit.name, style: textTheme.titleMedium),
],
),
),
);
}
}
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
1Dự án: Danh sách việc cần làm
Danh sách việc cần làm: Danh sách công việcDanh sách việc cần làm: Thêm công việc4Dự án: Theo dõi thói quen
Theo dõi thói quen: Thói quen của bạnTheo dõi thói quen: TuầnTự luyện tập: Trình biên dịch Flutter online