首页 > 解决方案 > 如何在列表视图的滚动中添加更多项目?

问题描述

此处的代码当前加载了存储在 Firestore 集合中的所有 brews。我如何最初仅加载 10 个 brews,然后当用户向下滚动并到达 10 个 brews 列表的末尾时。它应该加载最后一次冲泡后还有 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);
  }

标签: firebasefluttergoogle-cloud-firestoreflutter-layout

解决方案


不确定以下是否会有所帮助,但这是我在颤振应用程序中所做的。特别注意底部的 _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;
  }

推荐阅读