考虑一下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过渡而不会卡住的同时取得相似的结果?
答案 0 :(得分:0)
一种简单的方法是使用Notification侦听器和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'),
),
),
],
),
),
);
}
答案 1 :(得分:0)
通过使用 NotificationListener
控制页面视图,我有一个使用 PageController
的解决方法。用户实际控制较低的 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],),
),
),
最后: