扑 - 检测的ListView滚动位置,它是在顶部或底部?

问题描述 投票:15回答:5

我试图实现无限滚动功能。

我试图用一个ListView内上NotificationListener检测滚动事件,但我看不到,说如果滚动已达到视图底部的事件。

这将是实现这一目标的最佳方式是什么?

dart infinite-scroll flutter
5个回答
22
投票

您可以使用ListView.builder创造无限的项目滚动列表。在需要时新的细胞都透露出你的itemBuilder将被调用。

如果你想被通知滚动事件,因此您可以装载更多的数据离开网络,你可以传递一个controller参数,并使用addListener听者连接到ScrollController。所述positionScrollController可用于确定滚动是否接近底部。


6
投票
_scrollController = new ScrollController();

    _scrollController.addListener(
        () {
            double maxScroll = _scrollController.position.maxScrollExtent;
            double currentScroll = _scrollController.position.pixels;
            double delta = 200.0; // or something else..
            if ( maxScroll - currentScroll <= delta) { // whatever you determine here
                //.. load more
            }
        }
    );

科林的应该被接受的答案....


5
投票
// create an instance variable
var _controller = ScrollController(); 

@override
void initState() {
  super.initState();

  // set up listener here
  _controller.addListener(() {
    if (_controller.position.atEdge) {
      if (_controller.position.pixels == 0)
        // you are at top position
      else
        // you are at bottom position
    }
  });
}

用法:

ListView(controller: _controller) // assign it like this

2
投票

我用无限滚动不同的方法。我用ChangeNotifier类变量的变化监听器。如果在变量的变化,则触发事件,并最终击中了API。

class DashboardAPINotifier extends ChangeNotifier {
   bool _isLoading = false;
    get getIsLoading => _isLoading;
    set setLoading(bool isLoading) => _isLoading = isLoading;
}

初始化DashboardAPINotifier类。

@override
  void initState() {
    super.initState();
    _dashboardAPINotifier = DashboardAPINotifier();
    _hitDashboardAPI(); // init state

    _dashboardAPINotifier.addListener(() {
      if (_dashboardAPINotifier.getIsLoading) {
        print("loading is true");
        widget._page++; // For API page
        _hitDashboardAPI(); //Hit API
      } else {
        print("loading is false");
      }
    });

  }

现在最好的部分是,当你打的API。如果您正在使用SliverList,那么在什么时候,你打的API。

SliverList(delegate: new SliverChildBuilderDelegate(
       (BuildContext context, int index) {
        Widget listTile = Container();
         if (index == widget._propertyList.length - 1 &&
             widget._propertyList.length <widget._totalItemCount) {
             listTile = _reachedEnd();
            } else {
                    listTile = getItem(widget._propertyList[index]);
                   }
            return listTile;
        },
          childCount: (widget._propertyList != null)? widget._propertyList.length: 0,
    addRepaintBoundaries: true,
    addAutomaticKeepAlives: true,
 ),
)


_reachEnd() method take care to hit the api. It trigger the `_dashboardAPINotifier._loading`

// Function that initiates a refresh and returns a CircularProgressIndicator - Call when list reaches its end
  Widget _reachedEnd() {
    if (widget._propertyList.length < widget._totalItemCount) {
      _dashboardAPINotifier.setLoading = true;
      _dashboardAPINotifier.notifyListeners();
      return const Padding(
        padding: const EdgeInsets.all(20.0),
        child: const Center(
          child: const CircularProgressIndicator(),
        ),
      );
    } else {
      _dashboardAPINotifier.setLoading = false;
      _dashboardAPINotifier.notifyListeners();
      print("No more data found");
      Utils.getInstance().showSnackBar(_globalKey, "No more data found");
    }
  }

注意:您的API响应后,您需要通知监听器,

setState(() {
        _dashboardAPINotifier.setLoading = false;
        _dashboardAPINotifier.notifyListeners();
        }

0
投票

我想补充的answer provided by collin jackson例子。请参考下面的代码片段

    var _scrollController = ScrollController();
    _scrollController.addListener(() {
      if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent) {
        // Perform your task
      }
    });

这只会触发时,最后一个项目是显示在列表中。

© www.soinside.com 2019 - 2024. All rights reserved.