首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >嵌套PageView:在内部PageView到达末尾时更改外部PageView

嵌套PageView:在内部PageView到达末尾时更改外部PageView
EN

Stack Overflow用户
提问于 2020-03-05 19:06:17
回答 2查看 406关注 0票数 5

考虑这样一种PageView用法,其中一个PageView位于另一个内部:

代码语言:javascript
复制
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过渡而不被卡住呢?

EN

回答 2

Stack Overflow用户

发布于 2020-03-10 18:09:52

一种简单的方法是使用通知侦听器和animateToPage:

代码语言:javascript
复制
@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'),
            ),
          ),
        ],
      ),
    ),
  );
}
票数 0
EN

Stack Overflow用户

发布于 2021-02-05 14:22:32

通过使用PageController控制页面视图,我有一个使用NotificationListener的变通方法。用户实际控制较低的PageView并将偏移量传递给较高的PageView。

代码语言:javascript
复制
  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包装它

代码语言:javascript
复制
NotificationListener(
  onNotification: (_)=> true,
  child: ListView.builder(
    scrollDirection: Axis.horizontal,
    itemBuilder: (ctx,index) => Container(width: 50,color: Colors.primaries[index%Colors.primaries.length],),
  ),
),

结果:

最后:

  • 为了简单起见,我只处理PageView
  • 的左侧滚动,当拖动到末尾时,我不实现PageScrollPhysic (根据速度和页面位置计算)。
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60543962

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档