Rastreador de hábitos: Marca un día
Parte de la sección Proyectos del Journey de Flutter de Coddy. Lección 30 de 36.
Toca un círculo para marcar el día; tócalo de nuevo para desmarcarlo. Los hábitos están en el estado de la pantalla, pero el círculo se dibuja en lo más profundo de un HabitCard. El toque tiene que subir hasta donde están los datos.
Eso es elevar el estado mediante devoluciones de llamada. La pantalla controla el cambio:
void _toggle(Habit habit, int day) {
setState(() {
habit.days[day] = !habit.days[day];
});
}Le pasa a cada tarjeta una función, onToggle: (day) => _toggle(habit, day). El tipo de la tarjeta para esta función es void Function(int day), una función que recibe el número del día. Cada círculo recibe un VoidCallback sencillo, onTap: () => onToggle(i), y envuelve su Container en un GestureDetector que la llama.
!habit.days[day] invierte un bool: true pasa a ser false y viceversa, así que una sola función sirve tanto para marcar como para desmarcar.
Desafío
DifícilMarca los días:
- añade el método
_toggleal estado de la pantalla - asigna a
HabitCardunonTogglerequiredde tipovoid Function(int day)y pasa(day) => _toggle(habit, day) - asigna a
DayCircleunVoidCallback onTaprequired, envuelve suContaineren unGestureDetectory pasa() => onToggle(i)
Pruébalo tú mismo
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),
const SizedBox(height: 12),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
for (int i = 0; i < 7; i++) DayCircle(label: dayNames[i], done: habit.days[i]),
],
),
],
),
),
);
}
}
class DayCircle extends StatelessWidget {
const DayCircle({super.key, required this.label, required this.done});
final String label;
final bool done;
@override
Widget build(BuildContext context) {
final colors = Theme.of(context).colorScheme;
return 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,
),
),
);
}
}
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Proyectos
1Proyecto: Lista de tareas
Lista de tareas: La lista de tareasLista de tareas: Añadir una tarea4Proyecto: Rastreador de hábitos
Rastreador de hábitos: Tus hábitosRastreador de hábitos: La semana2Proyecto: Cuestionario
Cuestionario: La preguntaCuestionario: Correcto o incorrectoPractica por tu cuenta: Compilador de Flutter online