Как добавить дополнительные элементы при прокрутке в списке?
Этот код здесь в настоящее время загружает все варево, которые хранятся в коллекции Firestore.. Как я могу загрузить сначала только 10 варок, а затем, когда пользователь прокручивает вниз и достигает конца списка из 10 варок.. он должен загрузиться Еще 10 после последнего заварки.. и заварки должны быть отсортированы по отметке времени.
class BrewList extends StatefulWidget {
@override
_BrewListState createState() => _BrewListState();
}
class _BrewListState extends State<BrewList> {
List<Brew> brews = [];
ScrollController _controller = ScrollController();
@override
void initState() {
_startFirst();
super.initState();
_controller.addListener(_scrollListener);
}
_scrollListener() {
setState(() {
if (_controller.position.atEdge) {
if (_controller.position.pixels == 0) {
} else {
}
}
});
}
_startFirst() async {
brews = await DatabaseService().brews ?? [];
setState(() {
brews = brews;
});
}
@override
Widget build(BuildContext context) {
Future<void> _refreshBrews() async {
List<Brew> tempList = await DatabaseService().brews;
setState(() {
brews = tempList;
});
print(brews);
}
return RefreshIndicator(
onRefresh: _refreshBrews,
child: ListView.builder(
controller: _controller,
itemCount: brews.length,
itemBuilder: (context, index) {
return BrewTile(brew: brews[index]);
},
),
);
}
}
Future<List<Brew>> get brewss async {
QuerySnapshot snapshot = await brewsCollection
.orderBy('timestamp', descending: true)
.limit(2)
.getDocuments();
return _postListFromSnapshot(snapshot);
}
2 ответа
Не уверен, что это поможет, но вот что я сделал в своем приложении Flutter. Обратите особое внимание на функцию _onScroll внизу.
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../blocs/feed_bloc/feed_events.dart';
import '../../blocs/feed_bloc/bloc.dart';
import '../../blocs/feed_bloc/feed_state.dart';
import './post.dart';
import '../loader.dart';
class Feed extends StatefulWidget {
Feed({ Key key }): super(key: key);
@override
_FeedState createState() => _FeedState();
}
class _FeedState extends State<Feed> {
final _scrollController = ScrollController();
final _scrollThreshold = 300.0;
FeedBloc _feedBloc;
_FeedState();
@override
void initState() {
super.initState();
_scrollController.addListener(_onScroll);
_feedBloc = BlocProvider.of<FeedBloc>(context);
}
@override
Widget build(BuildContext context) {
return BlocBuilder<FeedBloc, FeedState>(
builder: (context, state) {
if (state is FeedUninitialized) {
_feedBloc.add(Init());
return Loader();
}
if (state is FeedLoading) {
return Loader();
}
if (state is FeedLoaded) {
return new RefreshIndicator(
child: ListView(
controller: _scrollController,
// Important: Remove any padding from the ListView.
padding: EdgeInsets.zero,
children: state.posts.map((post) {
return Post(
postModel: state.postMap[post]
);
}).toList(),
),
onRefresh: () {
_feedBloc.add(Refresh());
return new Future.delayed(new Duration(seconds: 1));
},
);
}
return Center(
child: SizedBox(
height: 33,
child: Text(
'Sorry, there was a problem loading the feed.',
style: TextStyle( color: Colors.white)
),
),
);
}
);
}
int lastScroll = 0;
void _onScroll() {
if (new DateTime.now().millisecondsSinceEpoch - lastScroll > 1000) {
lastScroll = new DateTime.now().millisecondsSinceEpoch;
final maxScroll = _scrollController.position.maxScrollExtent;
final currentScroll = _scrollController.position.pixels;
if (maxScroll - currentScroll <= _scrollThreshold) {
_feedBloc.add(Fetch());
}
}
}
}
Я думаю, что вам нужно startAfterDocument. Смотри ниже...
Future<Map<String, dynamic>> getPosts({PostModel parent, PostModel lastPost}) async {
// First, we create the initial query.
// We pass in the parent key if there is one.
Query query = Firestore.instance
.collection('posts');
if (parent != null) {
query = query.where('parentId', isEqualTo: parent.key);
} else {
query = query.where('parentId', isNull: true);
}
query = query.orderBy('timestamp', descending: true);
// If we want to start at a certain doc (user is scrolling throught he feed)
// then we specify to start after a certain doc
if (lastPost != null) {
query = query.startAfterDocument(lastPost.rawDoc);
}
// Execute the query
final results = await query
.limit(18)
.getDocuments();
// Create some Lists/Maps we're going to need
List<String> posts = new List<String>();
Map<String, PostModel> postMap = new Map<String, PostModel>();
Map<String, bool> likeMap = new Map<String, bool>();
// Convienience/Brevity
final List<DocumentSnapshot> documents = results.documents;
final int numDocs = documents.length;
if (numDocs > 0) {
final firstDoc = results.documents[0].data;
final lastDoc = results.documents[numDocs-1].data;
// Get all your likes for a certain date range that aligns with the
// documents we just retrieved
likeMap = await getLikes(firstDoc['postCreated'], lastDoc['postCreated']);
}
// Loop through, and create all the PostModels
for (int i = 0; i < numDocs; i++) {
DocumentSnapshot doc = documents[i];
PostModel post = snapshotToPostModel(doc, likeMap[doc.documentID]);
postMap[doc.documentID] = post;
posts.add(post.key);
}
final Map<String, dynamic> res = new Map<String, dynamic>();
res['posts'] = posts;
res['postMap'] = postMap;
return res;
}
Вы можете использовать контроллер прокрутки и прослушиватель, чтобы определить, прокрутил ли пользователь до нижней части экрана. Если они есть, загрузите следующие 10 элементов из службы базы данных.
Это будет выглядеть примерно так.
ScrollController _controller = ScrollController();
@override
void initState() {
super.initState();
// add listener
_controller.addListener(_scrollListener);
}
_scrollListener() {
setState(() {
if (_controller.position.atEdge) {
if (_controller.position.pixels == 0)
{
// user is at top of the list
}
else
{
// user is at the bottom of the list.
// load next 10 items and add them to the list of items in the list.
}
}
});
}