我想我已经成功了。我没有使用onPageChange
事件。相反,我聆听了控制器中的变化。
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
static const Widget _home = HomePage();
@override
Widget build(BuildContext context) => MaterialApp(
home: _home,
);
}
class HomePage extends StatefulWidget {
const HomePage();
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
late PageController _controller;
// This points always to the mid-element in _list
late int _initialIndex;
// This should work with 3, 7, 11, ... odd elements. Mind the pattern!!!
List<int> _list = [-2, -1, 0, 1, 2];
@override
void initState() {
super.initState();
// Calculate mid.
_initialIndex = (_list.length / 2).floor();
_controller = PageController(initialPage: _initialIndex, viewportFraction: 0.8);
// This is where we listen to changes.
_controller.addListener(() {
// Get index according to the direction
// _controller.page! > _initialIndex => swiping to the right, going to the left / previous element
// _controller.page! < _initialIndex => swiping to the left, going to the right / next element
final index = _controller.page! > _initialIndex ? _controller.page!.floor() : _controller.page!.ceil();
if (index == _initialIndex) return;
if (index == _initialIndex - 1) {
_prev();
} else if (index == _initialIndex + 1) {
_next();
}
});
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
// Update list and jump to the middle element
void _next() {
setState(() {
_list
..removeAt(0)
..insert(_list.length, _list.last + 1);
// Update current DateTime here
});
_controller.jumpToPage(_initialIndex);
}
// Update list and jump to the middle element
void _prev() {
setState(() {
_list
..insert(0, _list.first - 1)
..removeLast();
// Update current DateTime here
});
_controller.jumpToPage(_initialIndex);
}
@override
Widget build(BuildContext context) => Scaffold(
appBar: AppBar(
actions: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 20.0),
child: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () {
_prev();
},
),
),
Padding(
padding: const EdgeInsets.only(right: 20.0),
child: IconButton(
icon: const Icon(Icons.arrow_forward),
onPressed: () {
_next();
},
),
),
],
),
body: PageView.builder(
controller: _controller,
itemCount: _list.length,
itemBuilder: (context, i) {
// This is where you should put your widget that generates
// the view of the month.
// Calculate DateTime like so 'DateTime(initialDate.year, initialDate.month + _list[index], initialDate.day)'
return Padding(
padding: const EdgeInsets.all(32.0),
child: Container(
color: Colors.blueAccent[100],
alignment: Alignment.center,
child: Text(
'${_list[i]}',
style: const TextStyle(fontSize: 32),
),
),
);
}
),
);
}