flutter下拉刷新上拉加载的简单实现方式三

devtools/2024/11/17 0:26:53/

        使用 `CustomScrollView` 结合 `SliverList` 实现了一个支持下拉刷新上拉加载更多功能的滚动列表,对下面代码进行解析学习。

import 'dart:math';import 'package:flutter/material.dart';import 'custom_pull/gsy_refresh_sliver.dart';
import 'package:flutter/cupertino.dart' as IOS;class NewMyRefreshDemoPage extends StatefulWidget {const NewMyRefreshDemoPage({super.key});@overrideState<StatefulWidget> createState() => _NewMyRefreshDemoState();
}class _NewMyRefreshDemoState extends State<NewMyRefreshDemoPage> {final GlobalKey<CupertinoSliverRefreshControlState> sliverRefreshKey =GlobalKey<CupertinoSliverRefreshControlState>();final int pageSize = 30;bool disposed = false;List<String> dataList = [];final ScrollController _scrollController = ScrollController();Future<void> onRefresh() async {await Future.delayed(const Duration(seconds: 2));dataList.clear();for (int i = 0; i < pageSize; i++) {dataList.add("refresh");}if (disposed) {return;}setState(() {});}Future<void> loadMore() async {await Future.delayed(const Duration(seconds: 2));for (int i = 0; i < pageSize; i++) {dataList.add("loadmore");}if (disposed) {return;}setState(() {});}@overridevoid didChangeDependencies() {Future.delayed(const Duration(milliseconds: 500), () {_scrollController.animateTo(-141,duration: const Duration(milliseconds: 600), curve: Curves.linear);return true;});}@overridevoid dispose() {disposed = true;super.dispose();}@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text("NewMyRefreshDemoPage"),),body: NotificationListener(onNotification: (ScrollNotification notification) {//通知 CupertinoSliverRefreshControl 当前的拖拽状态sliverRefreshKey.currentState?.notifyScrollNotification(notification);if (notification is ScrollEndNotification) {if (_scrollController.position.pixels > 0 &&_scrollController.position.pixels ==_scrollController.position.maxScrollExtent) {loadMore();}}return false;},child: CustomScrollView(controller: _scrollController,physics: const BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()),slivers: <Widget>[CupertinoSliverRefreshControl(key: sliverRefreshKey,refreshIndicatorExtent: 100,refreshTriggerPullDistance: 140,onRefresh: onRefresh,builder: buildSimpleRefreshIndicator,),//列表SliverSafeArea(sliver: SliverList(delegate: SliverChildBuilderDelegate((BuildContext context, int index) {if (index == dataList.length) {return Container(margin: const EdgeInsets.all(10),child: const Align(child: CircularProgressIndicator(),),);}return Card(child: Container(height: 60,alignment: Alignment.centerLeft,child: Text("Item ${dataList[index]} $index"),),);},childCount: (dataList.length >= pageSize)? dataList.length + 1: dataList.length,),))],),),);}
}Widget buildSimpleRefreshIndicator(BuildContext context,RefreshIndicatorMode? refreshState,double pulledExtent,double refreshTriggerPullDistance,double refreshIndicatorExtent) {const Curve opacityCurve = Interval(0.4, 0.8, curve: Curves.easeInOut);return Align(alignment: Alignment.bottomCenter,child: Padding(padding: const EdgeInsets.only(bottom: 16.0),child: refreshState != RefreshIndicatorMode.refresh? Opacity(opacity: opacityCurve.transform(min(pulledExtent / refreshTriggerPullDistance, 1.0)),child: const Icon(IOS.CupertinoIcons.down_arrow,color: IOS.CupertinoColors.inactiveGray,size: 36.0,),): Opacity(opacity: opacityCurve.transform(min(pulledExtent / refreshIndicatorExtent, 1.0)),child: const IOS.CupertinoActivityIndicator(radius: 14.0),),),);
}

相关代码解析

NewMyRefreshDemoPage

这是一个 `StatefulWidget`,表示可以维护状态的组件。核心功能是提供一个支持刷新和加载更多的列表页面。

_NewMyRefreshDemoState

`State` 类的子类,负责管理 `NewMyRefreshDemoPage` 的状态。包含了 `dataList` 用于存储列表数据,以及控制滚动和刷新状态的逻辑。

相关状态管理

  • `sliverRefreshKey`:一个 `GlobalKey`,用于访问 `CupertinoSliverRefreshControl` 的状态。
  • `pageSize`:每次刷新或加载的项目数。
  • `disposed`:用于标识状态是否已被销毁,避免在组件卸载后进行状态更新。
  • `dataList`:存储列表项的数据。

相关方法

  • `onRefresh`:模拟网络请求,清空并重新填充列表数据。
  • `loadMore`:模拟网络请求,向列表追加更多数据。
  • `didChangeDependencies`:在组件依赖变化时调用,初始化时会在短暂延时后滚动到一个指定位置以触发下拉刷新
  • `dispose`:在组件卸载时调用,标记状态为已销毁。

UI 构建相关

`build` 方法

Scaffold:页面的基础结构,包含一个 `AppBar` 和 `body`。

NotificationListener:监听滚动事件,用于通知刷新控件当前的拖拽状态,以及检测是否到达滚动底部以加载更多。

CustomScrollView:允许在同一滚动视图中使用多个 sliver 组件。

  • SliverSafeArea & SliverList:用于在安全区域内展示列表项。

`buildSimpleRefreshIndicator` 方法

  • `refreshState`:当前刷新状态。
  • `pulledExtent`:拖动距离。
  • `refreshTriggerPullDistance`:触发刷新的拖动距离。
  • `refreshIndicatorExtent`:指示器的最大显示高度。

GlobalKey

final GlobalKey<CupertinoSliverRefreshControlState> sliverRefreshKey =GlobalKey<CupertinoSliverRefreshControlState>();

用于标识 `CupertinoSliverRefreshControl` 的全局键,允许在其他地方访问其状态。在 Flutter 中,`GlobalKey` 是一个强大的工具,用于唯一地标识和访问某个特定的组件实例。通过使用 `GlobalKey`,你可以在树的其他地方访问这个组件的状态或执行某些操作。

GlobalKey 是一个特殊的键,可以在 widget 树中唯一标识一个 widget。它允许访问与之关联的 widget 状态(`State` 对象),这在需要跨越 widget 树访问状态时非常有用。

CupertinoSliverRefreshControlState

这是 `CupertinoSliverRefreshControl` 的状态类。使用 `GlobalKey` 可以直接访问这个状态,进行一些状态更新或调用状态中的方法。

使用场景:

  • 访问刷新控件的状态:通过 `sliverRefreshKey.currentState`,你可以访问 `CupertinoSliverRefreshControl` 的状态对象。
  • 通知滚动状态:在 `NotificationListener` 中,使用 `sliverRefreshKey.currentState?.notifyScrollNotification(notification)` 来通知刷新控件当前的滚动状态。

CupertinoSliverRefreshControl

`CupertinoSliverRefreshControl` 是 Flutter 中一个用于实现 iOS 风格下拉刷新效果的组件。它通常用于 `CustomScrollView` 中,以提供流畅的下拉刷新体验,类似于 iOS 应用的原生行为。

主要特性

  • iOS 风格:以 iOS 的外观和行为为设计基础,提供原生般的用户体验。
  • 与 Sliver 兼容:设计用于与 `CustomScrollView` 和 sliver 系统一起使用,适合实现复杂的滚动布局。
  • 自动处理刷新逻辑:通过提供 `onRefresh` 回调,轻松实现数据刷新逻辑。

主要属性

refreshTriggerPullDistance

定义触发刷新操作所需的下拉距离(默认值为 100.0)。用户必须拉动至少此距离才能触发刷新。

refreshIndicatorExtent

刷新指示器的最大高度(默认值为 60.0)。指示器在用户继续下拉时可以扩展到的最大高度。

builder

自定义刷新指示器的外观。默认情况下,使用内置的 iOS 风格指示器,你可以提供一个自定义构建函数来改变其外观。

onRefresh

异步回调函数,当用户触发刷新操作时调用。通常用于执行异步操作(如网络请求)来更新数据。

注意

  • `CustomScrollView`:用于包裹 `CupertinoSliverRefreshControl` 和 `SliverList`,使得刷新控件可以与列表一起滚动。
  • `CupertinoSliverRefreshControl`:提供下拉刷新功能,`onRefresh` 回调用于定义刷新时的逻辑(如更新数据)。
  • 刷新逻辑:在 `_handleRefresh` 中模拟了一个网络请求,通过 `Future.delayed` 来延迟刷新操作。

buildSimpleRefreshIndicator

`buildSimpleRefreshIndicator` 是一个用于自定义刷新指示器外观的函数。它通常在实现下拉刷新功能时与 `CupertinoSliverRefreshControl` 一起使用。这个函数根据用户下拉的距离和当前的刷新状态来动态调整指示器的外观。

BuildContext context

Flutter 的上下文对象,用于获取主题、媒体查询等信息。在这个函数中没有被直接使用。

RefreshIndicatorMode? refreshState

刷新指示器的当前状态。可能的值包括:

  • `inactive`:未触发刷新。
  • `drag`:用户正在拖动,但未达到刷新阈值。
  • `armed`:用户拖动超过阈值,松手后将触发刷新。
  • `refresh`:正在刷新中。
  • `done`:刷新完成。

该函数使用此状态来决定显示箭头图标还是加载动画。

double pulledExtent

用户下拉的距离(以像素为单位)。

double refreshTriggerPullDistance

触发刷新的下拉距离阈值。

double refreshIndicatorExtent

刷新指示器的最大显示高度。

Curve

const Curve opacityCurve = Interval(0.4, 0.8, curve: Curves.easeInOut)

使用 `Interval` 定义一个曲线,用于控制不透明度变化的动画效果。`Interval(0.4, 0.8, curve: Curves.easeInOut)` 表示在 40% 到 80% 的时间内应用 `easeInOut` 曲线。

刷新指示器的作用

使用条件表达式根据 `refreshState` 的值显示不同的组件:

  • 如果状态不是 `RefreshIndicatorMode.refresh`,则显示一个箭头图标,且图标的透明度根据 `pulledExtent` 与 `refreshTriggerPullDistance` 的比例动态调整。
  • 如果状态是 `RefreshIndicatorMode.refresh`,则显示一个 `CupertinoActivityIndicator` 加载动画,且透明度根据 `pulledExtent` 与 `refreshIndicatorExtent` 的比例调整。

如何工作

  • 当用户开始下拉时,指示器的箭头图标会根据下拉距离逐渐显现。
  • 当用户的下拉距离超过 `refreshTriggerPullDistance` 并松手后,指示器状态变为 `refresh`,显示加载动画。
  • 加载动画的透明度也会随着用户下拉距离的变化而变化,提供更好的视觉反馈。


http://www.ppmy.cn/devtools/134572.html

相关文章

hhdb数据库介绍(9-14)

SQL语法支持 DML语句 在关系集群数据库中&#xff0c;DML语句的逻辑将变的更为复杂。计算节点将DML语句分为两大类&#xff1a;单库DML语句与跨库DML语句。 单库DML语句&#xff0c;指SQL语句只需在一个节点上运行&#xff0c;即可计算出正确结果。假设分片表customer分片字…

杨中科 .Net Core 笔记 DI 依赖注入2

ServiceCollection services new ServiceCollection();//定义一个承放服务的集合 services.AddScoped<iGetRole, GetRole>();using (ServiceProvider serviceProvider services.BuildServiceProvider()) {var list serviceProvider.GetServices(typeof(iGetRole));//获…

力扣题目解析--合并两个链表

题目 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1&#xff1a; 输入&#xff1a;l1 [1,2,4], l2 [1,3,4] 输出&#xff1a;[1,1,2,3,4,4]示例 2&#xff1a; 输入&#xff1a;l1 [], l2 [] 输出&#xff…

Java基础:内部类

欢迎来到“雪碧聊技术”CSDN博客&#xff01; 在这里&#xff0c;您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者&#xff0c;还是具有一定经验的开发者&#xff0c;相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导&#xff0c;我将…

密码学在网络安全中的应用

密码学作为网络安全领域的核心技术之一&#xff0c;发挥着举足轻重的作用。以下是对密码学在网络安全中应用的详细阐述&#xff1a; 一、数据加密密码学通过加密算法将明文转换为密文&#xff0c;以防止未经授权的个人或机构获取敏感信息。这主要包括&#xff1a;对称加密&…

正点原子IMX6ULL--嵌入式Linux开发板学习中常用命令和笔记记录

学习路线图 传驱动文件 sudo cp chrdevbase.ko chrdevbaseApp /home/txj/linux/nfs/rootfs/lib/modules/4.1.15/ -f bootcmd setenv bootcmd tftp 80800000 zImage;tftp 83000000 imx6ull-alientek-emmc.dtb;bootz 80800000 - 83000000 setenv bootcmd tftp 80800000 zImag…

PHP大模型深度学习库TransformersPHP 安装体验

TransformersPHP是一个工具包&#xff0c;PHP开发人员可以轻松地将机器学习魔法添加到他们的项目中。 管方地址&#xff1a;TransformersPHP github地址&#xff1a;GitHub - CodeWithKyrian/transformers-php: Transformers PHP is a toolkit for PHP developers to add machi…

STM32芯片EXIT外部中断的配置与原理以及模板代码(标准库)

配置EXIT外部中断其实就是把GPIO刀NVIC的各个外设配置好 第一步&#xff1a;配置RCC&#xff0c;把我们涉及到的外设的时钟都打开 &#xff08;此处EXTI是默认打开的&#xff0c;而NVIC是内核外设无需配置&#xff09; 第二步&#xff1a;配置GPIO,选择端口为输入模式 第三…