123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394 |
- import 'dart:convert';
- import 'dart:math';
- import 'dart:ui';
- import 'dart:ui' as ui;
- import 'package:flutter/material.dart';
- import 'package:flutter/painting.dart';
- import 'package:sport/bean/sport_step.dart';
- import 'package:sport/pages/home/step_realtime_page.dart';
- import 'package:sport/router/navigator_util.dart';
- import 'package:sport/services/Converter.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/image.dart';
- import 'package:sport/widgets/loading.dart';
- import 'package:sport/widgets/misc.dart';
- import 'package:sport/widgets/persistent_header.dart';
- import 'package:sport/widgets/space.dart';
- const Color _color = Color(0xffFFC400);
- const List<String> TABS = ["日", "周", "月", "年"];
- class StepPage extends StatefulWidget {
- @override
- State<StatefulWidget> createState() => _PageState();
- }
- class _PageState extends State<StepPage> with TickerProviderStateMixin, InjectApi, InjectLoginApi {
- ValueNotifier<String> _tab = ValueNotifier<String>("日");
- ValueNotifier<SportStep> _valueNotifierSportDetail = ValueNotifier(null);
- ValueNotifier<DateTime> _valueNotifierDate = ValueNotifier(DateTime.now());
- PageController _pageController;
- @override
- void initState() {
- super.initState();
- _pageController = PageController(initialPage: 0);
- var now = DateTime.now();
- // api.addDaily(
- // step: Random().nextInt(255), distance: Random().nextInt(255) * 10, time: '${now.year}-${now.month}-${now.day} ${now.hour}:${now.minute}:${now.second}');
- // api.addDaily(data: json.encode([[Random().nextInt(255), Random().nextInt(255),DateTime.now().millisecondsSinceEpoch ~/ 1000 - Random().nextInt(1000)],[Random().nextInt(255), Random().nextInt(255),DateTime.now().millisecondsSinceEpoch ~/ 1000 - Random().nextInt(1000)],[Random().nextInt(255), Random().nextInt(255),DateTime.now().millisecondsSinceEpoch ~/ 1000 - Random().nextInt(1000)]]));
- changeTab();
- }
- @override
- void dispose() {
- _pageController?.dispose();
- super.dispose();
- _tab?.dispose();
- _valueNotifierSportDetail?.dispose();
- _valueNotifierDate?.dispose();
- }
- @override
- Widget build(BuildContext context) {
- return Scaffold(
- backgroundColor: Colors.white,
- appBar: buildAppBar(
- context,
- title: "运动步数",
- actions: <Widget>[
- IconButton(
- icon: Image.asset(
- "lib/assets/img/runsteps_icon.png",
- width: 22.0,
- ),
- onPressed: () => NavigatorUtil.goPage(context, (context) => StepRealTimePage()),
- )
- ],
- ),
- body: Container(
- color: Colors.white,
- child: ValueListenableBuilder(
- valueListenable: _tab,
- builder: (BuildContext context, String value, Widget child) {
- return Column(
- children: <Widget>[
- Padding(
- padding: const EdgeInsets.all(8.0),
- child: Row(
- mainAxisAlignment: MainAxisAlignment.center,
- children: ["日", "/", "周", "/", "月", "/", "年"]
- .map((e) => e == "/"
- ? Container(
- margin: const EdgeInsets.fromLTRB(5, 0, 1, 0),
- color: const 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.jumpToPage(0);
- // _pageController= PageController(initialPage: 0);
- changeTab();
- },
- child: Container(
- margin: EdgeInsets.symmetric(horizontal: 12.0),
- padding: EdgeInsets.all(8.0),
- decoration: value == e ? BoxDecoration(color: _color, shape: BoxShape.circle) : null,
- child: Text(
- "$e",
- style: value == e
- ? Theme.of(context).textTheme.subtitle1.copyWith(color: Colors.white)
- : Theme.of(context).textTheme.subtitle1,
- ),
- )))
- .toList(),
- ),
- ),
- Center(
- child: ValueListenableBuilder<DateTime>(
- valueListenable: _valueNotifierDate,
- builder: (_, time, ___) {
- int type = toType();
- String text = "";
- if (type == 0) {
- text = "${time.year}.${'${time.month}'.padLeft(2, '0')}.${'${time.day}'.padLeft(2, '0')} 6:00 - 24:00 ";
- } 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");
- 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) {
- text = ("${time.year}年${'${time.month}'.padLeft(2, '0')}月");
- } else if (type == 3) {
- text = ("${time.year}年");
- }
- return Row(
- mainAxisSize: MainAxisSize.min,
- children: <Widget>[
- GestureDetector(
- behavior: HitTestBehavior.opaque,
- onTap: () {
- _pageController?.nextPage(duration: Duration(milliseconds: 500), curve: Curves.linear);
- },
- child: Padding(
- padding: const EdgeInsets.all(18.0),
- child: arrowLeft(),
- ),
- ),
- Text(
- text,
- style: Theme.of(context).textTheme.bodyText2.copyWith(color: Color(0xff333333)),
- strutStyle: fixedLine,
- ),
- GestureDetector(
- behavior: HitTestBehavior.opaque,
- onTap: () {
- if (_pageController?.page == 0.0) {
- ToastUtil.show("没有数据了");
- return;
- }
- _pageController?.previousPage(duration: Duration(milliseconds: 500), curve: Curves.linear);
- },
- child: Padding(
- padding: const EdgeInsets.all(18.0),
- child: arrowRight(),
- ),
- ),
- ],
- );
- }),
- ),
- Expanded(
- child: PageView.builder(
- reverse: true,
- itemCount: 10240,
- controller: _pageController,
- onPageChanged: (page) {
- rollDate(-page);
- },
- itemBuilder: (context, index) {
- int type = toType();
- DateTime time = offsetDate(type, -index);
- return FutureBuilder<RespData<SportStep>>(
- future: createFuture(time),
- builder: (BuildContext context, AsyncSnapshot<RespData<SportStep>> snapshot) {
- var _value = snapshot?.data?.data;
- return snapshot.connectionState != ConnectionState.done
- ? RequestLoadingWidget()
- : Padding(
- padding: const EdgeInsets.fromLTRB(12.0, 12.0, 12.0, 0),
- child: SingleChildScrollView(
- child: Column(
- children: <Widget>[
- Text(
- "${_value?.sum?.stepDayAvg ?? _value?.sum?.step ?? 0}",
- style: Theme.of(context).textTheme.headline1.copyWith(fontSize: 26.0, color: _color),
- ),
- Text(
- toType() == 0 ? "日总步数" : "日均步数",
- style: Theme.of(context).textTheme.subtitle2.copyWith(color: Color(0xff999999)),
- ),
- SizedBox(
- height: 30.0,
- ),
- Padding(
- padding: const EdgeInsets.only(right: 12.0),
- child: CustomPaint(
- painter: Chart(
- type: TABS.indexOf(_tab.value),
- records: snapshot.data?.data?.records
- ?.map((e) => ChartItem(type == 3 ? "${e.month}" : e.createdAt, e.step))
- ?.toList() ??
- [],
- dateTime: time,
- drawMax: true,
- unit: "歩")
- ..initData(maxValue: 7000.0 * (type + 1)),
- child: Container(
- height: 200,
- ),
- ),
- ),
- Padding(
- padding: const EdgeInsets.all(12.0),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: <Widget>[
- Space(
- height: 10,
- ),
- Text(
- "运动总距离",
- style: Theme.of(context).textTheme.subtitle1,
- ),
- Space(
- height: 10,
- ),
- RichText(
- text: TextSpan(style: Theme.of(context).textTheme.subtitle2, children: <InlineSpan>[
- TextSpan(
- text:
- '${_value == null ? ".." : "${((_value.sum.stepDaily + _value.sum.stepGame) * .6).toStringAsFixed(1)}"}',
- style: Theme.of(context).textTheme.subtitle2.copyWith(fontWeight: FontWeight.bold, fontSize: 25)),
- TextSpan(text: ' 米', style: Theme.of(context).textTheme.subtitle1),
- ]),
- ),
- Divider(
- height: 24,
- ),
- if (type != 0)
- Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: <Widget>[
- Text(
- type == 1 ? "周总步数" : type == 2 ? "月总步数" : "年总步数",
- style: Theme.of(context).textTheme.subtitle1,
- ),
- Text("${_value == null ? ".." : "${_value.sum.stepDaily + _value.sum.stepGame}"}",
- style: Theme.of(context).textTheme.subtitle1)
- ],
- ),
- if (type != 0)
- Space(
- height: 8,
- ),
- Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: <Widget>[
- Text(
- "日常步数",
- style: Theme.of(context).textTheme.subtitle1,
- ),
- Text("${_value == null ? ".." : "${_value.sum.stepDaily}"}", 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.sum.stepGame}"}", 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.sum.stepRate}"} /min",
- 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.sum.stepRateMax}"} /min",
- style: Theme.of(context).textTheme.subtitle1)
- ],
- ),
- Space(
- height: 8,
- ),
- ],
- ),
- )
- ],
- ),
- ),
- );
- });
- },
- ),
- ),
- ],
- );
- },
- ),
- ));
- }
- int toType() {
- return TABS.indexOf(_tab.value);
- }
- void changeTab() async {
- _valueNotifierSportDetail.value = null;
- if (_valueNotifierDate.value == null) return;
- Future<RespData<SportStep>> data = createFuture(_valueNotifierDate.value);
- if (data != null) {
- data.then((value) => _valueNotifierSportDetail.value = value.data);
- }
- }
- Future<RespData<SportStep>> createQueryFuture(int offset) {
- int type = toType();
- DateTime next = offsetDate(type, offset);
- return createFuture(next);
- }
- Future<RespData<SportStep>> createFuture(DateTime time) {
- int type = toType();
- Future<RespData<SportStep>> data;
- switch (type) {
- case 0:
- data = api.getStepRecordListOneDay('${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.getStepRecordListByDay('${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.getStepRecordListByDay('${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.getStepRecordListByMonth(time.year);
- break;
- }
- return data;
- }
- void rollDate(int offset) {
- if (_valueNotifierSportDetail.value == null) return;
- int type = toType();
- DateTime next = offsetDate(type, offset);
- _valueNotifierDate.value = next;
- changeTab();
- }
- }
|