在 Flutter 中使用网格列表进行分页

时间:2020-12-28 07:04:57

标签: flutter flutter-layout flutter-dependencies

我想在我的网格列表中有一个分页。 我有一个来自 API 端点的项目列表。目前我正在显示 21 条记录。但原始列表很长。所以,我想要一个分页类型,用户可以在其中看到来自 API 的列表中的所有项目。

这是我的代码。

class _CategoryPageState extends State<CategoryPage> {
  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: getCategoryList(widget.slug, widget.isSubList, widget.token),
      builder: (context, AsyncSnapshot snapshot) {
        switch (snapshot.connectionState) {
          case ConnectionState.none:
          case ConnectionState.waiting:
            return CircularProgress();
          default:
            if (snapshot.hasError)
              return Text('Error: ${snapshot.error}');
            else
              return createListView(context, snapshot, widget.isSubList, widget.token);
        }
      },
    );
  }
}

Widget createListView(BuildContext context, AsyncSnapshot snapshot, bool isSubList, String token) {
  List<CategoryModel> values = snapshot.data;

  return GridView.count(
    crossAxisCount: 3,
//    physics: NeverScrollableScrollPhysics(),
//      values[index].imageUrl
    padding: EdgeInsets.all(1.0),
    /*childAspectRatio: 8.0 / 9.0,*/
    children: List<Widget>.generate(values.length, (index) {
      if(values[index].imageUrl == null){
        values[index].imageUrl = 'dummy.jpg';
      }
      return GridTile(
          child: GridTilesCategory(
        name: values[index].name,
        imageUrl: values[index].imageUrl,
        slug: values[index].slug,
        fromSubProducts: isSubList,
        token: token,
        imageType: 'category-images',
      ));
    }),
  );
}

Future<List<CategoryModel>> getCategoryList(String slug, bool isSubList, String token) async {
  if (isSubList) {
    categories = null;
  }
  if (categories == null) {
    final response = await http.post(
        Urls.ROOT_URL + slug,
        body: json.encode({
          "filter" : {"categoryname":null,"status" : 1},
          "sortOrder" : "ASC",
          "sortField" : "",
          "pageNumber" : 0,
          "pageSize" : 21
        }),
        headers: {
          'content-type': 'application/json',
          'Authorization': 'Bearer $token',
        }
    );
    print(response.toString());
    final responseData = json.decode(response.body);

    int statusCode = response.statusCode;
    final body = json.decode(response.body);
    print(body);
    if (statusCode == 200) {
      categories = (body['items'] as List).map((i) => CategoryModel.fromJson(i)).toList();

      return categories;
    } else {
      return categories = List();
    }
  } else {
    return categories;
  }
}

我的要求就像一个继续滚动类型的分页。

2 个答案:

答案 0 :(得分:0)

尝试像这样使用 ListView.builder:

ListView.builder(
    key: PageStorageKey<String>('savePositionKey'),
    itemCount: widget.activities.length + 1,
    itemBuilder: (builderContext, index) {
      if (index == (widget.activities.length - 1)) {
        getNextActivitiesPage();
      }if (index == (widget.activities.length)) {
        return !widget.activitiesFetchState.isCompleted() &&
                !widget.isNewData //when you start again from page 0
            ? Center(child: CircularProgressIndicator())
            : SizedBox.shrink();
      }
      you code- on tap and more.....
);    

并在您的管理器中创建获取下一页并将其插入到列表末尾的 getNext 函数

答案 1 :(得分:0)

Sice 没有人认为这个问题值得回答。 我找到了一种实现分页的方法。这是我的最终代码。

class _ProductListWidgetState extends State<ProductListWidget> {
  int pageNumber = 0;
  int totalCount = 0;
  int totalPages = 0;

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: getProductList(widget.slug, false, widget.token, widget.name, widget.identifier, pageNumber),
      builder: (context, AsyncSnapshot snapshot) {
        switch (snapshot.connectionState) {
          case ConnectionState.none:
          case ConnectionState.waiting:
            return CircularProgress();
          default:
            if (snapshot.hasError)
              return Text('Error: ${snapshot.error}');
            else
              return createListView(context, snapshot, widget.token);
        }
      },
    );
  }
  ProductsModels products;

  Future<ProductsModels> getProductList(String slug, bool isSubList, String token, String name, String identifier, int page) async {
    if (isSubList) {
      products = null;
    }

    final response = await http.post(
        Urls.ROOT_URL + slug,
        body: json.encode({
          "filter" : {"categoryname":identifier,"status" : 1},
          "sortOrder" : "ASC",
          "sortField" : "",
          "pageNumber" : page,
          "pageSize" : 20
        }),
        headers: {
          'content-type': 'application/json',
          'Authorization': 'Bearer $token',
        }
    );

    int statusCode = response.statusCode;
    final body = json.decode(response.body);

    if (statusCode == 200) {
      products = ProductsModels.fromJson(body);
      totalCount = products.count;
      totalPages = totalCount~/20;

      print('total count: $totalCount');
      print('total pages: $totalPages');
      return products;
    } else {
      return products = ProductsModels();
    }
  }

  Widget createListView(BuildContext context, AsyncSnapshot snapshot, String token) {
    ProductsModels values = snapshot.data;
    List<Results> results = values.results;
    print(results.toString());
    return SingleChildScrollView(
      physics: AlwaysScrollableScrollPhysics(),
      child: Column(
        children: [
          GridView.count(
            shrinkWrap: true,
            primary: true,
            physics: NeverScrollableScrollPhysics(),
            crossAxisCount: 2,
            padding: EdgeInsets.all(1.0),
            children: List<Widget>.generate(results.length, (index) {
              if(results[index].imageUrls == null){
                results[index].imageUrls = 'dummy.jpg';
              }
              return GridTile(
                  child: GridTilesProducts(
                    name: results[index].name,
                    imageUrl: results[index].imageUrls,
                    slug: results[index].slug,
                    price: results[index].price.toString(),
                    token: token,
                  ));
            }),
          ),
          Divider(height: 1.0, color: Color(0xFFe2e2e2),thickness: 1.0,),
          Padding(
            padding:  EdgeInsets.all(20),
            child: Row(
              mainAxisSize: MainAxisSize.max,
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: <Widget>[
                OutlineButton(
                    borderSide: BorderSide(color: Color(0xFFe1e5e8)),
                    onPressed: (){
                      if((pageNumber > totalPages) || (pageNumber > 0)){
                        setState(() {
                          pageNumber--;
                        });
                      }
                      else{
                        Toast.show("Page 1 Reached", context, duration: Toast.LENGTH_SHORT, gravity:  Toast.BOTTOM);
                      }
                    },
                    color: Color(0xFFe1e5e8),
                    textColor: Color(0xFFe1e5e8),
                    child: Container(
                      height: 30.0,
                      child: Center(
                        child: Text('Previous Page',
                            style: TextStyle(fontSize: 15.0, fontFamily: 'Brand-Bold', color: Color(0xFF383635))),
                      ),
                    )
                ),
                RaisedButton(
                  onPressed: (){
                    if(pageNumber < totalPages){
                      setState(() {
                        pageNumber++;
                      });
                    }
                    else{
                      Toast.show("No More Items Found", context, duration: Toast.LENGTH_SHORT, gravity:  Toast.BOTTOM);
                    }
                  },
                  color: Color(0xFFd16608),
                  textColor: Colors.white,
                  child: Container(
                    height: 30,
                    child: Center(
                      child: Text(
                        'Next Page',
                        style: TextStyle(fontSize: 15, fontFamily: 'Poppins-Bold'),
                      ),
                    ),
                  ),
                )
              ],
            ),
          ),
        ],
      ),
    );
  }
}