簡體   English   中英

在 Flutter 中實現無限滾動 GridView 的最佳實踐?

[英]Best practices for implementing an infinite scroll GridView in Flutter?

我想創建一個 GridView 來顯示將從服務器獲取的項目的偏移量。 我在 GridView 中只加載了 10 個項目,當用戶滾動到 10 后,我將加載更多的 10 個項目。 在 Flutter 中實現無限滾動 GridView 的最佳實踐是什么?

您需要在ListViewGridView底部添加滾動檢測的ScrollController 由於您需要GridView ,我創建了ScrollController列表器並添加到GridView's contoller中以檢測滾動。 我已經創建了它的演示,請檢查一次。 第一次它加載10 個項目,當列表到達底部時,它會在其中添加更多10 個項目。

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

class HomeScreen extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return HomeState();
  }
}

class HomeState extends State<HomeScreen> {
  List dataList = new List<int>();
  bool isLoading = false;
  int pageCount = 1;
  ScrollController _scrollController;

  @override
  void initState() {
    super.initState();

    ////LOADING FIRST  DATA
    addItemIntoLisT(1);

    _scrollController = new ScrollController(initialScrollOffset: 5.0)
      ..addListener(_scrollListener);
  }

  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'Gridview',
        debugShowCheckedModeBanner: false,
        theme: ThemeData(
          primaryColor: Colors.red,
          accentColor: Color(0xFFFEF9EB),
        ),
        home: Scaffold(
            appBar: new AppBar(),
            body: GridView.count(
              controller: _scrollController,
              scrollDirection: Axis.vertical,
              crossAxisCount: 2,
              mainAxisSpacing: 10.0,

              physics: const AlwaysScrollableScrollPhysics(),
              children: dataList.map((value) {
                return Container(
                      alignment: Alignment.center,
                      height: MediaQuery.of(context).size.height * 0.2,
                      margin: EdgeInsets.only(left: 10.0, right: 10.0),
                      decoration: BoxDecoration(
                        border: Border.all(color: Colors.black),
                      ),
                      child: Text("Item ${value}"),
                    );


              }).toList(),
            )));
  }

  //// ADDING THE SCROLL LISTINER
  _scrollListener() {
    if (_scrollController.offset >=
            _scrollController.position.maxScrollExtent &&
        !_scrollController.position.outOfRange) {
      setState(() {
        print("comes to bottom $isLoading");
        isLoading = true;

        if (isLoading) {
          print("RUNNING LOAD MORE");

          pageCount = pageCount + 1;

          addItemIntoLisT(pageCount);
        }
      });
    }
  }

  ////ADDING DATA INTO ARRAYLIST
  void addItemIntoLisT(var pageCount) {
    for (int i = (pageCount * 10) - 10; i < pageCount * 10; i++) {
      dataList.add(i);
      isLoading = false;
    }
  }

  @override
  void dispose() {
    _scrollController.dispose();
    super.dispose();
  }
}

而上述程序的output如下
在此處輸入圖像描述

class AllOrdersPage extends StatefulWidget {
  @override
  _AllOrdersPageState createState() => _AllOrdersPageState();
}

class _AllOrdersPageState extends State<AllOrdersPage> {
  List<OrderDatum> ordersList;
  ScrollController _scrollController = ScrollController();
  int skip = 0;
  bool shouldLoadMore = true;
  Future<OrdersResponse> future;

  @override
  void initState() {
    super.initState();

    ordersList = [];
    future = getAllOrders(skip); //load data for first time
    _scrollController.addListener(() {
      if (_scrollController.position.pixels ==
          _scrollController.position.maxScrollExtent) {  //Check whether user scrolled to last position
        if (shouldLoadMore) {
          setState(() {
            skip += ordersList.length;
            future = getAllOrders(skip); //load more data
          });
        }
      }
    });
  }

  @override
  void dispose() {
    _scrollController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<OrdersResponse>(
        future: future,
        builder: (context, snapshot) {
          if (snapshot.hasError)
            return ErrorText('${snapshot.error.toString()}');
          if (snapshot.hasData) {
            skip = snapshot.data.skip;
            if (snapshot.data.limit + snapshot.data.skip >=
                snapshot.data.total) {
              shouldLoadMore = false;
            }
            snapshot.data.data.forEach((element) {
              if (!ordersList.contains(element)) ordersList.add(element);
            });
            if (skip == 0 && ordersList.isEmpty) {
              return ErrorText('No orders.');
            }
            return Scrollbar(
              controller: _scrollController,
              isAlwaysShown: true,
              child: GridView.builder(
                gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                    crossAxisCount: 2,
                    crossAxisSpacing: 8,
                    childAspectRatio: 2.5,
                    mainAxisSpacing: 8),
                controller: _scrollController,
                padding: const EdgeInsets.all(8),
                itemBuilder: (BuildContext context, int index) {
                  if (index == ordersList.length) {
                    return shouldLoadMore
                        ? Center(child: CircularProgressIndicator())
                        : Container();
                  }
                  return Container(
                      width: MediaQuery.of(context).size.width,
                      child: OrderCard(ordersList[index]));
                },
                itemCount: ordersList.length + 1,
              ),
            );
          }
          return Loader();
        });
  }
}

謝謝

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM