我试图实现无限滚动功能。
我试图用一个ListView
内上NotificationListener
检测滚动事件,但我看不到,说如果滚动已达到视图底部的事件。
这将是实现这一目标的最佳方式是什么?
您可以使用ListView.builder
创造无限的项目滚动列表。在需要时新的细胞都透露出你的itemBuilder
将被调用。
如果你想被通知滚动事件,因此您可以装载更多的数据离开网络,你可以传递一个controller
参数,并使用addListener
听者连接到ScrollController
。所述position
的ScrollController
可用于确定滚动是否接近底部。
_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
}
}
);
科林的应该被接受的答案....
// 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
我用无限滚动不同的方法。我用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();
}
我想补充的answer provided by collin jackson例子。请参考下面的代码片段
var _scrollController = ScrollController();
_scrollController.addListener(() {
if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent) {
// Perform your task
}
});
这只会触发时,最后一个项目是显示在列表中。