week_page.dart 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. import 'package:flutter/material.dart';
  2. import 'calendar_utils.dart' show get2Weekdays, addDay, subtractDay, firstDayOfWeek;
  3. import 'day_table_view.dart';
  4. enum PageState {
  5. previous,
  6. current,
  7. next,
  8. }
  9. /// 一周的Days的PageView页面
  10. class WeekPage extends StatefulWidget {
  11. const WeekPage({
  12. super.key,
  13. required this.selectedDate,
  14. required this.now,
  15. required this.isAutoSelect,
  16. this.onChangedSelectedDate,
  17. this.onChangedPage,
  18. });
  19. final DateTime now;
  20. final DateTime selectedDate;
  21. final bool isAutoSelect;
  22. final Function(DateTime)? onChangedSelectedDate; //选择日期变化的监听
  23. final Function(DateTime date, PageState state)? onChangedPage; //切换日期Page的监听
  24. final double height = 40 + 40 + 10;
  25. @override
  26. State<StatefulWidget> createState() => _WeekPageState();
  27. }
  28. class _WeekPageState extends State<WeekPage> {
  29. double get height => widget.height;
  30. final int initialPage = 999;
  31. List<int> pageCounts = [0, 1, 2];
  32. int currentPage = 1;
  33. late DateTime _currentPageDate;
  34. late DateTime _slectedDate;
  35. DateTime get now => widget.now;
  36. DateTime get selectedDate => widget.selectedDate;
  37. @override
  38. void initState() {
  39. super.initState();
  40. _currentPageDate = selectedDate;
  41. _slectedDate = selectedDate;
  42. }
  43. @override
  44. Widget build(BuildContext context) {
  45. return Flexible(
  46. child: AnimatedSize(
  47. duration: const Duration(milliseconds: 250),
  48. curve: Curves.easeInOut,
  49. alignment: Alignment.topCenter,
  50. child: SizedBox(
  51. height: height,
  52. child: pageViewBuilder(),
  53. ),
  54. ),
  55. );
  56. }
  57. //PageView的方式展示不同的星期,每周每一个Page
  58. Widget pageViewBuilder() {
  59. final PageController pageController = PageController(initialPage: initialPage);
  60. return PageView.builder(
  61. itemBuilder: (context, index) {
  62. final idx = _getIndex(index);
  63. return dayTable(idx);
  64. },
  65. onPageChanged: onPageChanged,
  66. controller: pageController,
  67. );
  68. }
  69. //两周的数据
  70. Widget dayTable(int index) {
  71. int at = pageCounts[index] - 1;
  72. final weekdays = get2Weekdays(now, at);
  73. return DayTableView(
  74. weekdays: weekdays,
  75. onSelect: (date) {
  76. setState(() {
  77. _slectedDate = date;
  78. });
  79. //主动点击之后回调
  80. widget.onChangedSelectedDate?.call(date);
  81. },
  82. selectedDate: _slectedDate,
  83. currentDate: now,
  84. );
  85. }
  86. //是否需要切换页面的时候自动选中
  87. void changeSelectedDate(int value) {
  88. if (_pageState(value) == PageState.next) {
  89. if (widget.isAutoSelect) {
  90. _slectedDate = addDay(selectedDate, 14);
  91. widget.onChangedSelectedDate?.call(_slectedDate);
  92. }
  93. } else {
  94. if (widget.isAutoSelect) {
  95. _slectedDate = subtractDay(selectedDate, 14);
  96. widget.onChangedSelectedDate?.call(_slectedDate);
  97. }
  98. }
  99. }
  100. //当切换页面的时候更新当前页面数据,返回当前页面第一条数据的日期
  101. void updateCurrentPageDate(int value) {
  102. final first = firstDayOfWeek(_currentPageDate);
  103. if (_pageState(value) == PageState.next) {
  104. _currentPageDate = addDay(first, 14);
  105. widget.onChangedPage?.call(_currentPageDate, PageState.next);
  106. } else {
  107. _currentPageDate = subtractDay(first, 14);
  108. widget.onChangedPage?.call(_currentPageDate, PageState.previous);
  109. }
  110. }
  111. void onPageChanged(int value) {
  112. changeSelectedDate(value);
  113. updateCurrentPageDate(value);
  114. int currentIndex = _getIndex(value);
  115. int leftIndex = (currentIndex - 1 < 0) ? pageCounts.length - 1 : currentIndex - 1;
  116. int rightIndex = (currentIndex + 1 > pageCounts.length - 1) ? 0 : currentIndex + 1;
  117. pageCounts[leftIndex] = pageCounts[currentIndex] - 1;
  118. pageCounts[rightIndex] = pageCounts[currentIndex] + 1;
  119. currentPage = pageCounts[currentIndex];
  120. }
  121. int _getIndex(int idx) {
  122. return (idx + 1) % pageCounts.length;
  123. }
  124. PageState _pageState(int idx) {
  125. final prePage = currentPage;
  126. final current = pageCounts[_getIndex(idx)];
  127. return (prePage < current) ? PageState.next : PageState.previous;
  128. }
  129. }