In this mini project, we'll build a simple Habit Tracker UI. Users can enter a habit name and tap Add, see habits listed, and tap one to increase its completed count. This project lets you practice TextField, Button, List, setState, and basic layout all in one place.
dart
class HabitTracker extends StatefulWidget {
const HabitTracker({super.key});
@override
State<HabitTracker> createState() => _HabitTrackerState();
}
class _HabitTrackerState extends State<HabitTracker> {
final controller = TextEditingController();
final List<Map<String, dynamic>> habits = [];
void addHabit() {
final name = controller.text.trim();
if (name.isEmpty) return;
setState(() {
habits.add({'name': name, 'done': 0});
controller.clear();
});
}
void completeHabit(int index) {
setState(() {
habits[index]['done']++;
});
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Habit Tracker')),
body: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
TextField(
controller: controller,
decoration: const InputDecoration(
labelText: 'New habit',
border: OutlineInputBorder(),
),
),
const SizedBox(height: 12),
ElevatedButton(
onPressed: addHabit,
child: const Text('Add Habit'),
),
const SizedBox(height: 20),
Expanded(
child: ListView.builder(
itemCount: habits.length,
itemBuilder: (context, index) {
final habit = habits[index];
return Card(
child: ListTile(
title: Text(habit['name']),
subtitle: Text("Completed: ${habit['done']} times"),
trailing: const Icon(Icons.check_circle_outline),
onTap: () => completeHabit(index),
),
);
},
),
),
],
),
),
);
}
}You should see
The Habit Tracker screen appears, letting you add new habits. Every tap on a habit card increases its Completed count.Next Steps
You can keep expanding this project by adding a delete button, a completed filter, a local database, notification reminders, or a dark mode toggle.