考虑这样一种PageView用法,其中一个PageView位于另一个内部:
PageView(
children: [
Container(color: Colors.red),
Column(
children: [
Text('Title'),
PageView(
children: [
Container(color: Colors.green),
Container(color: Colors.yellow),
],
),
],
)
],
);这样的架构将允许我们在外部PageView和内部PageView之间进行过渡。但是一旦我们到达了内在的PageView,我们就不能再出去了。
这是一个展示它的gif:

在这样的体系结构中,我们不能将两个PageView“合并”成一个,因为内部的PageView不会填满屏幕
我们如何才能达到类似的结果,同时允许从两个PageView过渡而不被卡住呢?
发布于 2020-03-10 18:09:52
一种简单的方法是使用通知侦听器和animateToPage:
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
color: Colors.yellow,
child: PageView(
controller: _parentController,
children: [
Container(
color: Colors.green,
child: Center(
child: Text('0'),
),
),
NotificationListener<OverscrollNotification>(
onNotification: (notification) {
if (notification.overscroll < 0)
_parentController.animateToPage(0,
duration: Duration(milliseconds: 400),
curve: Curves.easeInOutQuart);
if (notification.overscroll > 0)
_parentController.animateToPage(2,
duration: Duration(milliseconds: 400),
curve: Curves.easeInOutQuart);
return false;
},
child: PageView(
children: [
Container(
color: Colors.green,
child: Center(child: Text('2: 0')),
),
Container(
color: Colors.blue,
child: Center(child: Text('2: 1')),
),
],
),
),
Container(
color: Colors.red,
child: Center(
child: Text('2'),
),
),
],
),
),
);
}发布于 2021-02-05 14:22:32
通过使用PageController控制页面视图,我有一个使用NotificationListener的变通方法。用户实际控制较低的PageView并将偏移量传递给较高的PageView。
final _pageController1 = PageController(); // Controlled
final _pageController2 = PageController(); // Controller
@override
Widget build(BuildContext context) {
var leftOverScroll = 0.0; // total over-scroll offset on left side
return PageView(
controller: _pageController1,
children: [
Container(color: Colors.red),
Column(
children: [
Text('Title'),
Expanded(
child: NotificationListener(
onNotification: (notification){
// over scroll to the left side
if (notification is OverscrollNotification && notification.overscroll < 0) {
leftOverScroll += notification.overscroll;
_pageController1.position.correctPixels(_pageController1.position.pixels + notification.overscroll);
_pageController1.position.notifyListeners();
}
// scroll back after over scrolling
if (leftOverScroll < 0) {
if (notification is ScrollUpdateNotification) {
final newOverScroll = math.min(notification.metrics.pixels + leftOverScroll, 0.0);
final diff = newOverScroll - leftOverScroll;
_pageController1.position.correctPixels(_pageController1.position.pixels + diff);
_pageController1.position.notifyListeners();
leftOverScroll = newOverScroll;
}
_pageController2.position.correctPixels(0);
_pageController2.position.notifyListeners();
}
// release
if(notification is UserScrollNotification && notification.direction == ScrollDirection.idle && leftOverScroll != 0){
_pageController1.previousPage(curve: Curves.ease, duration: Duration(milliseconds: 400));
leftOverScroll = 0;
}
return false;
},
child: PageView(
controller: _pageController2,
children: [
Container(color: Colors.green),
Container(color: Colors.yellow),
],
),
),
),
],
),
],
);
}至于如何避免来自另一个子部件的通知,我只能考虑用另一个NotificationListener包装它
NotificationListener(
onNotification: (_)=> true,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemBuilder: (ctx,index) => Container(width: 50,color: Colors.primaries[index%Colors.primaries.length],),
),
),结果:

最后:
https://stackoverflow.com/questions/60543962
复制相似问题