Flutter使用ScrollController检测用户滚动

5

项目

你好,我正在尝试使用自定义控制器和监听器在Flutter中构建简单的列表。以下是代码:

class Test2 extends StatefulWidget {
  @override
  _Test2State createState() => _Test2State();
}

class _Test2State extends State<Test2> {
  ScrollController scrollController = ScrollController();

  @override
  void initState() {
    scrollController.addListener((){
      print('controller called');
    });
    super.initState();
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: ListView.builder(
          controller: scrollController,
      itemCount: 8,
      itemBuilder: (context, index) {
        return Padding(
          padding: const EdgeInsets.all(8.0),
          child: Container(
            color: Colors.white,
            height: 50,
          ),
        );
      },
    ));
  }
}

问题

我的代码按预期工作,但我想在没有滑动内容时检测用户的滑动。目前,如果列表超出屏幕时调用用户滑动滚动监听器,但当项目列表短于屏幕尺寸时,这种情况不会发生。 如何强制监听器始终监听?


尝试使用NotificationListener了吗? - pskink
即使列表太短而无法滚动,它是否仍能检测到滑动操作? - justAnotherOverflowUser
2个回答

8

也许这段代码可以帮到你。

将脚手架包装在NotificationListener中,可以监听所有事件,即使itemCount为零。

不要忘记提供一个AlwaysScrollableScrollPhysics物理对象。

import 'dart:math' as math;

import 'package:flutter/material.dart';

class TestPage extends StatefulWidget {
  @override
  _TestPageState createState() => _TestPageState();
}

class _TestPageState extends State<TestPage> {
  @override
  Widget build(BuildContext context) {
    final ScrollController scrollController = ScrollController();

    return NotificationListener(
      child: Scaffold(
        body: ListView.builder(
          controller: scrollController,
          physics: const AlwaysScrollableScrollPhysics(),
          itemCount: 0,
          itemBuilder: (context, index) {
            return Container(
              color: Colors.black,
              height: 50,
            );
          },
        ),
      ),
      onNotification: (notificationInfo) {
        if (notificationInfo is ScrollStartNotification) {
          print("scroll");
          print("detail:"+notificationInfo.dragDetails.toString());
          /// your code
        }
        return true;
      },
    );
  }
}

由于这个未解决的问题 https://github.com/flutter/flutter/issues/44732,目前这个功能无法正常工作。 - ANDYNVT
如果我在这里放置一个像scroll to index这样的函数,就会出现多个错误。有没有一种方法可以识别用户是否向右滚动,然后跳到下一个正确的索引,如果用户向左滚动,则转到上一个索引? - Md. Kamrul Amin

3
你需要将自定义的滚动监听器传递给以下函数: scrollController.addListener(_scrollListener); 完整代码:
@override
  void initState() {
    scrollController.addListener(_scrollListener);
    super.initState();
}

以及您的自定义滚动监听器方法:

_scrollListener() {
    if (_controller.offset >= _controller.position.maxScrollExtent &&
        !_controller.position.outOfRange) {
      setState(() {
        message = "reach the bottom";
      });
    }
    if (_controller.offset <= _controller.position.minScrollExtent &&
        !_controller.position.outOfRange) {
      setState(() {
        message = "reach the top";
      });
    }
  }

来源:https://medium.com/@diegoveloper/flutter%E4%BA%86%E8%A7%A3scrollcontroller%E5%92%8Cscrollnotification-652b2685a4ac


2
问题在于如果没有实际滚动,scrollListener将不会触发。我的列表是动态构建的,我不知道列表是否会超出屏幕高度。 - justAnotherOverflowUser
如果列表视图无法滚动,您想要做什么? - OMi Shah
我想触发一个设置状态,以折叠该部分。 - justAnotherOverflowUser
那么为什么不使用“Wrap(children: <Widget>[]))”方法或列呢?Column( mainAxisSize: MainAxisSize.max, children: <Widget>[], ); - OMi Shah
因为我不知道会有多少个列表视图元素被构建。它们是动态的。在这个例子中,我为了简单起见硬编码了元素的数量。 - justAnotherOverflowUser
这就是为什么我建议了一些东西给你 :) 请检查您回复此消息的上方。 - OMi Shah

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