습관 추적기: 한 주
Coddy Flutter 여정의 프로젝트 섹션에 포함된 레슨. 36개 중 29번째.
각 이름 아래에는 일주일이 표시됩니다. 월요일부터 일요일까지 작은 원 일곱 개가 있고, 해당하는 일을 한 날에는 원이 채워집니다. 각 원은 레이블과 완료 여부를 표시하는 DayCircle라는 작은 위젯입니다.
원은 크기가 고정된 Container이며, shape가 BoxShape.circle인 BoxDecoration을 사용합니다. 색상은 테마에서 가져오므로 앱의 녹색과 어울리고, 나중에 다크 모드에서는 색상이 자동으로 바뀝니다.
final colors = Theme.of(context).colorScheme;
...
color: done ? colors.primary : colors.surfaceContainerHighest,색이 있는 배경 위의 텍스트는 색상 구성표에서 어울리는 색을 사용합니다. primary에는 onPrimary를, 회색에는 onSurfaceVariant를 사용합니다. 두 색을 짝지으면 텍스트를 언제나 읽기 쉽습니다.
원 일곱 개는 MainAxisAlignment.spaceBetween을 사용하는 Row로 배치하여 카드 전체에 고르게 펼쳐집니다. 횟수를 세는 for 반복문으로 원을 만들면 됩니다. dayNames[i]는 레이블이고, habit.days[i]는 완료 여부입니다.
챌린지
중급한 주를 표시하세요:
requiredlabel과done을 사용하는DayCircle위젯을 작성하세요. 완료된 경우primary, 완료되지 않은 경우surfaceContainerHighest를 사용하는 40×40 크기의 원을 만들고, 가운데에 굵기 11 크기의 라벨을onPrimary또는onSurfaceVariant색상으로 표시하세요.HabitCard에서 이름 아래에 12픽셀 간격을 두고,spaceBetween으로 펼쳐진Row에DayCircle7개를 추가하세요.
직접 해보기
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),
],
),
),
);
}
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
프로젝트의 모든 레슨
직접 연습해 보세요: 온라인 Flutter 컴파일러