123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499 |
- import 'package:flutter/material.dart';
- import 'package:provider/provider.dart';
- import 'package:sport/pages/run/chart.dart';
- import 'package:sport/pages/run/location.dart';
- import 'package:sport/pages/run/run_page.dart';
- import 'package:sport/provider/user_model.dart';
- import 'package:sport/utils/DateFormat.dart';
- import 'package:sport/utils/sport_utils.dart';
- import 'package:sport/widgets/decoration.dart';
- import 'package:sport/widgets/image.dart';
- class StatisticsWidget extends StatelessWidget {
- double totalDistance = 0;
- double totalAltitude = 0;
- int totalTime = 0;
- int totalStep = 0;
- int stepAvg = 0;
- int stepMax = 0;
- int totalConsume = 0;
- int kmTime = 0;
- double avg = 0.0;
- double avgSpeed = 0.0;
- int min = 0;
- int max = 0;
- DateTime? timeStart;
- DateTime? timeEnd;
- List<int> stepRateList = [];
- List<double> altitudeList = [];
- final Map<int, Location> _pointsKm = {};
- final Map<int, Duration> _pointsKmTime = {};
- @override
- Widget build(BuildContext context) {
- var maxKm = _pointsKmTime.isNotEmpty ? _pointsKmTime.keys.reduce((value, element) => value > element ? value : element) : 0;
- return Column(
- children: [
- Container(
- height: 68.0,
- child: Consumer<UserModel>(
- builder: (_, model, __) => Stack(
- children: [
- Positioned(
- right: 0,
- bottom: 0,
- left: 0,
- child: Container(
- padding: const EdgeInsets.fromLTRB(100.0, 12.0, 20.0, 6.0),
- decoration:
- BoxDecoration(color: Colors.white, borderRadius: BorderRadius.only(topLeft: Radius.circular(10.0), topRight: Radius.circular(10.0))),
- child: Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- crossAxisAlignment: CrossAxisAlignment.end,
- children: <Widget>[
- Text(model.user.name, style: Theme.of(context).textTheme.headline1!),
- Text(
- "${SportUtils.toDateTime(timeStart)} ${SportUtils.toEndTime(timeStart)} ~ ${SportUtils.toEndTime(timeEnd)}",
- style: Theme.of(context).textTheme.bodyText1!,
- )
- ],
- ),
- ),
- ),
- Positioned(
- left: 0,
- top: 0,
- child: Container(
- margin: const EdgeInsets.symmetric(horizontal: 16.0),
- padding: const EdgeInsets.all(4),
- decoration: BoxDecoration(color: Colors.white, shape: BoxShape.circle),
- child: CircleAvatar(
- backgroundColor: Colors.black26,
- backgroundImage: userAvatarProvider(model.user.avatar),
- radius: 30.0,
- ),
- ))
- ],
- ),
- ),
- ),
- Container(
- color: Colors.white,
- child: Column(
- children: [
- Padding(
- padding: const EdgeInsets.symmetric(horizontal: 4.0),
- child: Column(
- children: [
- Padding(
- padding: const EdgeInsets.all(20.0),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- RichText(
- text: TextSpan(children: <InlineSpan>[
- TextSpan(
- text: "${formatNum(totalDistance / 1000, 2)}",
- style: Theme.of(context).textTheme.headline1!.copyWith(fontSize: 45.0, fontFamily: "DIN"),
- ),
- WidgetSpan(alignment: PlaceholderAlignment.bottom, child: Text(" 公里", style: Theme.of(context).textTheme.subtitle1!))
- ]),
- ),
- const SizedBox(
- height: 20.0,
- ),
- Row(
- children: [
- // Container(
- // margin: EdgeInsets.only(right: 6.0),
- // height: 4,
- // width: 10,
- // color: COLOR_RUN_FAST,
- // ),
- Text(
- // "${SportUtils.toEndTime(timeStart)}开始",
- "快 ${SportUtils.pace(SportUtils.calPace((min), 1))}",
- style: Theme.of(context).textTheme.bodyText1!,
- ),
- Expanded(
- child: Container(
- margin: EdgeInsets.symmetric(horizontal: 6.0),
- height: 4,
- decoration: BoxDecoration(
- gradient: LinearGradient(
- begin: Alignment.centerLeft,
- end: Alignment.centerRight,
- colors: [
- COLOR_RUN_FAST,
- COLOR_RUN_MIDDLE,
- COLOR_RUN_SLOW,
- ],
- )))),
- Text(
- // "${SportUtils.toEndTime(timeEnd)}结束",
- "慢 ${SportUtils.pace(SportUtils.calPace((max), 1))}",
- style: Theme.of(context).textTheme.bodyText1!,
- ),
- ],
- ),
- ],
- ),
- ),
- Padding(
- padding: const EdgeInsets.only(left: 20.0),
- child: Row(
- crossAxisAlignment: CrossAxisAlignment.end,
- children: [
- Expanded(
- flex: 4,
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Text(
- "${DateFormat.toTime(totalTime)}",
- style: Theme.of(context).textTheme.headline1!.copyWith(fontSize: 22.0, fontFamily: "DIN"),
- ),
- Text(
- "时长",
- style: Theme.of(context).textTheme.bodyText1!,
- )
- ],
- ),
- ),
- Expanded(
- flex: 4,
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Row(
- children: [
- Text(
- "${SportUtils.pace11(SportUtils.calPace(totalTime, totalDistance / 1000))}",
- style: Theme.of(context).textTheme.headline1!.copyWith(fontSize: 22.0, fontFamily: "DIN"),
- ),
- Text(
- "′",
- style: Theme.of(context).textTheme.headline1!.copyWith(fontSize: 22.0),
- ),
- Text(
- "${SportUtils.pace12(SportUtils.calPace(totalTime, totalDistance / 1000))}",
- style: Theme.of(context).textTheme.headline1!.copyWith(fontSize: 22.0, fontFamily: "DIN"),
- ),
- Text(
- "″",
- style: Theme.of(context).textTheme.headline1!.copyWith(fontSize: 22.0),
- ),
- ],
- ),
- Text(
- "配速(每公里用时)",
- style: Theme.of(context).textTheme.bodyText1!,
- )
- ],
- ),
- ),
- Expanded(
- flex: 3,
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Text(
- "$totalConsume",
- style: Theme.of(context).textTheme.headline1!.copyWith(fontSize: 22.0, fontFamily: "DIN"),
- ),
- Text(
- "消耗(大卡)",
- style: Theme.of(context).textTheme.bodyText1!,
- )
- ],
- ),
- ),
- ],
- ),
- ),
- const SizedBox(
- height: 20.0,
- ),
- Padding(
- padding: const EdgeInsets.only(left: 20.0),
- child: Row(
- children: [
- Expanded(
- flex: 4,
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Text(
- "${totalStep}",
- style: Theme.of(context).textTheme.headline1!.copyWith(fontSize: 22.0, fontFamily: "DIN"),
- ),
- Text(
- "步数(步)",
- style: Theme.of(context).textTheme.bodyText1!,
- ),
- ],
- ),
- ),
- Expanded(
- flex: 4,
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Text(
- totalStep == 0 ? "0" : "${totalStep ~/ (totalTime / 60)}",
- style: Theme.of(context).textTheme.headline1!.copyWith(fontSize: 22.0, fontFamily: "DIN"),
- ),
- Text(
- "平均步频(步/分钟)",
- style: Theme.of(context).textTheme.bodyText1!,
- ),
- ],
- ),
- ),
- Expanded(
- flex: 3,
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Text(
- totalStep == 0 ? "0" : "${(totalDistance / totalStep * 100).toInt()}",
- style: Theme.of(context).textTheme.headline1!.copyWith(fontSize: 22.0, fontFamily: "DIN"),
- ),
- Text(
- "平均步幅(厘米)",
- style: Theme.of(context).textTheme.bodyText1!,
- ),
- ],
- ),
- ),
- ],
- ),
- ),
- ],
- ),
- ),
- if (_pointsKmTime.isNotEmpty == true)
- BoxWidget(
- title: "配速",
- icon: "run_icon_tile1.png",
- child: Column(
- children: [
- Row(
- mainAxisSize: MainAxisSize.max,
- children: [
- Text(
- "公里",
- style: Theme.of(context).textTheme.bodyText1!,
- ),
- Expanded(
- child: Center(
- child: Text(
- "配速",
- style: Theme.of(context).textTheme.bodyText1!,
- ),
- ),
- ),
- ],
- ),
- const SizedBox(
- height: 12.0,
- ),
- Column(
- children: _pointsKmTime.isNotEmpty
- ? _pointsKmTime.keys
- .map(
- (e) => Padding(
- padding: const EdgeInsets.symmetric(vertical: 1.0),
- child: Row(
- mainAxisSize: MainAxisSize.max,
- children: [
- Text(
- "${e.toString().padLeft(2, "0")}",
- style: Theme.of(context).textTheme.subtitle1!.copyWith(fontFamily: "DIN"),
- ),
- Expanded(
- child: Container(
- height: 17.0,
- margin: const EdgeInsets.symmetric(horizontal: 10.0),
- child: LinearProgressIndicator(
- value: avg == 0 ? 0 : (_pointsKmTime[e]?.inSeconds ?? 0) / avg,
- // value: min == 0 ? 0 : (_pointsKmTime[e]?.inSeconds ?? 0) / min / 2,
- backgroundColor: const Color(0xffF1F1F1),
- valueColor: AlwaysStoppedAnimation<Color>(
- (_pointsKmTime[e]?.inSeconds ?? 0) == min ? const Color(0xffFF5B1D) : Theme.of(context).accentColor),
- ),
- ),
- ),
- ConstrainedBox(
- constraints: BoxConstraints(minWidth: 50),
- child: Text(
- "${SportUtils.pace(SportUtils.calPace((_pointsKmTime[e]?.inSeconds ?? 0), 1))}",
- style: Theme.of(context).textTheme.subtitle1!,
- ),
- ),
- ],
- ),
- ),
- )
- .toList()
- : [],
- ),
- if (_pointsKmTime.length > 0)
- const SizedBox(
- height: 12.0,
- ),
- if (_pointsKmTime.length > 0 && totalTime > 0)
- Row(
- mainAxisAlignment: MainAxisAlignment.spaceAround,
- children: [
- RichText(
- text: TextSpan(children: [
- TextSpan(text: "$maxKm公里累计用时 ", style: Theme.of(context).textTheme.bodyText1!),
- TextSpan(
- text: "${DateFormat.toTime(kmTime)}",
- style: Theme.of(context).textTheme.bodyText1!.copyWith(color: Theme.of(context).accentColor))
- ]),
- ),
- if (totalTime - kmTime > 0)
- RichText(
- text: TextSpan(children: [
- TextSpan(text: "最后不足1公里用时 ", style: Theme.of(context).textTheme.bodyText1!),
- TextSpan(
- text: "${DateFormat.toTime((totalTime) - kmTime)}",
- style: Theme.of(context).textTheme.bodyText1!.copyWith(color: Theme.of(context).accentColor))
- ]),
- ),
- ],
- )
- ],
- )),
- BoxWidget(
- title: "步频",
- icon: "run_icon_tile2.png",
- child: Column(
- children: [
- Row(
- children: [
- Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Text(
- "$stepAvg",
- style: Theme.of(context).textTheme.headline1!.copyWith(fontSize: 25.0, fontFamily: "DIN"),
- ),
- Text(
- "平均步频(步/分钟)",
- style: Theme.of(context).textTheme.bodyText1!,
- )
- ],
- ),
- const SizedBox(
- width: 37.0,
- ),
- Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Text(
- "$stepMax",
- style: Theme.of(context).textTheme.headline1!.copyWith(fontSize: 25.0, fontFamily: "DIN"),
- ),
- Text(
- "最高步频(步/分钟)",
- style: Theme.of(context).textTheme.bodyText1!,
- )
- ],
- ),
- ],
- ),
- RunChart(
- values: stepRateList.map((e) => e.toDouble()).toList(),
- gradient: false,
- ),
- ],
- )),
- BoxWidget(
- title: "运动海拔",
- icon: "run_icon_tile3.png",
- child: Column(
- children: [
- Row(
- children: [
- Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Text(
- "${(totalAltitude).toStringAsFixed(1)}",
- style: Theme.of(context).textTheme.headline1!.copyWith(fontSize: 25.0, fontFamily: "DIN"),
- ),
- Text(
- "累计爬升(米)",
- style: Theme.of(context).textTheme.bodyText1!,
- )
- ],
- ),
- ],
- ),
- RunChart(
- values: altitudeList.map((e) => e.toDouble()).toList(),
- gradient: true,
- ),
- ],
- )),
- ],
- ),
- )
- ],
- );
- }
- }
- class BoxWidget extends StatelessWidget {
- final String title;
- final String icon;
- final Widget child;
- const BoxWidget({Key? key, required this.title, required this.child, required this.icon}) : super(key: key);
- @override
- Widget build(BuildContext context) {
- return Container(
- margin: const EdgeInsets.fromLTRB(12.0, 0, 12.0, 12.0),
- // transform: Matrix4.translationValues(0, -10, 0),
- decoration: card(),
- child: Column(
- children: [
- const SizedBox(
- height: 25,
- ),
- // Divider(
- // height: 40.0,
- // ),
- Padding(
- padding: const EdgeInsets.symmetric(horizontal: 24.0),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Row(
- children: [
- Image.asset("lib/assets/img/$icon"),
- const SizedBox(
- width: 7.0,
- ),
- Text(
- "$title",
- style: Theme.of(context).textTheme.headline3!,
- ),
- ],
- ),
- const SizedBox(
- height: 16.0,
- ),
- child,
- ],
- ),
- ),
- ],
- ),
- );
- }
- }
|