自学内容网 自学内容网

Flutter:列表分页,上拉加载下拉刷新,在GetBuilder模板使用方式

GetBuilder模板使用方式参考上一节
本篇主要代码记录如何使用上拉加载下拉刷新,
接口请求和商品组件的代码不包括在内

pubspec.yaml装包

  cupertino_icons: ^1.0.8
  # 分页 上拉加载,下拉刷新
  pull_to_refresh_flutter3: 2.0.2

商品列表:controller

import 'package:flutter_aidishi/api/index.dart';
import 'package:flutter_aidishi/models/home/product_model/product_model.dart';
import 'package:flutter_aidishi/models/index.dart';
import 'package:get/get.dart';
import 'package:pull_to_refresh_flutter3/pull_to_refresh_flutter3.dart';

class GoodsListController extends GetxController {
  GoodsListController();
  final isHot = Get.arguments['hot'];
  List<ProductModel> items = [];

  /*
  * 分页
  * refreshController:分页控制器
  * _page:分页
  * _limit:每页条数
  * _loadNewsSell:拉取数据(是否刷新)
  * onLoading:上拉加载新商品
  * onRefresh:下拉刷新
  * */
  final RefreshController refreshController = RefreshController(
    initialRefresh: true,
  );
  int _page = 1;
  int _limit = 20;
  Future<bool> _loadNewsSell(bool isRefresh) async {
    var result = await ProductApi.products(ProductsReq(
      page:isRefresh ? 1:_page,
        prePage:_limit
    ));
    if(isRefresh){
      _page = 1;
      items.clear();
    }
    if(result.isNotEmpty){
      _page++;
      items.addAll(result);
    }
    // 是否是空
    return result.isEmpty;
  }
  // 上拉载入新商品
  void onLoading() async{
    if(items.isNotEmpty){
      try{
        // 拉取数据是否为空 ? 设置暂无数据 : 加载完成
        var isEmpty = await _loadNewsSell(false);
        isEmpty ? refreshController.loadNoData() :  refreshController.loadComplete();
      }catch(e){
        refreshController.loadFailed(); // 加载失败
      }
    }else{
      refreshController.loadNoData(); // 设置无数据
    }
    update(["goods_list"]);
  }
  // 下拉刷新
  void onRefresh() async{
    try{
      await _loadNewsSell(true);
      refreshController.refreshCompleted();
    }catch(e){
      refreshController.refreshFailed();
    }
    update(["goods_list"]);
  }



  _initData() async{
    update(["goods_list"]);
  }

  void onTap() {}

  @override
  void onInit() {
    super.onInit();
  }

  @override
  void onReady() {
    super.onReady();
    _initData();
  }

  @override
  void onClose() {
    super.onClose();
    // 控制器释放
    refreshController.dispose();
  }
}

商品列表:view

import 'package:flutter/material.dart';
import 'package:flutter_aidishi/components/product_item.dart';
import 'package:flutter_aidishi/components/refresher.dart';
import 'package:get/get.dart';
import 'package:pull_to_refresh_flutter3/pull_to_refresh_flutter3.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'index.dart';

class GoodsListPage extends GetView<GoodsListController> {
  const GoodsListPage({super.key});
  
  // AppBar
  AppBar _buildAppBar(){
    return AppBar(
        title: const Text("goods_list")
    );
  }
  
  // 主视图
  Widget _buildView() {
    return GridView.builder(
      itemCount: controller.items.length,
      itemBuilder: (context,index){
        var product = controller.items[index];
        // 自行封装商品item组件
        return ProductItemWidget(
            product,
            imgHeight: 117.w, // 图片高度
        );
      },
      gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
        crossAxisCount: 3, // 每行3个
        mainAxisSpacing: 10.w, // 主轴间距
        crossAxisSpacing: 10.w, // 交叉轴间距
        childAspectRatio: 0.7, // 宽高比
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return GetBuilder<GoodsListController>(
      init: GoodsListController(),
      id: "goods_list",
      builder: (_) {
        return Scaffold(
          appBar: _buildAppBar(),
          body: SmartRefresher(
            controller: controller.refreshController,
            enablePullUp: true, // 启用上拉加载
            onRefresh: controller.onRefresh, // 下拉刷新回调
            onLoading: controller.onLoading, // 上拉加载回调
            footer: const SmartRefresherFooterWidget(), // 底部加载更多组件
            child: _buildView(),
          ),
        );
      },
    );
  }
}

底部加载更多组件:SmartRefresherFooterWidget

import 'package:flutter/cupertino.dart';
import 'package:flutter_aidishi/extension/index.dart';
import 'package:pull_to_refresh_flutter3/pull_to_refresh_flutter3.dart';


/// 底部加载更多组件
class SmartRefresherFooterWidget extends StatelessWidget {
  /// 底部高度
  final double? height;

  /// 图标大小
  final double? iconSize;

  const SmartRefresherFooterWidget({
    Key? key,
    this.iconSize,
    this.height,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ClassicFooter(
      height: height ?? 60 + MediaQuery.of(context).padding.bottom + 30, // 底部高度
      loadingIcon: const CupertinoActivityIndicator().tight(
        width: iconSize ?? 25,
        height: iconSize ?? 25,
      ), // 加载中
      outerBuilder: (child) => child.center().height(height ?? 60), // 内容
    );
  }
}

main也需要启用上拉加载下拉刷新

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) :super(key: key);
  @override
  Widget build(BuildContext context) {
    return ScreenUtilInit(
        designSize: const Size(375, 812), // 设计稿中设备的尺寸(单位随意,建议dp,但在使用过程中必须保持一致)
        builder: (context,child){
          return RefreshConfiguration(
            headerBuilder: () => const ClassicHeader(), // 自定义刷新头部
            footerBuilder: () => const ClassicFooter(), // 自定义刷新尾部
            hideFooterWhenNotFull: true, // 当列表不满一页时,是否隐藏刷新尾部
            headerTriggerDistance: 80, // 触发刷新的距离
            maxOverScrollExtent: 100, // 最大的拖动距离
            footerTriggerDistance: 150, // 触发加载的距离
            child:GetMaterialApp(
            ...
            ...
            )
          );
        }
    );
  }
}

完成!


原文地址:https://blog.csdn.net/qq_40745143/article/details/144112921

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!