sport_data_calendar.dart 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. import 'package:flutter/material.dart';
  2. import 'package:paged_vertical_calendar/paged_vertical_calendar.dart';
  3. import 'package:provider/provider.dart';
  4. import 'package:sport/bean/sport_detail.dart';
  5. import 'package:sport/services/api/inject_api.dart';
  6. import 'package:sport/services/api/resp.dart';
  7. import 'package:sport/widgets/image.dart';
  8. class SportDataCalendarPage extends StatefulWidget {
  9. final DateTime time;
  10. const SportDataCalendarPage({
  11. Key? key,
  12. required this.time,
  13. }) : super(key: key);
  14. @override
  15. State<StatefulWidget> createState() => _PageState();
  16. }
  17. class _PageState extends State<SportDataCalendarPage> with InjectApi {
  18. late PageController _pageController;
  19. @override
  20. void initState() {
  21. super.initState();
  22. DateTime t = DateTime.now();
  23. DateTime now = DateTime(t.year, t.month, t.day);
  24. _pageController = PageController(initialPage: now.year - widget.time.year);
  25. }
  26. @override
  27. void dispose() {
  28. _pageController.dispose();
  29. super.dispose();
  30. }
  31. @override
  32. Widget build(BuildContext context) {
  33. var today = DateTime.now().difference(widget.time).inDays == 0 ? true : false;
  34. return Scaffold(
  35. backgroundColor: Colors.transparent,
  36. body: Column(
  37. children: [
  38. Padding(
  39. padding: const EdgeInsets.all(16.0),
  40. child: Row(
  41. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  42. children: [
  43. Text("选择时间"),
  44. InkWell(
  45. onTap: () {
  46. Navigator.maybePop(context, DateTime.now());
  47. },
  48. child: Image.asset(
  49. "lib/assets/img/icon_table_today_select.png",
  50. width: 16,
  51. color: today ? Color(0xffFF5B1D) : null,
  52. ),
  53. ),
  54. ],
  55. ),
  56. ),
  57. Expanded(
  58. child: FutureProvider<List<SportHistory>>(
  59. create: (context) async {
  60. DateTime t = DateTime.now();
  61. try {
  62. RespList<SportHistory> resp = await api.getSportRecordHistory(t.year);
  63. return resp.results;
  64. } catch (e) {
  65. print(e);
  66. }
  67. return [];
  68. },
  69. initialData: [],
  70. builder: (context, child) {
  71. return PageView.builder(
  72. controller: _pageController,
  73. reverse: true,
  74. itemCount: 1000,
  75. itemBuilder: (context, index) {
  76. DateTime t = DateTime.now();
  77. DateTime now = DateTime(t.year, t.month, t.day);
  78. DateTime startDate = DateTime(now.year - index, 1, 1);
  79. DateTime endDate = DateTime(now.year + 1 - index, 1, 1);
  80. if (index == 0) {
  81. endDate = DateTime(now.year, now.month + 1, 1);
  82. }
  83. DateTime ee = endDate.subtract(Duration(days: 1));
  84. DateTime initialDate = DateTime(startDate.year, widget.time.month, widget.time.day);
  85. var _dot = Align(
  86. alignment: Alignment.bottomCenter,
  87. child: Container(
  88. width: 4,
  89. height: 4,
  90. margin: EdgeInsets.only(bottom: 6),
  91. decoration: BoxDecoration(shape: BoxShape.circle, color: const Color(0xffFF5B1D)),
  92. ));
  93. List<SportHistory> items = context.watch<List<SportHistory>>();
  94. SportHistory? history;
  95. for (var i in items) {
  96. if (i.year == startDate.year) {
  97. history = i;
  98. break;
  99. }
  100. }
  101. print("11111111 == $index == $now $startDate $endDate $ee ${widget.time} $initialDate items ${items.length}");
  102. return Column(
  103. children: [
  104. Row(
  105. mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  106. children: <Widget>[
  107. GestureDetector(
  108. behavior: HitTestBehavior.opaque,
  109. onTap: () => _pageController.nextPage(duration: Duration(milliseconds: 500), curve: Curves.linear),
  110. child: Padding(
  111. padding: const EdgeInsets.all(18.0),
  112. child: arrowLeft(),
  113. ),
  114. ),
  115. Text(
  116. "${startDate.year}",
  117. style: Theme.of(context).textTheme.headline3,
  118. ),
  119. index == 0
  120. ? Padding(
  121. padding: const EdgeInsets.all(18.0),
  122. child: arrowRight(color: Color(0x90cccccc)),
  123. )
  124. : GestureDetector(
  125. behavior: HitTestBehavior.opaque,
  126. onTap: () => _pageController.previousPage(duration: Duration(milliseconds: 500), curve: Curves.linear),
  127. child: Padding(
  128. padding: const EdgeInsets.all(18.0),
  129. child: arrowRight(),
  130. ),
  131. ),
  132. ],
  133. ),
  134. Row(
  135. children: ["一", "二", "三", "四", "五", "六", "日"].map((e) => Container(margin: const EdgeInsets.all(6.0), child: Text("$e"))).toList(),
  136. mainAxisAlignment: MainAxisAlignment.spaceAround,
  137. ),
  138. Expanded(
  139. child: PagedVerticalCalendar(
  140. startDate: startDate,
  141. endDate: ee,
  142. initialDate: initialDate,
  143. listPadding: EdgeInsets.all(8),
  144. monthBuilder: (context, month, year) {
  145. return Padding(
  146. padding: const EdgeInsets.all(12.0),
  147. child: Text(
  148. "$year年$month月",
  149. style: Theme.of(context).textTheme.subtitle1!,
  150. ),
  151. );
  152. },
  153. dayBuilder: (context, date) {
  154. // print("2222222222222222 == $now $date ${widget.time} ${now.difference(date).inDays}");
  155. bool hasData = false;
  156. if (history != null) {
  157. // print("3333333333333333 == ${history.year} ${history.data.length}");
  158. for (var i = 0; i < history.data.length; i++) {
  159. var m = history.data[i];
  160. // print("3333333333333333 == $m ");
  161. for (var d in m) {
  162. if (i == date.month - 1 && d == date.day) {
  163. // print("3333333333333333 == $m ${date.month} $d ${date.day}");
  164. hasData = true;
  165. }
  166. }
  167. }
  168. }
  169. return Container(
  170. margin: const EdgeInsets.all(6.0),
  171. decoration: widget.time.difference(date).inDays == 0 ? BoxDecoration(shape: BoxShape.circle, border: Border.all(width: 1, color: const Color(0xffFF5B1D))) : null,
  172. child: Stack(
  173. fit: StackFit.expand,
  174. children: [
  175. Center(
  176. child: Text(
  177. "${date.day}",
  178. style: now.difference(date).inDays >= 0 ? Theme.of(context).textTheme.subtitle1!.copyWith(fontSize: 16.0) : Theme.of(context).textTheme.bodyText2!.copyWith(fontSize: 16.0),
  179. )),
  180. if (hasData == true) _dot,
  181. ],
  182. ),
  183. );
  184. },
  185. onDayPressed: (date) {
  186. if (DateTime.now().difference(date).inSeconds < 0) return;
  187. Navigator.maybePop(context, date);
  188. },
  189. invisibleMonthsThreshold: 2,
  190. onMonthLoaded: (y, m) {},
  191. ),
  192. ),
  193. ],
  194. );
  195. });
  196. }),
  197. ),
  198. ],
  199. ),
  200. );
  201. }
  202. }