123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928 |
- import 'dart:async';
- import 'dart:math';
- import 'dart:ui';
- import 'package:cached_network_image/cached_network_image.dart';
- import 'package:flutter/cupertino.dart';
- import 'package:flutter/material.dart';
- import 'package:flutter/painting.dart';
- import 'package:flutter_easyrefresh/easy_refresh.dart';
- import 'package:provider/provider.dart';
- import 'package:sport/bean/feed_back.dart';
- import 'package:sport/bean/game.dart';
- import 'package:sport/bean/share_info.dart';
- import 'package:sport/bean/sport_detail.dart';
- import 'package:sport/bean/sport_target.dart';
- import 'package:sport/bean/sport_target_today.dart';
- import 'package:sport/pages/home/step_page.dart';
- import 'package:sport/pages/home/target_modify.dart';
- import 'package:sport/pages/my/feedback_detail_page.dart';
- import 'package:sport/pages/my/level_page.dart';
- import 'package:sport/pages/social/share_webview.dart';
- import 'package:sport/provider/bluetooth.dart';
- import 'package:sport/provider/user_model.dart';
- import 'package:sport/router/navigator_util.dart';
- import 'package:sport/router/routes.dart';
- import 'package:sport/services/api/inject_api.dart';
- import 'package:sport/services/api/resp.dart';
- import 'package:sport/utils/date.dart';
- import 'package:sport/utils/toast.dart';
- import 'package:sport/widgets/appbar.dart';
- import 'package:sport/widgets/chart.dart';
- import 'package:sport/widgets/decoration.dart';
- import 'package:sport/widgets/dialog/alert_dialog.dart';
- import 'package:sport/widgets/dialog/request_dialog.dart';
- import 'package:sport/widgets/image.dart';
- import 'package:sport/widgets/label.dart';
- import 'package:sport/widgets/loading.dart';
- import 'package:sport/widgets/misc.dart';
- import 'package:sport/widgets/popmenu_bg.dart';
- import 'package:sport/widgets/space.dart';
- class SportDetailPage extends StatefulWidget {
- @override
- State<StatefulWidget> createState() => _PageState();
- }
- class _PageState extends State<SportDetailPage> with TickerProviderStateMixin, InjectApi, InjectLoginApi {
- final List<String> _TABS = ["日", "周", "月", "年"];
- ValueNotifier<String> _tab = ValueNotifier<String>("日");
- ValueNotifier<SportTargetToday> _valueNotifierTarget = ValueNotifier(null);
- ValueNotifier<SportDetail> _valueNotifierSportDetail = ValueNotifier(null);
- ValueNotifier<DateTime> _valueNotifierDate = ValueNotifier(DateTime.now());
- int _durationTarget = 60;
- SportDetail _sportDetail;
- PageController _pageController;
- int _page = 0;
- StreamSubscription streamSubscription;
- EasyRefreshController _easyRefreshController;
- @override
- void initState() {
- super.initState();
- _easyRefreshController = EasyRefreshController();
- _pageController = PageController(initialPage: 0)
- ..addListener(() {
- _page = _pageController.page.toInt();
- });
- streamSubscription = Provider.of<Bluetooth>(context, listen: false).queryStream.listen((event) {
- refreshData();
- });
- refreshData();
- Provider.of<Bluetooth>(context, listen: false).queryDeviceStep();
- }
- refreshData() {
- api.getSportDetail().then((value) {
- _sportDetail = value.data;
- if (_sportDetail == null) return;
- _durationTarget = value.data.durationTarget;
- _valueNotifierSportDetail.value = _sportDetail;
- _valueNotifierTarget.value = SportTargetToday(remain: value.data.durationTarget - value.data.durationTotalDay, target: value.data.target);
- if (mounted) setState(() {});
- if (value.data.target == null) {
- _showFirstTarget();
- }
- });
- }
- @override
- void dispose() {
- super.dispose();
- _pageController?.dispose();
- _tab?.dispose();
- _valueNotifierTarget?.dispose();
- _valueNotifierSportDetail?.dispose();
- _valueNotifierDate?.dispose();
- streamSubscription?.cancel();
- _easyRefreshController?.dispose();
- }
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- body: Stack(
- children: <Widget>[
- EasyRefresh.builder(
- controller: _easyRefreshController,
- enableControlFinishRefresh: true,
- header: buildClassicalHeader(),
- onRefresh: () async {
- Provider.of<Bluetooth>(context, listen: false).queryDeviceStep();
- await Future.delayed(Duration(seconds: 5));
- _easyRefreshController.finishRefresh(success: true);
- },
- builder: (context, physics, header, footer) {
- return CustomScrollView(
- physics: physics,
- slivers: <Widget>[
- buildSliverAppBar(context, "运动详情", backgroundColor: Theme.of(context).scaffoldBackgroundColor, actions: <Widget>[
- PopupMenuTheme(
- data: PopupMenuThemeData(shape: PopmenuShape(borderRadius: BorderRadius.all(Radius.circular(10.0)))),
- child: PopupMenuButton(
- padding: EdgeInsets.zero,
- offset: Offset(0, kToolbarHeight / 2 + 15),
- icon: Image.asset("lib/assets/img/topbar_more.png"),
- onSelected: (action) async {
- switch (action) {
- case "modify":
- NavigatorUtil.go(context, Routes.targetModify).then((value) {
- if (value == null) return;
- if (value is SportTargetToday) {
- _valueNotifierTarget.value = value;
- Provider.of<UserModel>(context, listen: false).durationTarget.value = value.target.duration;
- }
- });
- break;
- case "data":
- FeedTypeInfoData group;
- await request(context, () async {
- FeedTypeInfo _feedTypeInfo = await loginApi.getFeedBackTypes();
- if (_feedTypeInfo.code == 0) {
- group = _feedTypeInfo.data.singleWhere((element) => element.groupId == '2');
- }
- });
- if (group != null) {
- print("[group:]---------------------------$group");
- NavigatorUtil.goPage(context, (context) => FeedbackDetailPage(group));
- }
- break;
- case "share":
- String hash;
- print("------------------------------------------------------------");
- await request(context, () async {
- ShareInfo _info = (await api.getshareCreateSport("day",50.0)).data;
- hash = _info.hash;
- print("[hash:]---------------------------${_info.hash}");
- });
- if(hash != null){
- NavigatorUtil.goPage(context, (context)=> WebViewSharePage("http://shoes-web.hiyd.com/share",hash: hash,));
- }
- break;
- }
- },
- itemBuilder: (_) => [
- menuItem("modify", "linkpop_icon_modify.png", "修改目标"),
- menuDivider(),
- menuItem("data", "linkpop_icon_modify_1.png", "数据报错"),
- menuDivider(),
- menuItem("share", "linkpop_icon_share.png", "数据分享"),
- ],
- ),
- )
- ]),
- header,
- SliverToBoxAdapter(
- child: _buildTargetWidget(),
- ),
- SliverToBoxAdapter(
- child: _buildDataWidget(),
- ),
- SliverToBoxAdapter(
- child: _buildAchievementWidget(),
- ),
- SliverToBoxAdapter(
- child: _buildSportListWidget(),
- ),
- ],
- );
- }),
- Positioned(
- right: -1,
- top: kToolbarHeight + MediaQuery.of(context).padding.top,
- child: GestureDetector(
- onTap: () => NavigatorUtil.goPage(context, (context) => StepPage()),
- child: Container(
- padding: EdgeInsets.fromLTRB(3, 3, 12, 3),
- decoration: BoxDecoration(
- color: Colors.white,
- borderRadius: BorderRadius.only(topLeft: Radius.circular(30), bottomLeft: Radius.circular(30)),
- border: Border.all(
- color: Theme.of(context).scaffoldBackgroundColor,
- width: .5,
- ),
- ),
- child: Row(
- children: <Widget>[
- Image.asset("lib/assets/img/gamedetail_step.png"),
- ValueListenableBuilder<SportDetail>(
- valueListenable: _valueNotifierSportDetail,
- builder: (_, _value, ___) => Text(
- " ${_value?.step ?? 0}步",
- style: Theme.of(context).textTheme.subtitle1,
- ))
- ],
- ),
- ),
- ),
- )
- ],
- ),
- );
- }
- Widget _buildTargetWidget() {
- return ValueListenableBuilder<SportTargetToday>(
- valueListenable: _valueNotifierTarget,
- builder: (_, _value, ___) => _value == null
- ? RequestLoadingWidget()
- : Column(
- children: <Widget>[
- Padding(
- padding: const EdgeInsets.only(right: 12.0, top: 15),
- child: Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: <Widget>[
- LabelWidget(title: "今日目标"),
- _value.target != null
- ? Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: <Widget>[
- Text("目标时长:${_value.target.duration}分钟\t\t\t\t强度:${_value.target.intension}", style: Theme.of(context).textTheme.bodyText1),
- ],
- )
- : InkWell(
- onTap: () {
- NavigatorUtil.go(context, Routes.targetModify).then((value) {
- if (value == null) return;
- if (value is SportTargetToday) {
- _valueNotifierTarget.value = value;
- }
- });
- },
- child: Row(
- mainAxisAlignment: MainAxisAlignment.end,
- children: <Widget>[
- Text("设立目标", style: Theme.of(context).textTheme.subtitle1.copyWith(color: Theme.of(context).accentColor)),
- Space(
- width: 5,
- ),
- arrowRight6()
- ],
- ),
- ),
- ],
- ),
- ),
- Container(
- margin: EdgeInsets.fromLTRB(12.0, 6.0, 12.0, 18.0),
- padding: EdgeInsets.fromLTRB(12.0, 12.0, 12.0, 12.0),
- decoration: circular(),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: <Widget>[
- Text("运动时长", style: Theme.of(context).textTheme.subtitle1),
- Space(
- height: 12,
- ),
- Container(child: LayoutBuilder(builder: (context, box) {
- int minute = _sportDetail.durationTotalDay;
- double percent = minute / (_value.target == null ? _durationTarget : _value.target.duration);
- double w = 70;
- double padding = box.maxWidth * percent - w / 2;
- if (padding < w / 2) {
- padding = 0;
- }
- if (padding > box.maxWidth - w) {
- padding = box.maxWidth - w;
- }
- // fix 一直在最左!
- padding = 0;
- return Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: <Widget>[
- Padding(
- padding: EdgeInsets.only(left: padding),
- child: Container(
- width: w,
- alignment: padding == 0 ? Alignment.centerLeft : Alignment.center,
- child: RichText(
- text: TextSpan(style: Theme.of(context).textTheme.subtitle2, children: <InlineSpan>[
- TextSpan(
- text: '$minute',
- style: Theme.of(context).textTheme.subtitle2.copyWith(fontWeight: FontWeight.bold, fontSize: 25),
- ),
- TextSpan(text: '分钟'),
- ]),
- ),
- ),
- ),
- Space(
- height: 4,
- ),
- CustomPaint(
- painter: _ProgressBar(percent),
- child: Container(
- height: 12,
- ),
- ),
- ],
- );
- })),
- Space(
- height: 15,
- ),
- Row(
- children: <Widget>[
- Text(
- "消耗(kal)",
- style: Theme.of(context).textTheme.subtitle2,
- ),
- Space(
- width: 6,
- ),
- Text(
- "${_sportDetail?.recordsTodaySum?.consume ?? 0}",
- style: Theme.of(context).textTheme.headline1.copyWith(color: Theme.of(context).accentColor),
- ),
- Space(
- width: 30,
- ),
- Text(
- "累计运动 (次)",
- style: Theme.of(context).textTheme.subtitle2,
- ),
- Space(
- width: 6,
- ),
- Text(
- "${_sportDetail?.recordsTodaySum?.times ?? 0}",
- style: Theme.of(context).textTheme.headline1.copyWith(color: Theme.of(context).accentColor),
- ),
- ],
- ),
- SizedBox(
- height: 4,
- ),
- Divider(),
- SizedBox(
- height: 4,
- ),
- if (_sportDetail?.nextAchievement != null)
- InkWell(
- onTap: () => NavigatorUtil.goAchievementDetails(context, id: _sportDetail.nextAchievement.achievement.id),
- child: Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: <Widget>[
- RichText(
- text: TextSpan(style: Theme.of(context).textTheme.bodyText1, children: <InlineSpan>[
- TextSpan(text: '距离'),
- TextSpan(
- text: ' ${_sportDetail.nextAchievement.achievement?.name} ',
- style: Theme.of(context).textTheme.bodyText1.copyWith(color: Theme.of(context).accentColor),
- ),
- TextSpan(
- text: '还需运动 ${_sportDetail.nextAchievement.diff ?? 0}${_sportDetail.nextAchievement.achievement?.conditionMeasure ?? ''}'),
- ])),
- arrowRight4()
- ],
- ),
- ),
- ],
- ),
- ),
- ],
- ),
- );
- }
- Widget _buildDataWidget() {
- return Column(
- children: <Widget>[
- LabelWidget(title: "数据统计"),
- Container(
- margin: EdgeInsets.fromLTRB(12.0, 6.0, 12.0, 18.0),
- padding: EdgeInsets.fromLTRB(12.0, 12.0, 12.0, 12.0),
- decoration: circular(),
- child: Column(
- children: <Widget>[
- ValueListenableBuilder(
- valueListenable: _tab,
- builder: (BuildContext context, String value, Widget child) {
- return Column(
- children: <Widget>[
- Row(
- mainAxisAlignment: MainAxisAlignment.center,
- mainAxisSize: MainAxisSize.min,
- children: ["日", "/", "周", "/", "月", "/", "年"]
- .map((e) => e == "/"
- ? Container(
- margin: EdgeInsets.symmetric(horizontal: 6.0),
- color: Color(0xffdcdcdc),
- width: 0.5,
- height: 14,
- transform: Matrix4.rotationZ(0.35),
- )
- : InkWell(
- onTap: () {
- if (_valueNotifierSportDetail.value == null) return;
- _tab.value = e;
- _valueNotifierDate.value = DateTime.now();
- // _pageController = PageController(initialPage: 0);
- _pageController.jumpToPage(0);
- changeTab(DateTime.now());
- },
- child: Container(
- margin: EdgeInsets.symmetric(horizontal: 12.0),
- padding: EdgeInsets.all(8.0),
- decoration: value == e ? BoxDecoration(color: Theme.of(context).accentColor, shape: BoxShape.circle) : null,
- child: Text(
- "$e",
- style: Theme.of(context).textTheme.subtitle1.copyWith(color: value == e ? Colors.white : Color(0xff333333)),
- ),
- )))
- .toList(),
- ),
- ],
- );
- },
- ),
- ValueListenableBuilder(
- valueListenable: _tab,
- builder: (_, time, ___) => Container(
- height: 520,
- child: PageView.builder(
- reverse: true,
- itemCount: 10240,
- controller: _pageController,
- onPageChanged: (page) {},
- itemBuilder: (context, index) {
- var time = offsetDate(toType(), -index);
- return FutureBuilder<SportDetail>(
- future: changeTab(time),
- builder: (BuildContext context, AsyncSnapshot<SportDetail> snapshot) {
- SportDetail _value = snapshot.data;
- return snapshot.connectionState != ConnectionState.done
- ? RequestLoadingWidget()
- : Column(
- children: <Widget>[
- Padding(
- padding: const EdgeInsets.symmetric(horizontal: 30, vertical: 12),
- child: Row(
- mainAxisAlignment: MainAxisAlignment.center,
- children: <Widget>[
- GestureDetector(
- behavior: HitTestBehavior.opaque,
- onTap: () {
- _pageController?.nextPage(duration: Duration(milliseconds: 500), curve: Curves.linear);
- },
- child: Padding(
- padding: const EdgeInsets.all(16.0),
- child: arrowLeft(),
- ),
- ),
- Expanded(
- child: Center(
- child: LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) {
- int type = toType();
- if (type == 0) {
- return Text(
- "${time.year}.${'${time.month}'.padLeft(2, '0')}.${'${time.day}'.padLeft(2, '0')} ${WEEK[time.weekday == 0 ? 6 : time.weekday - 1]}");
- } else if (type == 1) {
- DateTime start = DateTime(time.year, time.month, time.day - time.weekday + 1);
- DateTime end = DateTime(time.year, time.month, time.day + 6 - time.weekday + 1);
- print("$time ${time.weekday} == $start $end");
- return Text(
- "${start.year}.${'${start.month}'.padLeft(2, '0')}.${'${start.day}'.padLeft(2, '0')} 至 ${end.year}.${'${end.month}'.padLeft(2, '0')}.${'${end.day}'.padLeft(2, '0')}");
- } else if (type == 2) {
- return Text("${time.year}年${'${time.month}'.padLeft(2, '0')}月");
- } else if (type == 3) {
- return Text("${time.year}年");
- }
- return Text(" ");
- }),
- ),
- ),
- GestureDetector(
- behavior: HitTestBehavior.opaque,
- onTap: () {
- if (_pageController?.page == 0.0) {
- return;
- }
- _pageController?.previousPage(duration: Duration(milliseconds: 500), curve: Curves.linear);
- },
- child: Padding(
- padding: const EdgeInsets.all(16.0),
- child: arrowRight(),
- ),
- ),
- ],
- ),
- ),
- Space(
- height: 12,
- ),
- CustomPaint(
- painter: Chart(type: _TABS.indexOf(_tab.value),records: _value?.recordsToday?.map((e) => ChartItem(e.createdAt, e.consume))?.toList(), dateTime: time)..initData(),
- child: Container(
- height: 160,
- ),
- ),
- Space(
- height: 6,
- ),
- Column(
- children: <Widget>[
- Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: <Widget>[
- Text(
- "总消耗",
- style: Theme.of(context).textTheme.subtitle1,
- ),
- Text("${_value == null ? ".." : "${_value.recordsTodaySum.consume}"} kal",
- style: Theme.of(context).textTheme.subtitle1)
- ],
- ),
- Space(
- height: 8,
- ),
- Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: <Widget>[
- Text(
- "总时长",
- style: Theme.of(context).textTheme.subtitle1,
- ),
- Text("${_value == null ? ".." : "${_value.recordsTodaySum.duration}"}分钟",
- style: Theme.of(context).textTheme.subtitle1)
- ],
- ),
- Space(
- height: 8,
- ),
- Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: <Widget>[
- Text(
- "累计运动",
- style: Theme.of(context).textTheme.subtitle1,
- ),
- Text("${_value == null ? ".." : "${_value.recordsTodaySum.times ?? 0}"}次",
- style: Theme.of(context).textTheme.subtitle1)
- ],
- ),
- Space(
- height: 8,
- ),
- Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: <Widget>[
- Text(
- "跳跃次数",
- style: Theme.of(context).textTheme.subtitle1,
- ),
- Text("${_value == null ? ".." : "${_value.recordsTodaySum.jumpCount}"}次",
- style: Theme.of(context).textTheme.subtitle1)
- ],
- ),
- Space(
- height: 8,
- ),
- Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: <Widget>[
- Text(
- "下蹲次数",
- style: Theme.of(context).textTheme.subtitle1,
- ),
- Text("${_value == null ? ".." : "${_value.recordsTodaySum.crouchCount}"}次",
- style: Theme.of(context).textTheme.subtitle1)
- ],
- ),
- Space(
- height: 8,
- ),
- Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: <Widget>[
- Text(
- "游戏步数",
- style: Theme.of(context).textTheme.subtitle1,
- ),
- Text("${_value == null ? ".." : "${_value.recordsTodaySum?.stepCount ?? 0}"}次",
- style: Theme.of(context).textTheme.subtitle1)
- ],
- ),
- Row(
- children: <Widget>[
- Expanded(child: Divider()),
- Padding(
- padding: const EdgeInsets.all(16.0),
- child: Text(
- "相当于",
- style: Theme.of(context).textTheme.bodyText1,
- ),
- ),
- Expanded(child: Divider())
- ],
- ),
- sportBeEquivalentTo(
- context, _value == null || _value.recordsTodaySum == null ? 0 : _value.recordsTodaySum.consume),
- ],
- ),
- Space(
- height: 10,
- )
- ],
- );
- });
- },
- ),
- )),
- ],
- ),
- ),
- ],
- );
- }
- Widget _buildAchievementWidget() {
- return Column(
- children: <Widget>[
- Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: <Widget>[
- LabelWidget(title: "我的成就"),
- GestureDetector(
- behavior: HitTestBehavior.opaque,
- onTap: () {
- NavigatorUtil.goPage(context, (context) => LevelPage());
- },
- child: Padding(
- padding: const EdgeInsets.fromLTRB(12.0, 6.0, 12.0, 6.0),
- child: Row(
- children: <Widget>[
- Text(
- "更多",
- style: Theme.of(context).textTheme.bodyText1,
- ),
- Space(
- width: 4,
- ),
- arrowRight4()
- ],
- ),
- ),
- )
- ],
- ),
- Container(
- margin: EdgeInsets.fromLTRB(12.0, 6.0, 12.0, 18.0),
- padding: EdgeInsets.fromLTRB(12.0, 12.0, 12.0, 12.0),
- width: double.infinity,
- decoration: circular(),
- child: Padding(
- padding: const EdgeInsets.symmetric(vertical: 12.0),
- child: achievementGroupWidget(_sportDetail?.achievements),
- ),
- ),
- ],
- );
- }
- Widget _buildSportListWidget() {
- return _sportDetail?.gamesSum?.isNotEmpty == true
- ? Column(
- children: <Widget>[
- LabelWidget(title: "运动统计"),
- Container(
- margin: EdgeInsets.fromLTRB(12.0, 6.0, 12.0, 18.0),
- padding: EdgeInsets.fromLTRB(12.0, 12.0, 12.0, 12.0),
- decoration: circular(),
- child: ListView.separated(
- padding: EdgeInsets.zero,
- shrinkWrap: true,
- physics: NeverScrollableScrollPhysics(),
- itemBuilder: (context, index) {
- GamesSum sum = _sportDetail.gamesSum[index];
- return Column(
- children: <Widget>[
- _buildWrapListHeaderWidget(sum),
- _buildWrapListTileWidget("总消耗:", "${sum.consumeTotal}kal"),
- _buildWrapListTileWidget("总时长:", "${sum.durationTotal}分钟"),
- _buildWrapListTileWidget("运动效率:", "${(sum.consumeTotal / sum.durationTotal).toStringAsFixed(2)}kal/min"),
- _buildWrapListTileWidget("总局数:", "${sum.playCount}局"),
- _buildWrapListTileWidget("最高得分:", "${sum.scoreMax.toStringAsFixed(1)}"),
- Padding(
- padding: const EdgeInsets.all(8.0),
- child: InkWell(
- onTap: () => NavigatorUtil.goGameHistory(context, sum.game),
- child: Row(
- mainAxisSize: MainAxisSize.min,
- children: <Widget>[
- Text(
- "查看记录详情 ",
- style: Theme.of(context).textTheme.bodyText1,
- ),
- arrowRight4()
- ],
- ),
- ),
- )
- ],
- );
- },
- separatorBuilder: (context, index) => Divider(),
- itemCount: _sportDetail.gamesSum.length),
- ),
- ],
- )
- : Container();
- }
- Widget _buildWrapListHeaderWidget(GamesSum sum) {
- GameInfoData game = sum.game;
- return Row(
- children: <Widget>[
- Container(
- width: 50,
- height: 50,
- margin: EdgeInsets.fromLTRB(0, 6, 8, 6),
- decoration:
- BoxDecoration(borderRadius: BorderRadius.circular(6), image: DecorationImage(fit: BoxFit.cover, image: CachedNetworkImageProvider(game.cover))),
- ),
- Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: <Widget>[
- Text(
- game.name,
- style: Theme.of(context).textTheme.headline3,
- ),
- Space(
- height: 5,
- ),
- Text(
- "最近游玩:${sum.lastPlayAt}",
- style: Theme.of(context).textTheme.bodyText1,
- )
- ],
- )
- ],
- );
- }
- Widget _buildWrapListTileWidget(String key, String value) {
- return Padding(
- padding: const EdgeInsets.symmetric(vertical: 4.0),
- child: Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: <Widget>[
- Text(
- key,
- style: Theme.of(context).textTheme.subtitle1,
- ),
- Text(
- value,
- style: Theme.of(context).textTheme.subtitle1,
- )
- ],
- ),
- );
- }
- int toType() {
- return _TABS.indexOf(_tab.value);
- }
- Future<SportDetail> changeTab(DateTime time) async {
- int type = toType();
- Future<RespData<SportDetailSimple>> data;
- switch (type) {
- case 0:
- data = api.getSportRecordListOneDay('${time.year}-${'${time.month}'.padLeft(2, '0')}-${'${time.day}'.padLeft(2, '0')}');
- break;
- case 1:
- DateTime start = DateTime(time.year, time.month, time.day - time.weekday + 1);
- DateTime end = DateTime(time.year, time.month, time.day + 6 - time.weekday + 1);
- data = api.getSportRecordListByDay('${start.year}-${'${start.month}'.padLeft(2, '0')}-${'${start.day}'.padLeft(2, '0')}',
- '${end.year}-${'${end.month}'.padLeft(2, '0')}-${'${end.day}'.padLeft(2, '0')}');
- break;
- case 2:
- DateTime start = DateTime(time.year, time.month, 1);
- DateTime end = DateTime(time.year, time.month + 1, 0);
- data = api.getSportRecordListByDay('${start.year}-${'${start.month}'.padLeft(2, '0')}-${'${start.day}'.padLeft(2, '0')}',
- '${end.year}-${'${end.month}'.padLeft(2, '0')}-${'${end.day}'.padLeft(2, '0')}');
- break;
- case 3:
- data = api.getSportRecordListByMonth(time.year);
- break;
- }
- if (data != null) {
- var simple = await data;
- if (simple.code == 0) {
- return SportDetail(
- recordsTodaySum: simple.data.sum ?? RecordsTodaySum(consume: 0, duration: 0, crouchCount: 0, jumpCount: 0), recordsToday: simple.data.records);
- }
- }
- return null;
- }
- void _showFirstTarget() async {
- SportTarget sportTarget;
- var result = await showDialog(
- context: context,
- barrierDismissible: false,
- builder: (context) => NotificationListener<TargetNotification>(
- onNotification: (notification) {
- sportTarget = notification.target;
- return true;
- },
- child: CustomAlertDialog(
- addClose: true,
- title: '运动目标设置',
- child: Column(
- children: <Widget>[
- Align(
- alignment: Alignment.centerLeft,
- child: Padding(
- padding: const EdgeInsets.only(left: 20.0),
- child: Text(
- "请选择每日运动目标",
- style: Theme.of(context).textTheme.subtitle1,
- ),
- ),
- ),
- Padding(
- padding: const EdgeInsets.symmetric(horizontal: 20.0, vertical: 5.0),
- child: TargetModify(
- editCustom: false,
- padding: false,
- ),
- )
- ],
- ),
- ok: () async {
- if (sportTarget == null) {
- return;
- }
- RespData<SportTargetToday> resp = (sportTarget.name == '自定义'
- ? await api.setSportTargetCustom(sportTarget.duration, sportTarget.consume)
- : await api.setSportTarget(sportTarget.id));
- if (resp.code == 0) {
- Navigator.of(context).pop(resp.data);
- } else {
- ToastUtil.show(resp.msg);
- }
- },
- )));
- if (result is SportTargetToday) {
- if (result != null) {
- setState(() {
- _valueNotifierTarget.value = result;
- });
- Provider.of<UserModel>(context, listen: false).durationTarget.value = result.target.duration;
- }
- }
- }
- }
- class _ProgressBar extends CustomPainter {
- final Paint _paint = Paint()
- ..color = Color(0xffeeeeee)
- ..isAntiAlias = true;
- final Paint _indicatorPaint = Paint()
- ..color = Color(0xffFFC400)
- ..isAntiAlias = true;
- double _paddingBar = 2;
- double percent;
- _ProgressBar(this.percent);
- @override
- void paint(Canvas canvas, Size size) {
- double indicator = size.width * min(1.0, this.percent);
- canvas.save();
- var rect = Rect.fromLTRB(0, 0, size.width, size.height);
- canvas.clipRRect(RRect.fromRectAndRadius(rect, Radius.circular(size.height / 2)), doAntiAlias: true);
- canvas.drawRect(rect, _paint);
- Paint _valuePaint = Paint()
- ..shader = LinearGradient(
- begin: Alignment.centerLeft,
- end: Alignment.centerRight,
- colors: <Color>[Color(0xffFFE600), Color(0xffFF9100)],
- ).createShader(rect);
- canvas.drawRect(Rect.fromLTRB(0, 0, size.width * this.percent, size.height), _valuePaint);
- canvas.restore();
- // Path path = Path()
- // ..moveTo(indicator, size.height - 13 - _paddingBar)
- // ..lineTo(indicator - 5, 0)
- // ..lineTo(indicator + 5, 0)
- // ..close();
- // canvas.drawPath(path, _indicatorPaint);
- }
- @override
- bool shouldRepaint(CustomPainter oldDelegate) {
- return false;
- }
- }
|