מעקב הרגלים: רצף
חלק מהיחידה פרויקטים במסלול ה-Flutter של Coddy. שיעור 32 מתוך 36.
רצפים גורמים לאנשים לחזור: ימים רצופים מרגישים כמו משהו שכדאי להגן עליו. כאן הרצף הוא רצף הימים הארוך ביותר שבהם ההרגל בוצע במהלך השבוע. שתיית מים, שבוצעה מיום שני עד יום רביעי וביום שישי, מגיעה לרצף של 3 ימים.
כדי לספור רצף, עוברים על הימים לפי הסדר עם שני מספרים: run, מספר הימים הרצופים עד כה, ו-best, הרצף הארוך ביותר שנצפה. יום שבו ההרגל בוצע מוסיף לרצף; יום שבו ההרגל לא בוצע מאפס אותו ל-0.
int get streak {
int best = 0;
int run = 0;
for (bool day in days) {
if (day) {
run++;
if (run > best) best = run;
} else {
run = 0;
}
}
return best;
}החזר את best, ולא את run: בסוף הלולאה, run הוא רק הרצף האחרון, והוא 0 אם יום ראשון הוא יום שבו ההרגל לא בוצע.
הצג אותו מתחת לשבוע עם סמל של להבה: בכתום כשיש רצף, ובאפור של outline של ערכת העיצוב כשאין רצף. "רצף של 0 ימים" נשמע מוזר, אז במקרה כזה כתוב "עדיין אין רצף".
אתגר
קשההצגת רצפים:
- הוסיפו את ה־getter
streakל־Habit - מתחת לשבוע, אחרי 12 פיקסלים, הוסיפו
Row:Icons.local_fire_departmentבגודל 20 (בכתום כשהרצף גדול מ־0, וב־outlineשל ערכת הנושא אחרת), 4 פיקסלים והטקסט - הטקסט הוא
3 day streak(עם המספר האמיתי), אוNo streak yetכשמדובר ב־0
נסו בעצמכם
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;
int get done => days.where((day) => day).length;
}
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: [
Row(
children: [
Expanded(child: Text(habit.name, style: textTheme.titleMedium)),
Text('${habit.done} of 7 days', style: textTheme.bodySmall),
],
),
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,
),
),
),
);
}
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה פרויקטים
תרגלו בעצמכם: קומפיילר Flutter אונליין