如何在Flutter中仅向下滚动?

3

我有一个可以在上下方向滚动的页面视图。我能否使它只能向下滚动,一旦向下滚动就无法向上滚动?我查询了谷歌,但没有找到有用的结果。

更新:

class _ScrollDownOnlyState extends State<ScrollDownOnly> {
  bool checkDir = false;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Down scroll"),
      ),
      body: PageView.builder(
        scrollDirection: Axis.vertical,
        physics: checkDir ? const NeverScrollableScrollPhysics() : const AlwaysScrollableScrollPhysics(),
        itemBuilder: (context, index) {
          print("checl $checkDir");
          return GestureDetector(
            onPanUpdate: (details) {
              print(details.delta.dy);
              if (details.delta.dy > 0) {
                setState(() {
                  checkDir = true;
                });
              }
              if (details.delta.dy < 0) {
                // set your var
                setState(() {
                  checkDir = false;
                });
              }
            },
            child: Container(
              margin: EdgeInsets.only(top: 20),
              color: Colors.pink,
              child: Center(
                child: Text(
                  "${index + 1}",
                  style: TextStyle(color: Colors.white, fontSize: 30),
                ),
              ),
            ),
          );
        },
        itemCount: 50,
      ),
    );
  }
}
3个回答

2

我自己也卡在这里一段时间(其他发布的答案对我不起作用),所以我发表我的解决方案:

每当用户按允许的方向滚动时,我会从列表中删除一个元素(在示例中为myItems)。在我的情况下,我已经配置了(未显示)我的ListView以将滚动捕捉到可预测的位置,以便任何滚动都会使一个元素离开屏幕(因此myItems.removeAt(0)就足够了)。如果有多个元素同时滑出屏幕,您需要以某种方式计数,以便您删除已滑出屏幕的数量。由于我还在从列表中删除元素后使用了setState,因此ListView也会相应更新。

NotificationListener(
  onNotification: (scroll) {
    if (scroll is UserScrollNotification && scroll.direction == ScrollDirection.reverse) {
       scrolling = true;
    } else if (scroll is UserScrollNotification && scroll.direction == ScrollDirection.forward) {
       scrolling = false;
    }
    if (scrolling && scroll is ScrollEndNotification && scroll.metrics.axisDirection == AxisDirection.right) {
      scrolling = false;
      setState(() {
        myItems.removeAt(0);
      });
    }   
    return true;
  },
  child: ListView(
           key: ObjectKey(myItems),
           children: myItems,
           scrollDirection: Axis.horizontal,
         ),
)

请注意,我还使用一个变量(我已命名为scrolling)来跟踪状态。这是必要的,因为尝试向相反方向滚动仍会在允许的方向触发ScrollEndNotification。只有当用户在允许的方向上启动滚动时,我才设置scrolling = true,以便只在那些条件下对ScrollEndNotifications调用setState。有关ScrollNotifications如何工作的更多详细信息,请参见此处:https://api.flutter.dev/flutter/widgets/ScrollNotification-class.html 另请注意,我的示例水平运行,防止用户从左到右滑动以进行滚动,并允许用户通过从右到左滑动来滚动。您可以通过更改scrollDirection参数并微调ScrollDirectionAxisDirection术语来使此方法适应垂直(仅向上或仅向下),直到看到所需的行为。

说得好,兄弟!:D - kaeland

1
你可以例如使用一个变量scrollDir并将其应用于PageView
physics: scrollDir ? const  NeverScrollableScrollPhysics() : const AlwaysScrollableScrollPhysics(),

使用 NeverScrollableScrollPhysics() 可以禁止滚动。使用 AlwaysScrollableScrollPhysics() 可以启用滚动功能。
通过使用 GestureDetector 检测上下滚动,您可以完全控制滚动。总体而言,它可能看起来像这样:
PageView(
            children: <Widget>[
              // Add children here
              GestureDetector(
                  onPanUpdate: (details) {
                    if (details.delta.dy > 0) {
                      setState(() {
                        checkDir = true;
                      });
                    }
                    if (details.delta.dy < 0) {
                      // set your var
                      checkDir = false;
                    }
                  },
                  child: Container(child: Text('MY WIDGETS')))
            ],
            physics: checkDir
                ? const NeverScrollableScrollPhysics()
                : const AlwaysScrollableScrollPhysics(),
          )),

Scrollphysics文档: https://api.flutter.dev/flutter/widgets/ScrollPhysics-class.html

GestureDetector文档: https://api.flutter.dev/flutter/widgets/GestureDetector-class.html


我可以将这个应用于PageView.builder吗?@MarcelDz - Naveen
几乎相同。您会将手势检测器放在项目构建器小部件之上。 - Marcel Dz
如果我帮助了您,请将其标记为答案,以便其他用户使用。 - Marcel Dz
当然。我会尝试并告诉你。 - Naveen
1
即使添加了 setstate,我仍然可以向上滚动。我已经更新了最新的代码@Marcel Dz - Naveen
显示剩余2条评论

0

您可以通过覆盖applyPhysicsToUserOffset来创建自定义的scrollphysics。

  @override
  double applyPhysicsToUserOffset(ScrollMetrics position, double offset) {
    return offset > 0 ? 0 : offset;
  }

然后在你的页面视图中实例化你的CustomScrollPhysics


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接