mirror of
https://github.com/flutter/samples.git
synced 2026-04-06 19:52:04 +00:00
Flutter 3.29 beta (#2571)
This commit is contained in:
207
pedometer/example/lib/main.dart
Normal file
207
pedometer/example/lib/main.dart
Normal file
@@ -0,0 +1,207 @@
|
||||
import 'package:fl_chart/fl_chart.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
import 'steps_repo.dart';
|
||||
|
||||
void main() {
|
||||
runApp(const MyApp());
|
||||
}
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
const MyApp({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
title: 'Flutter Demo',
|
||||
theme: ThemeData(primarySwatch: Colors.blue),
|
||||
home: const Home(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class RoundClipper extends CustomClipper<Path> {
|
||||
@override
|
||||
Path getClip(Size size) {
|
||||
final diameter = size.shortestSide * 1.5;
|
||||
final x = -(diameter - size.width) / 2;
|
||||
final y = size.height - diameter;
|
||||
final rect = Offset(x, y) & Size(diameter, diameter);
|
||||
return Path()..addOval(rect);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldReclip(CustomClipper<Path> oldClipper) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class Home extends StatefulWidget {
|
||||
const Home({super.key});
|
||||
|
||||
@override
|
||||
State<Home> createState() => _HomeState();
|
||||
}
|
||||
|
||||
class _HomeState extends State<Home> {
|
||||
var hourlySteps = <Steps>[];
|
||||
DateTime? lastUpdated;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
runPedometer();
|
||||
super.initState();
|
||||
}
|
||||
|
||||
void runPedometer() async {
|
||||
final now = DateTime.now();
|
||||
hourlySteps = await StepsRepo.instance.getSteps();
|
||||
lastUpdated = now;
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final textTheme = Theme.of(context).textTheme;
|
||||
|
||||
final barGroups =
|
||||
hourlySteps
|
||||
.map(
|
||||
(e) => BarChartGroupData(
|
||||
x: int.parse(e.startHour),
|
||||
barRods: [
|
||||
BarChartRodData(
|
||||
color: Colors.blue[900],
|
||||
toY: e.steps.toDouble() / 100,
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
|
||||
return Scaffold(
|
||||
body: Stack(
|
||||
children: [
|
||||
ClipPath(
|
||||
clipper: RoundClipper(),
|
||||
child: FractionallySizedBox(
|
||||
heightFactor: 0.55,
|
||||
widthFactor: 1,
|
||||
child: Container(color: Colors.blue[300]),
|
||||
),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.topCenter,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(80.0),
|
||||
child: Column(
|
||||
children: [
|
||||
lastUpdated != null
|
||||
? Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 50.0),
|
||||
child: Text(
|
||||
DateFormat.yMMMMd('en_US').format(lastUpdated!),
|
||||
style: textTheme.titleLarge!.copyWith(
|
||||
color: Colors.blue[900],
|
||||
),
|
||||
),
|
||||
)
|
||||
: const SizedBox(height: 0),
|
||||
Text(
|
||||
hourlySteps.fold(0, (t, e) => t + e.steps).toString(),
|
||||
style: textTheme.displayMedium!.copyWith(
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'steps',
|
||||
style: textTheme.titleLarge!.copyWith(color: Colors.white),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: GestureDetector(
|
||||
onTap: runPedometer,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(20.0),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.blue[900],
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.all(8.0),
|
||||
child: Icon(Icons.refresh, color: Colors.white, size: 50),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 30.0,
|
||||
vertical: 50.0,
|
||||
),
|
||||
child: AspectRatio(
|
||||
aspectRatio: 1.2,
|
||||
child: BarChart(
|
||||
BarChartData(
|
||||
titlesData: const FlTitlesData(
|
||||
show: true,
|
||||
// Top titles are null
|
||||
topTitles: AxisTitles(
|
||||
sideTitles: SideTitles(showTitles: false),
|
||||
),
|
||||
rightTitles: AxisTitles(
|
||||
sideTitles: SideTitles(showTitles: false),
|
||||
),
|
||||
leftTitles: AxisTitles(
|
||||
sideTitles: SideTitles(showTitles: false),
|
||||
),
|
||||
bottomTitles: AxisTitles(
|
||||
sideTitles: SideTitles(
|
||||
showTitles: true,
|
||||
reservedSize: 30,
|
||||
getTitlesWidget: getBottomTitles,
|
||||
),
|
||||
),
|
||||
),
|
||||
borderData: FlBorderData(show: false),
|
||||
barGroups: barGroups,
|
||||
gridData: const FlGridData(show: false),
|
||||
alignment: BarChartAlignment.spaceAround,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Axis labels for bottom of chart.
|
||||
Widget getBottomTitles(double value, TitleMeta meta) {
|
||||
final timeText = switch (value.toInt()) {
|
||||
0 => '12AM',
|
||||
6 => '6AM',
|
||||
12 => '12PM',
|
||||
18 => '6PM',
|
||||
_ => '',
|
||||
};
|
||||
return SideTitleWidget(
|
||||
space: 4,
|
||||
meta: meta,
|
||||
child: Text(
|
||||
timeText,
|
||||
style: TextStyle(fontSize: 14, color: Colors.blue[900]),
|
||||
),
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user