【问题标题】:How to force ScrollController to recalculate position.maxExtents?如何强制 ScrollController 重新计算 position.maxExtents?
【发布时间】:2020-03-25 19:04:50
【问题描述】:

我正在尝试创建一个桌面样式的滚动条,它会根据内容的大小来改变它的大小。我的滚动条与一个列表共享一个 ScrollController,并依靠 position.maxExtents 知道内容区域有多大。

问题是当我更改行数时,maxExtents 不会更新,直到启动滚动事件。

我用这样的代码解决了这个问题,在 100 毫秒内向上移动 1px,向下移动 1px:

widget.controller.jumpTo(controller.position.pixels + 1);
Future.microtask(() => widget.controller.animateTo(controller.position.pixels - 1, duration: 100.milliseconds, curve: Curves.linear));

当列表可以滚动时,效果非常好。但是,当列表

我怎么能只告诉列表:“嘿,列表,重新计算你的孩子!”?

【问题讨论】:

    标签: flutter flutter-layout


    【解决方案1】:

    除了您提到的问题之外,为滚动位置设置动画会导致 Flutter 不必要地绘制帧。

    借用@ltk@Rakaton,我认为有一种更简单有效的方法:

    // Run this code whenever the layout changes (i.e. any time you setState
    // to update the list content)
    WidgetsBinding.instance?.addPostFrameCallback((_) {
      widget.scrollController.position.notifyListeners();
    });
    

    您可能还希望将列表组件包装在 SizeChangedLayoutNotifier 中,以检测窗口调整大小等大小变化:

    NotificationListener<SizeChangedLayoutNotification>(
      onNotification: (notification) {
        WidgetsBinding.instance?.addPostFrameCallback((_) {
          scrollController.position.notifyListeners();
        });
        return true;
      },
      child: SizeChangedLayoutNotifier(
        child: ListView(
          // ...
        ),
      ),
    );
    

    【讨论】:

      【解决方案2】:

      您可以使用以下方法将代码延迟到控制器更新后。

      WidgetsBinding.instance.addPostFrameCallback((_) {
        ...your code which requires controller's max extents...   
      });
      

      【讨论】:

      • 谢谢,我面前没有那个代码了。但是iirc,问题是在列表被物理滚动之前,实际上并没有重新计算大小,无论是通过触摸还是以编程方式。这就是为什么我不得不强制它滚动 1px。
      • 我今天跳进了这个问题。只是我的猜测,控制器确实会重新计算范围,但新值仅在构建周期结束时可用。当您更改可滚动内容并在此之后立即执行代码时,它仍处于旧状态的构建周期内。并且 postFrameCallback 将您的代码推迟到新的范围值准备好时完成。
      【解决方案3】:

      我认为你应该考虑使用强制像素,但它是一种受保护的方法,所以它会给你一个警告。而且我不知道性能或其他有关它的东西。

      widget.controller.position.forcePixels(controller.position.pixels + 1);
      

      或正确像素和通知侦听器的组合。

      widget.controller.position.correctPixels(controller.position.pixels + 1);
      widget.controller.position.notifyListeners();
      

      【讨论】:

        猜你喜欢
        • 2020-12-10
        • 2014-04-17
        • 1970-01-01
        • 1970-01-01
        • 2023-03-27
        • 1970-01-01
        • 1970-01-01
        • 2023-04-02
        • 2012-11-30
        相关资源
        最近更新 更多