前提

由于第三天的接口只有4条无法显示上拉加载和下拉刷新的功能,于是重新用另外一个接口来请求。

先说一下最新的接口设计

传参有三个字段 分别为page当前页,pageSize每页数量,category水果类别。query方式

返回参数格式为

{
    "success": true,
    "data": {
        "list": [
            {
                "chinese": "脐橙",
                "name": "脐橙",
                "english": "NavelOrange",
                "nutrition": [
                    [
                        "维生素C",
                        "53mg/100g"
                    ],
                    [
                        "膳食纤维",
                        "2.4g/100g"
                    ],
                    [
                        "钾",
                        "159mg/100g"
                    ],
                    [
                        "叶酸",
                        "40μg/100g"
                    ],
                    [
                        "热量",
                        "47kcal/100g"
                    ]
                ],
                "category": "时令水果",
                "colorImageUrl": "xxx",
                "transparentImageUrl": "",
                "benefits": "富含维生素C,增强免疫力,促进胶原蛋白合成,抗氧化,预防感冒",
                "detailImages": [],
                "detailDescription": "脐橙口感酸甜多汁,富含维生素C,可增强免疫力和抗氧化,适合日常食用。",
                "mainColor": "#FF9800",
                "mainBg": "#FBE185",
                "features": [
                    {
                        "short": "增强免疫",
                        "long": "富含维生素C,有助于增强身体免疫力。"
                    },
                    {
                        "short": "抗氧化",
                        "long": "丰富的抗氧化物质,有效对抗自由基,延缓衰老。"
                    }
                ]
            }
        ],
        "pagination": {
            "page": 1,
            "pageSize": 1,
            "total": 29,
            "totalPages": 29
        }
    },
    "message": null,
    "statusCode": 200
}
1.鸿蒙手机上上拉加载效果图片

使用 Flutter 的 RefreshIndicator 组件

Flutter 提供了内置的 RefreshIndicator 组件来实现下拉刷新功能。这个组件会包裹一个可滚动的子组件(如 ListView、GridView 等),当用户在列表顶部向下拉动时,会显示一个圆形的加载指示器,同时触发 onRefresh 回调函数。

工作流程:

  • 用户手指在屏幕上向下滑动

  • 当滑动距离超过阈值时,显示刷新指示器

  • 用户松开手指,触发 onRefresh 回调

  • 执行异步数据请求

  • 请求完成后,刷新指示器自动收起

  • 列表显示最新数据

RefreshIndicator(
  onRefresh: () => _fetchData(isRefresh: true),  // 下拉触发的回调
  child: ListView.builder(
    itemCount: _fruitList.length,
    itemBuilder: (context, index) {
      return FruitCard(fruit: _fruitList[index]);
    },
  ),
)

下拉刷新实现

Future<void> _fetchData({bool isRefresh = false}) async {
  if (isRefresh) {
    _currentPage = 1;      // 重置页码
    _hasMore = true;       // 重置加载更多状态
  }
  
  final result = await FruitApi.getFruitList(
    page: _currentPage,
    pageSize: _pageSize,
  );

  setState(() {
    if (result != null) {
      if (isRefresh) {
        _fruitList = result.list;        // 刷新:替换整个列表
      } else {
        _fruitList.addAll(result.list);  // 加载更多:追加数据
      }
    }
  });
}

2.上拉加载

Flutter 没有内置的上拉加载组件,需要我们通过 ScrollController 来监听列表的滚动位置。当检测到用户滚动到列表底部时,自动触发加载更多数据的操作。

步骤

  • 创建 ScrollController 并绑定到 ListView

  • 添加滚动监听器,监听滚动位置变化

  • 当滚动位置等于最大滚动范围时,说明已到达底部

  • 检查是否正在加载中、是否还有更多数据

  • 如果满足条件,增加页码并请求下一页数据

  • 将新数据追加到现有列表中

  • 在列表底部显示加载指示器

定义变量

int _currentPage = 1;                // 当前页码
final int _pageSize = 10;            // 每页数量
bool _hasMore = true;                // 是否还有更多数据
bool _loading = false;               // 是否正在加载
final ScrollController _scrollController = ScrollController();  // 滚动控制器


初始化时添加滚动监听

@override
void initState() {
  super.initState();
  _scrollController.addListener(_onScroll);
}

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


监听滚动到底部

void _onScroll() {
  if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent) {
    if (!_loading && _hasMore) {
      _loadMore();
    }
  }
}
 

加载更多数据

Future<void> _loadMore() async {
  _currentPage++;
  await _fetchData();
}

Future<void> _fetchData({bool isRefresh = false}) async {
  setState(() { _loading = true; });

  final result = await FruitApi.getFruitList(page: _currentPage, pageSize: _pageSize);

  setState(() {
    if (result != null) {
      _fruitList.addAll(result.list);              // 追加数据
      _hasMore = result.list.length == _pageSize;  // 判断是否还有更多
    }
    _loading = false;
  });
}
 

列表绑定控制器并显示加载指示器

ListView.builder(
  controller: _scrollController,
  itemCount: _fruitList.length + (_hasMore ? 1 : 0),
  itemBuilder: (context, index) {
    if (index == _fruitList.length) {
      return const Center(child: CircularProgressIndicator());
    }
    return FruitCard(fruit: _fruitList[index]);
  },
)
 

3.最后

欢迎加入开源鸿蒙跨平台社区:
https://openharmonycrossplatform.csdn.net

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐