Fitness Dashboard
Loading preview
Starting the Flutter app
A showcase of Flutter's fitness dashboard functionality
import 'package:flutter/material.dart';
const _stats = [
{'label': 'Steps', 'value': '8,432', 'target': '10,000', 'icon': Icons.directions_walk},
{'label': 'Calories', 'value': '1,240', 'target': '2,000', 'icon': Icons.local_fire_department},
{'label': 'Active', 'value': '45', 'unit': 'min', 'icon': Icons.timer},
];
class FitnessDashboard extends StatelessWidget {
const FitnessDashboard({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Fitness Dashboard')),
body: ListView(
padding: const EdgeInsets.all(16),
children: [
Card(
color: Theme.of(context).colorScheme.primaryContainer,
child: Padding(
padding: const EdgeInsets.all(20),
child: Column(
children: [
Text('Today\'s Progress',
style: Theme.of(context).textTheme.titleMedium),
const SizedBox(height: 8),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
_StatChip(label: 'Workouts', value: '2'),
_StatChip(label: 'Rest', value: '6h'),
],
),
],
),
),
),
const SizedBox(height: 16),
..._stats.map((s) => Card(
margin: const EdgeInsets.only(bottom: 12),
child: ListTile(
leading: CircleAvatar(
child: Icon(s['icon'] as IconData),
),
title: Text(s['label'] as String),
subtitle: s['target'] != null
? Text('Target: ${s['target']}')
: null,
trailing: Text(
[s['value'], ?s['unit']].join(' '),
style: Theme.of(context).textTheme.titleLarge,
),
),
)),
const SizedBox(height: 16),
Text('Quick Actions', style: Theme.of(context).textTheme.titleMedium),
const SizedBox(height: 8),
Row(
children: [
Expanded(
child: FilledButton.icon(
onPressed: () => _showDemo(context, 'Start Workout (demo)'),
icon: const Icon(Icons.play_arrow),
label: const Text('Start Workout'),
),
),
const SizedBox(width: 8),
Expanded(
child: OutlinedButton.icon(
onPressed: () => _showDemo(context, 'Log (demo)'),
icon: const Icon(Icons.add),
label: const Text('Log'),
),
),
],
),
],
),
);
}
}
class _StatChip extends StatelessWidget {
final String label;
final String value;
const _StatChip({required this.label, required this.value});
@override
Widget build(BuildContext context) {
return Column(
children: [
Text(value, style: Theme.of(context).textTheme.headlineSmall),
Text(label, style: Theme.of(context).textTheme.bodySmall),
],
);
}
}
void _showDemo(BuildContext context, String message) {
ScaffoldMessenger.of(context)
..hideCurrentSnackBar()
..showSnackBar(SnackBar(content: Text(message)));
}
Add it to your project
Copies the Dart source into your app, so you own it. Flutter SDK only, no extra packages.
First time? Run dart pub global activate fluttertemplates_dev, or read the CLI guide.
How it works
A summary card built from two _StatChips sits above _stats, rendered as ListTiles. Entries differ in shape: Steps and Calories have a target, while Active has a unit, so s['target'] != null decides on a subtitle. Trailing text joins value and unit with a space, giving 45 min. All figures are hardcoded, and the two quick action buttons show a demo SnackBar.
Adapting it
- Replace
_statswith data from a package likehealth, which reads HealthKit and Health Connect. - Make
valueandtargetnumeric so each row can show aLinearProgressIndicator. - Wire
Start WorkoutandLogto your own routes.