Rém*_*let 39
你可以听一个ScrollController.
ScrollController有一些有用的信息,如scrolloffset和列表ScrollPosition.
在你的情况下,有趣的部分是controller.position当前可见的ScrollPosition.它代表可滚动的一部分.
ScrollPosition包含有关它在可滚动内部的位置的信息.如extentBefore和extentAfter.或者它的大小,有extentInside.
考虑到这一点,您可以触发基于extentAfter其的服务器调用,该调用表示可用的剩余卷轴空间.
这是使用我所说的基本示例.
class MyHome extends StatefulWidget {
@override
_MyHomeState createState() => new _MyHomeState();
}
class _MyHomeState extends State<MyHome> {
ScrollController controller;
List<String> items = new List.generate(100, (index) => 'Hello $index');
@override
void initState() {
super.initState();
controller = new ScrollController()..addListener(_scrollListener);
}
@override
void dispose() {
controller.removeListener(_scrollListener);
super.dispose();
}
@override
Widget build(BuildContext context) {
return new Scaffold(
body: new Scrollbar(
child: new ListView.builder(
controller: controller,
itemBuilder: (context, index) {
return new Text(items[index]);
},
itemCount: items.length,
),
),
);
}
void _scrollListener() {
print(controller.position.extentAfter);
if (controller.position.extentAfter < 500) {
setState(() {
items.addAll(new List.generate(42, (index) => 'Inserted $index'));
});
}
}
}
Run Code Online (Sandbox Code Playgroud)
您可以清楚地看到,当到达滚动的末尾时,由于加载了更多项目,滚动条会消耗掉.
Pan*_*rld 15
感谢RémiRousselet的方法,但它并没有解决所有问题.特别是当ListView滚动到底部时,它仍然会调用scrollListener几次.更好的方法是将Notification Listener与Remi的方法结合起来.这是我的解决方案:
bool _handleScrollNotification(ScrollNotification notification) {
if (notification is ScrollEndNotification) {
if (_controller.position.extentAfter == 0) {
loadMore();
}
}
return false;
}
@override
Widget build(BuildContext context) {
final Widget gridWithScrollNotification = NotificationListener<
ScrollNotification>(
onNotification: _handleScrollNotification,
child: GridView.count(
controller: _controller,
padding: EdgeInsets.all(4.0),
// Create a grid with 2 columns. If you change the scrollDirection to
// horizontal, this would produce 2 rows.
crossAxisCount: 2,
crossAxisSpacing: 2.0,
mainAxisSpacing: 2.0,
// Generate 100 Widgets that display their index in the List
children: _documents.map((doc) {
return GridPhotoItem(
doc: doc,
);
}).toList()));
return new Scaffold(
key: _scaffoldKey,
body: RefreshIndicator(
onRefresh: _handleRefresh, child: gridWithScrollNotification));
}
Run Code Online (Sandbox Code Playgroud)
chu*_*han 10
该解决方案使用 ScrollController,我看到了有关页面的评论。
我想分享我对包incrementally_loading_listview https://github.com/MaikuB/incrementally_loading_listview 的发现
。
正如打包所说:这可用于加载从 API 请求收到的分页数据。
基本上,当 ListView 构建最后一个项目时,这意味着用户已向下滚动到底部。
希望能帮到有类似问题的人。
出于演示目的,我已更改示例以让页面仅包含一项并添加一个 CircularProgressIndicator。
...
bool _loadingMore;
bool _hasMoreItems;
int _maxItems = 30;
int _numItemsPage = 1;
...
_hasMoreItems = items.length < _maxItems;
...
return IncrementallyLoadingListView(
hasMore: () => _hasMoreItems,
itemCount: () => items.length,
loadMore: () async {
// can shorten to "loadMore: _loadMoreItems" but this syntax is used to demonstrate that
// functions with parameters can also be invoked if needed
await _loadMoreItems();
},
onLoadMore: () {
setState(() {
_loadingMore = true;
});
},
onLoadMoreFinished: () {
setState(() {
_loadingMore = false;
});
},
loadMoreOffsetFromBottom: 0,
itemBuilder: (context, index) {
final item = items[index];
if ((_loadingMore ?? false) && index == items.length - 1) {
return Column(
children: <Widget>[
ItemCard(item: item),
Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: <Widget>[
Row(
crossAxisAlignment:
CrossAxisAlignment.start,
children: <Widget>[
Container(
width: 60.0,
height: 60.0,
color: Colors.grey,
),
Padding(
padding: const EdgeInsets.fromLTRB(
8.0, 0.0, 0.0, 0.0),
child: Container(
color: Colors.grey,
child: Text(
item.name,
style: TextStyle(
color: Colors.transparent),
),
),
)
],
),
Padding(
padding: const EdgeInsets.fromLTRB(
0.0, 8.0, 0.0, 0.0),
child: Container(
color: Colors.grey,
child: Text(
item.message,
style: TextStyle(
color: Colors.transparent),
),
),
)
],
),
),
),
Center(child: CircularProgressIndicator())
],
);
}
return ItemCard(item: item);
},
);
Run Code Online (Sandbox Code Playgroud)
完整示例https://github.com/MaikuB/incrementally_loading_listview/blob/master/example/lib/main.dart
包使用 ListView index = last item 和 loadMoreOffsetFromBottom 来检测何时加载更多。
itemBuilder: (itemBuilderContext, index) {
if (!_loadingMore &&
index ==
widget.itemCount() -
widget.loadMoreOffsetFromBottom -
1 &&
widget.hasMore()) {
_loadingMore = true;
_loadingMoreSubject.add(true);
}
Run Code Online (Sandbox Code Playgroud)
这是我查找 listView 结尾的解决方案
_scrollController.addListener(scrollListenerMilli);
if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent) {
getMoreData();
}
Run Code Online (Sandbox Code Playgroud)
如果您想在列表视图大小的 1/2 或 3/4 时加载更多数据,请使用这种方式。
if (_scrollController.position.pixels == (_scrollController.position.maxScrollExtent * .75)) {//.5
getMoreData();
}
Run Code Online (Sandbox Code Playgroud)
附加-> 确保getMore在到达底部时仅调用 API 一次。您可以通过多种方式解决这个问题,这是通过布尔变量解决这个问题的方法之一。
bool loadMore = false;
if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent && !loadMore) {
loadMore = true;
getMoreData().then(() => loadMore = false);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
14798 次 |
| 最近记录: |