在此方面寻求帮助,乍看起来似乎很简单,但是却无法解决...
基本上,我正在尝试制作一个具有垂直可滚动listView的垂直可滚动listView的页面。例如,列表在页面2上,用户在页面1上,然后向下滚动到页面2。现在,他向下滚动直到列表的末尾,我希望他能够滚动到比页面更多的位置3。
关于如何实施此建议?
答案 0 :(得分:1)
对我有用的是,我们需要附加ListView的滚动控制器以侦听滚动位置。然后页面控制器将移至下一页或上一页。
PageController pageController;
ScrollController scrollController;
@override
void initState() {
super.initState();
pageController = PageController();
scrollController = ScrollController();
scrollController.addListener(() {
// listView reaches the bottom
if (scrollController.offset >= scrollController.position.maxScrollExtent - 100 &&
!scrollController.position.outOfRange) {
pageController.nextPage(duration: const Duration(seconds: 1), curve: ElasticOutCurve());
}
// listView reaches the top
if (scrollController.offset <= scrollController.position.minScrollExtent &&
!scrollController.position.outOfRange) {
pageController.previousPage(duration: const Duration(seconds:1), curve: ElasticOutCurve());
}
});
}
别忘了连接控制器
PageView(
controller: pageController,
...
ListView(
controller: scrollController,
...
答案 1 :(得分:1)
此GitHub issue有一个方便的解决方案,我认为您需要的每个页面之间都有“悬停”行为。这是线程中提供的示例代码:
void main() => runApp(App());
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(),
body: Example()
)
);
}
}
class Example extends StatefulWidget {
@override
_ExampleState createState() => _ExampleState();
}
class _ExampleState extends State<Example> {
PageController _pageController;
ScrollController _listScrollController;
ScrollController _activeScrollController;
Drag _drag;
@override
void initState() {
super.initState();
_pageController = PageController();
_listScrollController = ScrollController();
}
@override
void dispose() {
_pageController.dispose();
_listScrollController.dispose();
super.dispose();
}
void _handleDragStart(DragStartDetails details) {
if (_listScrollController.hasClients && _listScrollController.position.context.storageContext != null) {
final RenderBox renderBox = _listScrollController.position.context.storageContext.findRenderObject();
if (renderBox.paintBounds.shift(renderBox.localToGlobal(Offset.zero)).contains(details.globalPosition)) {
_activeScrollController = _listScrollController;
_drag = _activeScrollController.position.drag(details, _disposeDrag);
return;
}
}
_activeScrollController = _pageController;
_drag = _pageController.position.drag(details, _disposeDrag);
}
void _handleDragUpdate(DragUpdateDetails details) {
if (_activeScrollController == _listScrollController && details.primaryDelta < 0 && _activeScrollController.position.pixels == _activeScrollController.position.maxScrollExtent) {
_activeScrollController = _pageController;
_drag?.cancel();
_drag = _pageController.position.drag(
DragStartDetails(
globalPosition: details.globalPosition,
localPosition: details.localPosition
),
_disposeDrag
);
}
_drag?.update(details);
}
void _handleDragEnd(DragEndDetails details) {
_drag?.end(details);
}
void _handleDragCancel() {
_drag?.cancel();
}
void _disposeDrag() {
_drag = null;
}
@override
Widget build(BuildContext context) {
return RawGestureDetector(
gestures: <Type, GestureRecognizerFactory>{
VerticalDragGestureRecognizer: GestureRecognizerFactoryWithHandlers<VerticalDragGestureRecognizer>(
() => VerticalDragGestureRecognizer(),
(VerticalDragGestureRecognizer instance) {
instance
..onStart = _handleDragStart
..onUpdate = _handleDragUpdate
..onEnd = _handleDragEnd
..onCancel = _handleDragCancel;
}
)
},
behavior: HitTestBehavior.opaque,
child: PageView(
controller: _pageController,
scrollDirection: Axis.vertical,
physics: const NeverScrollableScrollPhysics(),
children: [
ListView(
controller: _listScrollController,
physics: const NeverScrollableScrollPhysics(),
children: List.generate(
25,
(int index) {
return ListTile(
title: Text('Item $index')
);
}
)
),
Center(
child: Text('Page 2')
)
],
)
);
}
}