Flutter 中用于进展 PageView 的自定义滚动物理

jul*_*n.a 5 overriding flutter

我想PageView使用 custom创建一个进度ScrollPhysics,以便用户只能滚动到已完成的选项卡。请参阅下图以供参考,右上角是进度(绿色=可访问,红色=不可访问页面):

\n\n

1]

\n\n

在屏幕截图中,我完成了第 1 页和第 2 页,但我不想让用户滑动到当前正在发生的第 3 页。scroll_physics.dart我阅读了iOS 和 Android 实现的示例。但我还是被困住了。

\n\n

在这里尝试过这个尝试过,但它有问题。您可以阻止用户向右移动,但如果最后一个可访问的页面不完全可见(如屏幕截图所示),则滚动已被阻止,您无法进一步向右滚动。

\n\n

这是我现在的代码:

\n\n

电话来自:

\n\n
PageView(\n          controller: PageController(\n            initialPage: model.initallPage,\n          ),\n          children: pages,\n          physics: model.currentPage >= model.lastAccessiblePage ? CustomScrollPhysics(CustomScrollStatus()..rightEnd = true) : ScrollPhysics(),\n          onPageChanged: (value) {\n            model.currentPage = value;\n          },\n        ),\n
Run Code Online (Sandbox Code Playgroud)\n\n

自定义滚动物理:

\n\n
class CustomScrollStatus {\n  bool leftEnd = false;\n  bool rightEnd = false;\n  bool isGoingLeft = false;\n  bool isGoingRight = false;\n}\n\nclass CustomScrollPhysics extends ScrollPhysics {\n  final CustomScrollStatus status;\n\n  CustomScrollPhysics(\n    this.status, {\n    ScrollPhysics parent,\n  }) : super(parent: parent);\n\n  @override\n  CustomScrollPhysics applyTo(ScrollPhysics ancestor) {\n    return CustomScrollPhysics(this.status, parent: buildParent(ancestor));\n  }\n\n  @override\n  double applyPhysicsToUserOffset(ScrollMetrics position, double offset) {\n    status.isGoingLeft = offset.sign < 0;\n    return offset;\n  }\n\n  @override\n  double applyBoundaryConditions(ScrollMetrics position, double value) {\n    if (value < position.pixels && position.pixels <= position.minScrollExtent) {\n      print(\'underscroll\');\n      return value - position.pixels;\n    }\n    if (position.maxScrollExtent <= position.pixels && position.pixels < value) {\n      print(\'overscroll\');\n      return value - position.pixels;\n    }\n    if (value < position.minScrollExtent && position.minScrollExtent < position.pixels) {\n      print(\'hit top edge\');\n      return value - position.minScrollExtent;\n    }\n    if (position.pixels < position.maxScrollExtent && position.maxScrollExtent < value) {\n      print(\'hit bottom edge\');\n      return value - position.maxScrollExtent;\n    }\n\n    if (status.leftEnd) print("leftEnd");\n    if (status.rightEnd) print("rightEnd");\n    if (status.isGoingLeft) print("isGoingLeft");\n    if (status.isGoingRight) print("isGoingRight");\n\n    // do something to block movement > accesssible page\n\n    print(\'default\');\n    return 0.0;\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

编辑:

\n\n

我想到了一个完全不同的解决方案。动态更改 PageView 的子级。我仍然对覆盖 `ScrollPhysics\xc2\xb4 解决方案感兴趣,因为在我看来它更干净。

\n\n

children: pages

\n

Oma*_*att 1

如果您正在使用,PageView.builder则可以返回 null 来指示其他页面无法访问。你可以在这里查看我的答案,它与这个问题有点相似。

PageView.builder(
  controller: pageController,
  onPageChanged: getCurrentPage,
  itemBuilder: (context, position) {
    // stop at 5
    if (position == 5) return null;

    // else, create a page
    return createPage(position + 1);
  },
),
Run Code Online (Sandbox Code Playgroud)

至于在 PageView 末尾禁用滚动动画,本文最好地解释了解决方法