מעקב הרגלים: ימים שהושלמו
חלק מהיחידה פרויקטים במסלול ה-Flutter של Coddy. שיעור 31 מתוך 36.
קל לקרוא שבעה עיגולים, אבל מספר מהיר יותר לקריאה: "4 מתוך 7 ימים". מחשבים אותו לפי הימים, ולכן הוא שייך ל־Habit בתור getter:
int get done => days.where((day) => day).length;where משאיר את הפריטים שהתנאי שלו מאפשר לעבור. כאן התנאי הוא היום עצמו, מכיוון שכל יום הוא כבר true או false.
הציגו את הספירה בשורה של השם, מימין. Row עם השם בתוך Expanded דוחף את הספירה לקצה, ושם ארוך נשבר לשורה במקום לדחוק את הספירה אל מחוץ לכרטיס.
סימון כבר קורא ל־setState במסך, כך שכל הכרטיסים נבנים מחדש וכל ספירה נקראת שוב. אין צורך לחבר שום דבר נוסף.
אתגר
קלסופרים את הימים שהושלמו:
- הוסיפו את ה־getter
doneל־Habit - החליפו את השם ב־
HabitCardב־Row: השם בתוךExpanded, ואז4 of 7 days(עם המספר האמיתי) בתוךbodySmallשל ערכת העיצוב
נסו בעצמכם
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)),
];
void _toggle(Habit habit, int day) {
setState(() {
habit.days[day] = !habit.days[day];
});
}
@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,
onToggle: (day) => _toggle(habit, day),
),
],
),
);
}
}
class HabitCard extends StatelessWidget {
const HabitCard({super.key, required this.habit, required this.onToggle});
final Habit habit;
final void Function(int day) onToggle;
@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),
const SizedBox(height: 12),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
for (int i = 0; i < 7; i++)
DayCircle(
label: dayNames[i],
done: habit.days[i],
onTap: () => onToggle(i),
),
],
),
],
),
),
);
}
}
class DayCircle extends StatelessWidget {
const DayCircle({super.key, required this.label, required this.done, required this.onTap});
final String label;
final bool done;
final VoidCallback onTap;
@override
Widget build(BuildContext context) {
final colors = Theme.of(context).colorScheme;
return GestureDetector(
onTap: onTap,
child: Container(
width: 40,
height: 40,
alignment: Alignment.center,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: done ? colors.primary : colors.surfaceContainerHighest,
),
child: Text(
label,
style: TextStyle(
fontSize: 11,
fontWeight: FontWeight.bold,
color: done ? colors.onPrimary : colors.onSurfaceVariant,
),
),
),
);
}
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה פרויקטים
1פרויקט: רשימת משימות
רשימת משימות: רשימת המטלותרשימת משימות: הוספת מטלה4פרויקט: מעקב הרגלים
מעקב הרגלים: ההרגלים שלךמעקב הרגלים: השבועתרגלו בעצמכם: קומפיילר Flutter אונליין