到达结果底部时如何将更多项目加载到列表中

How to load more items to a list when reach the bottom of results flutter

我有下面的代码,它提供了一个包含来自 firebase 的 10 个结果的列表。在这种情况下,它只显示 10 个项目,现在我想,当用户获得结果的底部时,它会加载更多 10 个项目并将其添加到列表中。我已经有了 scrollController 并且它可以工作。当我得到结果的底部时,我收到日志“LOAD HERE”。

我的疑问是如何在列表中添加新的 10 个项目?

scrollListener() async {
    if (scrollController.position.maxScrollExtent == scrollController.offset) {
      print('LOAD HERE');
    
    }
  }

  @override
  void initState() {
    scrollController.addListener(scrollListener);
    super.initState();
  }

  @override
  void dispose() {
    scrollController.removeListener(scrollListener);
    super.dispose();
  }

  loadList(submenu ,callback, context, deviceSize){
    return FutureBuilder(
      future: ctrlLab.loadList(submenu, 10),
      builder: (ctx, snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return Center(child: CircularProgressIndicator());
        } else if (snapshot.error != null) {
          print(snapshot.error);
          return Center(child: Text('ERROR!'));
        }else {
          return GridView.builder(
            padding: EdgeInsets.all(10.0),
            controller: scrollController,
            itemCount: snapshot.data.length,
            itemBuilder: (ctx, i) {
              Item item = snapshot.data[i];
              if (i < snapshot.data.length) {
                return Dismissible(
                  key: UniqueKey(),
                  direction: DismissDirection.endToStart,
                  background: Container(
                    padding: EdgeInsets.all(10.0),
                    color: Colors.grey[800],
                    child: Align(
                      alignment: AlignmentDirectional.centerEnd,
                      child: Icon(
                        Icons.delete,
                        color: Colors.white,
                        size: 40,
                      ),
                    ),
                  ),
                  onDismissed: (DismissDirection direction) {
                    ctrl.onDismissed(callback, item);
                  },
                  child: GestureDetector(
                    child: Card(
                      elevation: 5.0,
                      child: Padding(
                        padding: EdgeInsets.all(10.0),
                        child: GridTile(
                          child: Hero(
                            tag: "${item}",
                            child: item.imageUrl == null
                                ? setIconLab(item)
                                : CachedNetworkImage(
                              fit: BoxFit.cover,
                              imageUrl: setIconLab(item),
                              placeholder: (ctx, url) =>
                                  Center(child: CircularProgressIndicator()),
                              errorWidget: (context, url, error) =>
                                  Image.asset('assets/images/noPhoto.jpg',
                                      fit: BoxFit.cover),
                            ),
                          ),
                          footer: Container(
                            padding: EdgeInsets.all(8.0),
                            color: Colors.white70,
                            child: Column(
                              mainAxisAlignment: MainAxisAlignment.spaceBetween,
                              children: [
                                Text(
                                  item.name
                                  ),
                                ),
                              ],
                            ),
                          ),
                        ),
                      ),
                    ),
                  ),
                );

              }
            },
            gridDelegate: SliverGridDelegateWithFixedCrossAxisCountAndLoading(
              itemCount: snapshot.data.length + 1,
              crossAxisCount: deviceSize.width < 600 ? 2 : 3,
              childAspectRatio: 0.7,
              crossAxisSpacing: 10.0,
              mainAxisSpacing: 10.0,
            ),
          );
        }
      },
    );
  }

您必须向 crtLap.loadList(subMenu, 20) 添加另外 10 个数据,并在 scrollListener 中调用 setState 以重建有关更改的小部件。

var data = crtLap.loadList(subMenu, 10);

scrollListener() async {
  if (scrollController.position.maxScrollExtent == scrollController.offset) {
    setState((){
       data = crtLap.loadList(subMenu, 20);
     });
  }
}

并直接将此数据字段用于 FutureBuilder,

loadList(submenu ,callback, context, deviceSize){
 return FutureBuilder(
   future: data,
    builder: (ctx, snapshot) {
    .....
  ...
..
}

ListView 中的无限滚动

我通过使用本地字段而不是从 firebase 获取数据来实现这种情况。希望它能给你一些想法。

import 'package:flutter/material.dart';

class ListViewDemo extends StatefulWidget {
  ListViewDemo({Key key}) : super(key: key);

  @override
  _ListViewDemoState createState() => _ListViewDemoState();
}

class _ListViewDemoState extends State<ListViewDemo> {
  ScrollController controller;
  int count = 15;

  @override
  void initState() {
    super.initState();
    controller = ScrollController()..addListener(handleScrolling);
  }

  void handleScrolling() {
    if (controller.offset >= controller.position.maxScrollExtent) {
      setState(() {
        count += 10;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('List view'),
      ),
      body: ListView.builder(
        controller: controller,
        itemCount: count,
        itemBuilder: (BuildContext context, int index) {
          return ListTile(
            title: Text('Item $index'),
          );
        },
      ),
    );
  }

  @override
  void dispose() {
    controller.removeListener(handleScrolling);
    super.dispose();
  }
}