我有类似的问题。我决定使用带有 SetState 的解决方案 -> 更新(重建)页面列表(在开始或结束时添加新的)并设置当前索引以保持当前页面可见。问题是页面完全更改之前触发的 _onPageChanged 方法(这意味着该方法在动画期间被触发)。 SetState 导致从未完成的动画跳转到显示静态页面。我用动画监听器测试了解决方案(找到动画的结尾),但是这个方法在完全不可预测的时刻被触发了。
最后我使用 _onPageChanged -> SetState 和页面列表,但我的列表扩展到 15 个元素 - 从今天到 +- 7 天我有流畅的动画。下一个不顺利,另一个 7 好 :)
我的用户通常不会在当天起 7 天后移动,但我对这个解决方案并不感到自豪。也许有人有更好的解决方案?
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:gymprogress/page-dashboard-widget.dart';
import 'package:gymprogress/chooseDateFromCalendar.dart';
import 'package:gymprogress/page-dashboard-timeline.dart';
import 'package:gymprogress/globals.dart';
import 'package:gymprogress/reusable/pageTemplate.dart';
import 'package:random_color/random_color.dart';
class Dashboard extends StatefulWidget {
Dashboard({Key key}) : super(key: key);
@override
_DashboardState createState() => _DashboardState();
}
class _DashboardState extends State<Dashboard> {
List<DashboardPageWidget> _daysList = [];
List<DashboardPageWidget> daysList = [];
DateTime _currentDate;
int _currentPageIndex;
int offset = 7;
PageController _controller = PageController(initialPage: 7, keepPage: false );
final List<ColorHue> _hueType = <ColorHue>[
ColorHue.green,
ColorHue.red,
ColorHue.pink,
ColorHue.purple,
ColorHue.blue,
ColorHue.yellow,
ColorHue.orange
];
ColorBrightness _colorLuminosity = ColorBrightness.veryLight;
ColorSaturation _colorSaturation = ColorSaturation.highSaturation;
@override
void initState() {
_currentDate = DateTime.now();
super.initState();
_goToDate(_currentDate);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Container(
child: Stack(
children: <Widget>[
ScaffoldTemplate(body: body()),
],
),
);
}
Widget body() {
return Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
actionPanel(),
Timeline(
date: _currentDate,
onPrevButton: () => _prevPressed(),
onNextButton: () => _nextPressed(),
),
Expanded(
child: bodyPageController()
),
],
),
);
}
Widget bodyPageController() {
return PageView(
scrollDirection: Axis.horizontal,
controller: _controller,
onPageChanged: (index) {_onPageChanged(index);
},
children: _daysList,
);
}
_myRandomColor(){
return RandomColor().randomColor(
colorHue: ColorHue.multiple(colorHues: _hueType),
colorSaturation: _colorSaturation,
colorBrightness: _colorLuminosity);
}
Widget actionPanel(){
return Container(
width: screenWidth,
// height: 50,
color: Color(0xFF068FFA),
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 2, 0, 2),
child: Row(
children: <Widget>[
Expanded(
flex: 1,
child: Container(
child: Column(
children: <Widget>[
IconButton(
tooltip: 'Dodaj swój nowy trening',
icon: FaIcon(FontAwesomeIcons.calendarPlus, color: Colors.white,),
color: Colors.red,
onPressed: () => _goToDate(DateTime.now()),
),
],
),
),
),
Expanded(
flex: 1,
child: Container(
child: Column(
children: <Widget>[
IconButton(
tooltip: 'Przejdź do dnia dzisiejszego',
icon: FaIcon(FontAwesomeIcons.calendarCheck, color: Colors.white,),
color: Colors.red,
onPressed: () => _goToDate(DateTime.now()),
),
],
),
),
),
Expanded(
flex: 1,
child: Container(
child: Column(
children: <Widget>[
IconButton(
tooltip: 'Wybierz datę z kalendarza',
icon: FaIcon(FontAwesomeIcons.calendarAlt, color: Colors.white,),
color: Colors.red,
onPressed: () => _openCalendar(),
),
],
),
),
),
],
),
)
);
}
_prevPressed(){
setState(() {
_controller.animateToPage(_currentPageIndex-1, duration: Duration(milliseconds: 200), curve: Curves.ease);
});
}
_nextPressed(){
setState(() {
_controller.animateToPage(_currentPageIndex+1, duration: Duration(milliseconds: 200), curve: Curves.ease);
});
}
_onPageChanged(index){
_currentPageIndex = index;
if((_currentPageIndex<1) || (_currentPageIndex>(2*offset-1))){
_goToDate(_daysList[index].day.date);
}
setState(() {
_currentDate = _daysList[_currentPageIndex].day.date;
});
}
_goToDate(DateTime _date) async{
await _buildPageView(_date);
_controller.jumpToPage(offset);
}
_buildPageView(_date) {
DateTime date = DateTime(_date.year, _date.month, _date.day);
daysList = [];
for (var i=0; i<(2*offset+1); i++){
daysList.add(DashboardPageWidget(day: Day(date.add(Duration(days: i-offset)), _myRandomColor()),));
print(i.toString());
}
setState(() {
_daysList = daysList;
_currentDate = date;
_currentPageIndex = offset;
});
}
_openCalendar() async{
await Navigator.of(context).push(
PageRouteBuilder(
opaque: false, // set to false
pageBuilder: (_, __, ___) => SelectDateFromCalendar(),
)).then((value){
print(value);
_goToDate(value);
});
}
}
class Day{
DateTime date;
Color color;
Day(DateTime date, Color color){
this.date = date;
this.color = color;
}
}