Commit 9721c07a authored by Stefan Haslinger's avatar Stefan Haslinger

extract and refactor get tiles methods for staggered grid views

parent bdd97632
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_secure_storage","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_secure_storage-3.3.3/","dependencies":[]},{"name":"path_provider","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.8/","dependencies":[]},{"name":"shared_preferences","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/shared_preferences-0.5.7+2/","dependencies":[]},{"name":"sqflite","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/sqflite-1.3.0+1/","dependencies":[]},{"name":"uni_links","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/uni_links-0.4.0/","dependencies":[]},{"name":"url_launcher","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-5.4.7/","dependencies":[]}],"android":[{"name":"flutter_secure_storage","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_secure_storage-3.3.3/","dependencies":[]},{"name":"path_provider","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.8/","dependencies":[]},{"name":"shared_preferences","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/shared_preferences-0.5.7+2/","dependencies":[]},{"name":"sqflite","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/sqflite-1.3.0+1/","dependencies":[]},{"name":"uni_links","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/uni_links-0.4.0/","dependencies":[]},{"name":"url_launcher","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-5.4.7/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.4+2/","dependencies":[]},{"name":"shared_preferences_macos","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/shared_preferences_macos-0.0.1+8/","dependencies":[]},{"name":"sqflite","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/sqflite-1.3.0+1/","dependencies":[]},{"name":"url_launcher_macos","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_macos-0.0.1+5/","dependencies":[]}],"linux":[],"windows":[],"web":[{"name":"shared_preferences_web","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/shared_preferences_web-0.1.2+5/","dependencies":[]},{"name":"url_launcher_web","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_web-0.1.1+5/","dependencies":[]}]},"dependencyGraph":[{"name":"flutter_secure_storage","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos"]},{"name":"path_provider_macos","dependencies":[]},{"name":"shared_preferences","dependencies":["shared_preferences_macos","shared_preferences_web"]},{"name":"shared_preferences_macos","dependencies":[]},{"name":"shared_preferences_web","dependencies":[]},{"name":"sqflite","dependencies":[]},{"name":"uni_links","dependencies":[]},{"name":"url_launcher","dependencies":["url_launcher_web","url_launcher_macos"]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_web","dependencies":[]}],"date_created":"2020-06-05 10:51:21.595980","version":"1.17.0-4.0.pre.7"}
\ No newline at end of file
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_secure_storage","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_secure_storage-3.3.3/","dependencies":[]},{"name":"path_provider","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.8/","dependencies":[]},{"name":"shared_preferences","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/shared_preferences-0.5.7+2/","dependencies":[]},{"name":"sqflite","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/sqflite-1.3.0+1/","dependencies":[]},{"name":"uni_links","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/uni_links-0.4.0/","dependencies":[]},{"name":"url_launcher","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-5.4.7/","dependencies":[]}],"android":[{"name":"flutter_secure_storage","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_secure_storage-3.3.3/","dependencies":[]},{"name":"path_provider","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-1.6.8/","dependencies":[]},{"name":"shared_preferences","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/shared_preferences-0.5.7+2/","dependencies":[]},{"name":"sqflite","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/sqflite-1.3.0+1/","dependencies":[]},{"name":"uni_links","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/uni_links-0.4.0/","dependencies":[]},{"name":"url_launcher","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-5.4.7/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.4+2/","dependencies":[]},{"name":"shared_preferences_macos","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/shared_preferences_macos-0.0.1+8/","dependencies":[]},{"name":"sqflite","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/sqflite-1.3.0+1/","dependencies":[]},{"name":"url_launcher_macos","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_macos-0.0.1+5/","dependencies":[]}],"linux":[],"windows":[],"web":[{"name":"shared_preferences_web","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/shared_preferences_web-0.1.2+5/","dependencies":[]},{"name":"url_launcher_web","path":"/daten/flutter/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_web-0.1.1+5/","dependencies":[]}]},"dependencyGraph":[{"name":"flutter_secure_storage","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos"]},{"name":"path_provider_macos","dependencies":[]},{"name":"shared_preferences","dependencies":["shared_preferences_macos","shared_preferences_web"]},{"name":"shared_preferences_macos","dependencies":[]},{"name":"shared_preferences_web","dependencies":[]},{"name":"sqflite","dependencies":[]},{"name":"uni_links","dependencies":[]},{"name":"url_launcher","dependencies":["url_launcher_web","url_launcher_macos"]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_web","dependencies":[]}],"date_created":"2020-06-05 11:31:05.529634","version":"1.17.0-4.0.pre.7"}
\ No newline at end of file
......@@ -102,7 +102,7 @@ class _DashboardState extends State<Dashboard> {
);
} else {
return ListView(
padding: const EdgeInsets.only(top: 20),
padding: const EdgeInsets.all(20),
children: <Widget>[
for (Athlete athlete in athletes)
Card(
......
This diff is collapsed.
This diff is collapsed.
......@@ -30,6 +30,101 @@ class ShowLapScreen extends StatelessWidget {
final List<Lap> laps;
final Athlete athlete;
List<Widget> tiles({@required BuildContext context}) {
return <Widget>[
navigationButton(
title: 'Overview',
color: MyColor.settings,
icon: MyIcon.metaData,
context: context,
nextWidget: ({Lap lap}) => LapOverviewWidget(lap: lap),
),
navigationButton(
title: 'Heart Rate',
color: MyColor.navigate,
icon: MyIcon.heartRate,
context: context,
nextWidget: ({Lap lap}) => LapHeartRateWidget(lap: lap),
),
navigationButton(
title: 'Power',
color: MyColor.navigate,
icon: MyIcon.power,
context: context,
nextWidget: ({Lap lap}) => LapPowerWidget(lap: lap),
),
navigationButton(
title: 'Power Duration',
color: MyColor.navigate,
icon: MyIcon.powerDuration,
context: context,
nextWidget: ({Lap lap}) => LapPowerDurationWidget(lap: lap),
),
navigationButton(
title: 'Ecor',
color: MyColor.navigate,
icon: MyIcon.power,
context: context,
nextWidget: ({Lap lap}) => LapEcorWidget(
lap: lap,
athlete: athlete,
),
),
navigationButton(
title: 'Ground Time',
color: MyColor.navigate,
icon: MyIcon.groundTime,
context: context,
nextWidget: ({Lap lap}) => LapGroundTimeWidget(lap: lap),
),
navigationButton(
title: 'Leg Spring Stiffness',
color: MyColor.navigate,
icon: MyIcon.legSpringStiffness,
context: context,
nextWidget: ({Lap lap}) => LapLegSpringStiffnessWidget(lap: lap),
),
navigationButton(
title: 'Form Power',
color: MyColor.navigate,
icon: MyIcon.formPower,
context: context,
nextWidget: ({Lap lap}) => LapFormPowerWidget(lap: lap),
),
navigationButton(
title: 'Cadence',
color: MyColor.navigate,
icon: MyIcon.cadence,
context: context,
nextWidget: ({Lap lap}) => LapStrydCadenceWidget(lap: lap),
),
navigationButton(
title: 'Vertical Oscillation',
color: MyColor.navigate,
icon: MyIcon.verticalOscillation,
context: context,
nextWidget: ({Lap lap}) => LapVerticalOscillationWidget(lap: lap),
),
navigationButton(
title: 'Metadata',
color: MyColor.settings,
icon: MyIcon.metaData,
context: context,
nextWidget: ({Lap lap}) => LapMetadataWidget(lap: lap),
),
navigationButton(
title: 'Tags',
color: MyColor.tag,
icon: MyIcon.tag,
context: context,
nextWidget: ({Lap lap}) => LapTagWidget(
lap: lap,
athlete: athlete,
),
),
];
}
@override
Widget build(BuildContext context) {
return Scaffold(
......@@ -41,104 +136,15 @@ class ShowLapScreen extends StatelessWidget {
),
),
body: StaggeredGridView.count(
staggeredTiles:
List<StaggeredTile>.filled(12, const StaggeredTile.fit(1)),
staggeredTiles: List<StaggeredTile>.filled(
tiles(context: context).length,
const StaggeredTile.fit(1),
),
crossAxisSpacing: 10,
padding: const EdgeInsets.all(10),
crossAxisCount:
MediaQuery.of(context).orientation == Orientation.portrait ? 2 : 4,
children: <Widget>[
navigationButton(
title: 'Overview',
color: MyColor.settings,
icon: MyIcon.metaData,
context: context,
nextWidget: ({Lap lap}) => LapOverviewWidget(lap: lap),
),
navigationButton(
title: 'Heart Rate',
color: MyColor.navigate,
icon: MyIcon.heartRate,
context: context,
nextWidget: ({Lap lap}) => LapHeartRateWidget(lap: lap),
),
navigationButton(
title: 'Power',
color: MyColor.navigate,
icon: MyIcon.power,
context: context,
nextWidget: ({Lap lap}) => LapPowerWidget(lap: lap),
),
navigationButton(
title: 'Power Duration',
color: MyColor.navigate,
icon: MyIcon.powerDuration,
context: context,
nextWidget: ({Lap lap}) => LapPowerDurationWidget(lap: lap),
),
navigationButton(
title: 'Ecor',
color: MyColor.navigate,
icon: MyIcon.power,
context: context,
nextWidget: ({Lap lap}) => LapEcorWidget(
lap: lap,
athlete: athlete,
),
),
navigationButton(
title: 'Ground Time',
color: MyColor.navigate,
icon: MyIcon.groundTime,
context: context,
nextWidget: ({Lap lap}) => LapGroundTimeWidget(lap: lap),
),
navigationButton(
title: 'Leg Spring Stiffness',
color: MyColor.navigate,
icon: MyIcon.legSpringStiffness,
context: context,
nextWidget: ({Lap lap}) => LapLegSpringStiffnessWidget(lap: lap),
),
navigationButton(
title: 'Form Power',
color: MyColor.navigate,
icon: MyIcon.formPower,
context: context,
nextWidget: ({Lap lap}) => LapFormPowerWidget(lap: lap),
),
navigationButton(
title: 'Cadence',
color: MyColor.navigate,
icon: MyIcon.cadence,
context: context,
nextWidget: ({Lap lap}) => LapStrydCadenceWidget(lap: lap),
),
navigationButton(
title: 'Vertical Oscillation',
color: MyColor.navigate,
icon: MyIcon.verticalOscillation,
context: context,
nextWidget: ({Lap lap}) => LapVerticalOscillationWidget(lap: lap),
),
navigationButton(
title: 'Metadata',
color: MyColor.settings,
icon: MyIcon.metaData,
context: context,
nextWidget: ({Lap lap}) => LapMetadataWidget(lap: lap),
),
navigationButton(
title: 'Tags',
color: MyColor.tag,
icon: MyIcon.tag,
context: context,
nextWidget: ({Lap lap}) => LapTagWidget(
lap: lap,
athlete: athlete,
),
),
],
children: tiles(context: context),
),
);
}
......
......@@ -14,121 +14,121 @@ class ActivityMetadataWidget extends StatelessWidget {
final Activity activity;
final Athlete athlete;
List<Widget> get tiles {
return <Widget>[
ListTile(title: Text(activity.db.name)),
ListTile(
title: Text(
DateFormat('dd MMM yyyy, h:mm:ss').format(activity.db.timeStamp)),
subtitle: const Text('timestamp'),
),
ListTile(
title: Text(activity.db.event),
subtitle: const Text('last event'),
),
if (activity.db.totalStrides != null)
ListTile(
title: Text(activity.db.totalStrides.toString()),
subtitle: const Text('total strides'),
),
if (activity.db.maxRunningCadence != null)
ListTile(
title: Text('${activity.db.avgRunningCadence.round()} /'
' ${activity.db.maxRunningCadence}'),
subtitle: const Text('avg / max running cadence'),
),
ListTile(
title: Text(
'${activity.db.avgTemperature}° / ${activity.db.maxTemperature}°'),
subtitle: const Text('avg / max temperature'),
),
ListTile(
title: Text(activity.db.avgVerticalOscillation.toStringAsFixed(2)),
subtitle: const Text('avg vertical oscillation'),
),
ListTile(
title: Text(activity.db.totalFractionalCycles.toStringAsFixed(2)),
subtitle: const Text('total fractional cycles'),
),
ListTile(
title: Text(Duration(seconds: activity.db.totalElapsedTime).asString()),
subtitle: const Text('total elapsed time'),
),
ListTile(
title: Text(Duration(seconds: activity.db.totalTimerTime).asString()),
subtitle: const Text('total timer time'),
),
ListTile(
title: Text('${activity.db.stravaId} / ${activity.db.serialNumber}'),
subtitle: const Text('Strava / Garmin id'),
),
ListTile(
title: Text(activity.db.type +
' / ' +
activity.db.sport +
' / ' +
activity.db.subSport),
subtitle: const Text('activity type / sport / sub sport'),
),
ListTile(
title: Text(activity.db.eventType + ' / ' + activity.db.trigger),
subtitle: const Text('event type / trigger'),
),
ListTile(
title: Text('${activity.db.numLaps} / ${activity.db.numSessions}'),
subtitle: const Text('number of laps / sessions'),
),
ListTile(
title: Text(activity.db.avgFractionalCadence.toStringAsFixed(2) +
' / ' +
activity.db.maxFractionalCadence.toStringAsFixed(2)),
subtitle: const Text('avg / max fractional cadence'),
),
ListTile(
title: Text(
'${activity.db.avgStanceTime} ms / ${activity.db.avgStanceTimePercent} %'),
subtitle: const Text('avg stance time / avg stance time percent'),
),
ListTile(
title: Text(activity.db.startPositionLong.semicirclesAsDegrees() +
' E\n' +
activity.db.startPositionLat.semicirclesAsDegrees() +
' N'),
subtitle: const Text('start position'),
),
ListTile(
title: Text(activity.db.necLong.semicirclesAsDegrees() +
' E\n' +
activity.db.necLat.semicirclesAsDegrees() +
' N'),
subtitle: const Text('north east corner'),
),
ListTile(
title: Text(activity.db.swcLong.semicirclesAsDegrees() +
' E\n' +
activity.db.swcLat.semicirclesAsDegrees() +
' N'),
subtitle: const Text('south west corner'),
),
ListTile(
title: Text((activity.db.avgSpeed * 3.6).toStringAsFixed(2) +
' km/h / ' +
(activity.db.maxSpeed * 3.6).toStringAsFixed(2) +
' km/h'),
subtitle: const Text('avg / max speed'),
),
];
}
@override
Widget build(BuildContext context) {
return StaggeredGridView.count(
staggeredTiles: List<StaggeredTile>.filled(22, const StaggeredTile.fit(1)),
staggeredTiles:
List<StaggeredTile>.filled(tiles.length, const StaggeredTile.fit(1)),
mainAxisSpacing: 4,
crossAxisCount:
MediaQuery.of(context).orientation == Orientation.portrait ? 2 : 4,
children: <Widget>[
ListTile(
title: Text(activity.db.name),
),
ListTile(
title: Text(
DateFormat('dd MMM yyyy, h:mm:ss').format(activity.db.timeStamp)),
subtitle: const Text('timestamp'),
),
ListTile(
title: Text(activity.db.event),
subtitle: const Text('last event'),
),
if (activity.db.totalStrides != null)
ListTile(
title: Text(activity.db.totalStrides.toString()),
subtitle: const Text('total strides'),
),
if (activity.db.maxRunningCadence != null)
ListTile(
title: Text('${activity.db.avgRunningCadence.round()} /'
' ${activity.db.maxRunningCadence}'),
subtitle: const Text('avg / max running cadence'),
),
ListTile(
title: Text(
'${activity.db.avgTemperature}° / ${activity.db.maxTemperature}°'),
subtitle: const Text('avg / max temperature'),
),
ListTile(
title: Text(activity.db.avgVerticalOscillation.toStringAsFixed(2)),
subtitle: const Text('avg vertical oscillation'),
),
ListTile(
title: Text(activity.db.totalFractionalCycles.toStringAsFixed(2)),
subtitle: const Text('total fractional cycles'),
),
ListTile(
title:
Text(Duration(seconds: activity.db.totalElapsedTime).asString()),
subtitle: const Text('total elapsed time'),
),
ListTile(
title: Text(Duration(seconds: activity.db.totalTimerTime).asString()),
subtitle: const Text('total timer time'),
),
ListTile(
title: Text('${activity.db.stravaId} / ${activity.db.serialNumber}'),
subtitle: const Text('Strava / Garmin id'),
),
ListTile(
title: Text(activity.db.type +
' / ' +
activity.db.sport +
' / ' +
activity.db.subSport),
subtitle: const Text('activity type / sport / sub sport'),
),
ListTile(
title: Text(activity.db.eventType + ' / ' + activity.db.trigger),
subtitle: const Text('event type / trigger'),
),
ListTile(
title: Text('${activity.db.numLaps} / ${activity.db.numSessions}'),
subtitle: const Text('number of laps / sessions'),
),
ListTile(
title: Text(activity.db.avgFractionalCadence.toStringAsFixed(2) +
' / ' +
activity.db.maxFractionalCadence.toStringAsFixed(2)),
subtitle: const Text('avg / max fractional cadence'),
),
ListTile(
title: Text(
'${activity.db.avgStanceTime} ms / ${activity.db.avgStanceTimePercent} %'),
subtitle: const Text('avg stance time / avg stance time percent'),
),
ListTile(
title: Text(activity.db.startPositionLong.semicirclesAsDegrees() +
' E\n' +
activity.db.startPositionLat.semicirclesAsDegrees() +
' N'),
subtitle: const Text('start position'),
),
ListTile(
title: Text(activity.db.necLong.semicirclesAsDegrees() +
' E\n' +
activity.db.necLat.semicirclesAsDegrees() +
' N'),
subtitle: const Text('north east corner'),
),
ListTile(
title: Text(activity.db.swcLong.semicirclesAsDegrees() +
' E\n' +
activity.db.swcLat.semicirclesAsDegrees() +
' N'),
subtitle: const Text('south west corner'),
),
ListTile(
title: Text((activity.db.avgSpeed * 3.6).toStringAsFixed(2) +
' km/h / ' +
(activity.db.maxSpeed * 3.6).toStringAsFixed(2) +
' km/h'),
subtitle: const Text('avg / max speed'),
),
const Text(''),
const Text('')
],
children: tiles,
);
}
}
......@@ -27,81 +27,91 @@ class _ActivityOverviewWidgetState extends State<ActivityOverviewWidget> {
super.initState();
}
List<Widget> get tiles {
return <ListTile>[
ListTile(
title: Text(
'${(widget.activity.db.distance / 1000).toStringAsFixed(2)} km'),
subtitle: const Text('distance'),
),
ListTile(
title: Text(
Duration(seconds: widget.activity.db.movingTime ?? 0).asString()),
subtitle: const Text('moving time'),
),
ListTile(
title: Text(widget.activity.db.avgSpeed.toPace() +
' / ' +
widget.activity.db.maxSpeed.toPace()),
subtitle: const Text('avg / max pace'),
),
ListTile(
title: Text((widget.activity.weight != null)
? (widget.activity.getAttribute(ActivityAttr.ecor) as double)
.toStringAsFixed(3) +
' kJ / kg / km'
: 'not available'),
subtitle: const Text('ecor'),
),
ListTile(
title: Text('${widget.activity.db.avgHeartRate} / '
'${widget.activity.db.maxHeartRate} bpm'),
subtitle: const Text('avg / max heart rate'),
),
ListTile(
title: Text('${widget.activity.db.avgPower.toStringAsFixed(1)} W'),
subtitle: const Text('avg power'),
),
ListTile(
title: (widget.activity.db.avgPower != -1)
? Text(
(widget.activity.db.avgPower / widget.activity.db.avgHeartRate)
.toStringAsFixed(2) +
' W/bpm')
: const Text('No power data available'),
subtitle: const Text('power / heart rate'),
),
ListTile(
title: Text('${widget.activity.db.totalCalories} kcal'),
subtitle: const Text('total calories'),
),
ListTile(
title: Text(DateFormat('dd MMM yyyy, h:mm:ss')
.format(widget.activity.db.timeCreated)),
subtitle: const Text('time created'),
),
ListTile(
title: Text('${widget.activity.db.totalAscent ?? 0} - '
'${widget.activity.db.totalDescent ?? 0}'
' = ' +
((widget.activity.db.totalAscent ?? 0) -
(widget.activity.db.totalDescent ?? 0))
.toString() +
' m'),
subtitle: const Text('total ascent - descent = total climb'),
),
ListTile(
title:
Text('${(widget.activity.db.avgRunningCadence ?? 0 * 2).round()} / '
'${widget.activity.db.maxRunningCadence ?? 0 * 2} spm'),
subtitle: const Text('avg / max steps per minute'),
),
ListTile(
title: Text(widget.activity.db.totalTrainingEffect.toString()),
subtitle: const Text('total training effect'),
),
];
}
@override
Widget build(BuildContext context) {
return StaggeredGridView.count(
staggeredTiles:
List<StaggeredTile>.filled(12, const StaggeredTile.fit(1)),
List<StaggeredTile>.filled(tiles.length, const StaggeredTile.fit(1)),
mainAxisSpacing: 4,
crossAxisCount:
MediaQuery.of(context).orientation == Orientation.portrait ? 2 : 4,
children: <ListTile>[
ListTile(
title: Text(
'${(widget.activity.db.distance / 1000).toStringAsFixed(2)} km'),
subtitle: const Text('distance'),
),
ListTile(
title: Text(
Duration(seconds: widget.activity.db.movingTime ?? 0).asString()),
subtitle: const Text('moving time'),
),
ListTile(
title: Text(widget.activity.db.avgSpeed.toPace() +
' / ' +
widget.activity.db.maxSpeed.toPace()),
subtitle: const Text('avg / max pace'),
),
ListTile(
title: Text((widget.activity.weight != null)
? (widget.activity.getAttribute(ActivityAttr.ecor) as double)
.toStringAsFixed(3) +
' kJ / kg / km'
: 'not available'),
subtitle: const Text('ecor'),
),
ListTile(
title: Text(
'${widget.activity.db.avgHeartRate} / ${widget.activity.db.maxHeartRate} bpm'),
subtitle: const Text('avg / max heart rate'),
),
ListTile(
title: Text('${widget.activity.db.avgPower.toStringAsFixed(1)} W'),
subtitle: const Text('avg power'),
),
ListTile(
title: (widget.activity.db.avgPower != -1)
? Text(
'${(widget.activity.db.avgPower / widget.activity.db.avgHeartRate).toStringAsFixed(2)} W/bpm')
: const Text('No power data available'),
subtitle: const Text('power / heart rate'),
),
ListTile(
title: Text('${widget.activity.db.totalCalories} kcal'),
subtitle: const Text('total calories'),
),
ListTile(
title: Text(DateFormat('dd MMM yyyy, h:mm:ss')
.format(widget.activity.db.timeCreated)),
subtitle: const Text('time created'),
),
ListTile(
title: Text(
'${widget.activity.db.totalAscent ?? 0} - ${widget.activity.db.totalDescent ?? 0}'
' = ${(widget.activity.db.totalAscent ?? 0) - (widget.activity.db.totalDescent ?? 0)} m'),
subtitle: const Text('total ascent - descent = total climb'),
),
ListTile(
title: Text(
'${(widget.activity.db.avgRunningCadence ?? 0 * 2).round()} / '
'${widget.activity.db.maxRunningCadence ?? 0 * 2} spm'),
subtitle: const Text('avg / max steps per minute'),
),
ListTile(