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

        使用 `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`:存储列表项的数据。
  • `_scrollController`:用于控制滚动行为的 `ScrollController`。

相关方法

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

UI 构建相关

`build` 方法

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

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

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

  • CupertinoSliverRefreshControl:提供下拉刷新功能。
  • 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.mzph.cn/bicheng/60709.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大模型研究报告 | 2024年中国金融大模型产业发展洞察报告|附34页PDF文件下载

随着生成算法、预训练模型、多模态数据分析等AI技术的聚集融合&#xff0c;AIGC技术的实践效用迎来了行业级大爆发。通用大模型技术的成熟推动了新一轮行业生产力变革&#xff0c;在投入提升与政策扶植的双重作用下&#xff0c;以大模型技术为底座、结合专业化金融能力的金融大…

MySQL联合索引(abc)命中测试

1.建表 mysql创建一张表&#xff0c;表名&#xff1a;‘test_models’ id列为 主键&#xff0c;int类型 &#xff0c;自增a,b,c,d,e 全部是int&#xff08;11&#xff09;为&#xff08;a,b,c&#xff09;添加一个联合索引 index_abc 执行语句&#xff1a;创建表 CREATE TA…

Gin 框架入门(GO)-1

1 介绍 Gin 是一个 Go (Golang) 编写的轻量级 http web 框架&#xff0c;运行速度非常快&#xff0c;Gin 最擅长的就是 Api 接口的高并发。 2 Gin 环境搭建 1.下载并安装 gin go get -u github.com/gin-gonic/gin 2.将 gin 引入到代码中&#xff1a; import "github.co…

VUE3+Three.js搭建教程

一、创建VUE项目工程 1、方法一 使用下面命令行快速创建vue项目&#xff0c;Please pick a preset这里我们选择使用VUE3 vue create projectName 创建时可能会遇到的报错 错误原因&#xff1a;当前使用的node版本未全局安装vue-cli脚手架&#xff0c;使用下面命令安装后再使…

【React】状态管理之Redux

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 状态管理之Redux引言1. Redux 的核心概念1.1 单一数据源&#xff08;Single Sou…

windows C#-查询表达式基础(二)

查询变量 在 LINQ 中&#xff0c;查询变量是存储查询而不是查询结果的任何变量。 更具体地说&#xff0c;查询变量始终是可枚举类型&#xff0c;在 foreach 语句或对其 IEnumerator.MoveNext() 方法的直接调用中循环访问时会生成元素序列。 本文中的示例使用以下数据源和示例…

day08|计算机网络重难点之 DNS查询过程、CDN是什么,有什么作用?、Cookie和Session是什么?有什么区别?

day08|计算机网络重难点之 DNS查询过程、CDN是什么&#xff0c;有什么作用&#xff1f;、Cookie和Session是什么&#xff1f;有什么区别&#xff1f; 21.DNS查询过程22.CDN是什么&#xff0c;有什么作用&#xff1f;23.Cookie和Session是什么&#xff1f;有什么区别&#xff1f…

自己动手写Qt Creator插件

文章目录 前言一、环境准备1.先看自己的Qt Creator IDE的版本2.下载源码 二、使用步骤1.参考原本的插件2.编写自定义插件1.cmakelist增加一个模块2.同理&#xff0c;qbs文件也增加一个3.插件源码 三、效果总结 前言 就目前而言&#xff0c;Qt Creator这个IDE&#xff0c;插件比…

C++中的动态断言和静态断言

C中包含动态断言&#xff08;assert&#xff09;和静态断言&#xff08;static_assert&#xff09;&#xff0c;下面分别分析各自的用法。 1.动态断言&#xff08;assert&#xff09; assert 是一个宏&#xff0c;在预处理阶段不生效&#xff0c;在运行阶段才起作用&#xff0…

【JAVA】Java基础—面向对象编程:继承—方法重写

一、背景介绍 在Java编程中&#xff0c;方法重写是面向对象编程&#xff08;OOP&#xff09;的一项重要特性。它允许子类提供对父类方法的具体实现&#xff0c;以便实现多态性。方法重写的主要用途包括&#xff1a; 实现多态性&#xff1a;允许在运行时根据对象的实际类型调用…

ORA-00257: archiver error

ORA-00257: archiver error 归档满问题&#xff1a; 报错&#xff1a; SQL> conn admin/admin ERROR: ORA-00257: archiver error. Connect internal only, until freed. Warning: You are no longer connected to ORACLE. 检查空间&#xff1a; SQL> select name, tot…

React Native 全栈开发实战班 -React Native 基础

本课程旨在帮助学员系统掌握 React Native 全栈开发技能&#xff0c;从基础入门到实战项目开发。课程将分为多个模块&#xff0c;第一部分将聚焦于 React Native 的基础知识&#xff0c;包括开发环境搭建、React Native 简介与特点&#xff0c;以及项目结构解析。 第一部分&am…

云服务器安装mysql8.0(阿里云或者腾讯云都可以)

先说明一下&#xff0c;我使用的是腾讯云&#xff0c;之前用阿里云&#xff0c;然后试用期到期了&#xff0c;所以这次换腾讯云使用&#xff0c;没想到&#xff0c;我在腾讯云里面需要按照阿里云的教程做&#xff0c;还成功了。 这里是阿里云的教程&#xff0c;真的很详细&…

Leetcode:118. 杨辉三角——Java数学法求解

题目——Leetcode:118. 杨辉三角 给定一个非负整数 numRows&#xff0c;生成「杨辉三角」的前 numRows 行。 在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 示例 1: 输入: numRows 5 输出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]示例 2: 输入: numRow…

配置jellyfin docker 硬件加速

mount //192.168.3.152 -o iocharsetutf8,username15814812866,password611611,uidadministrator docker run -it --privilegedtrue --namej4 -v /mnt/nas /media1:rwdocker run -d –namej30 –nethost -v /home/ckw/文档/jellyfin/config:/config -v /home/ckw/文档/jel…

Asp.NET Core Mvc中一个视图怎么设置多个强数据类型

在ASP.NET Core MVC中&#xff0c;一个视图通常与一个强类型模型&#xff08;Model&#xff09;相关联。然而&#xff0c;在某些情况下&#xff0c;你可能需要在单个视图中使用多个不同的模型类型。为了实现这一点&#xff0c;你有几种选择&#xff1a; 使用视图模型&#xff0…

Linux中.NET读取excel组件,不会出现The type initializer for ‘Gdip‘ threw an exception异常

组件&#xff0c;可通过nuget安装&#xff0c;直接搜名字&#xff1a; ExcelDataReader using ConsoleAppReadFileData.Model; using ExcelDataReader; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Task…

Robot | 用 RDK 做一个小型机器人(更新中)

目录 前言架构图开发过程摄像头模型转换准备校准数据使用 hb_mapper makertbin 工具转换模型 底版开发 结语 前言 最近想开发一个小型机器人&#xff0c;碰巧看到了 RDK x5 发布了&#xff0c;参数对于我来说非常合适&#xff0c;就买了一块回来玩。 外设也是非常丰富&#xf…

jenkins使用cli发行uni-app到h5

官网文档HBuilderX 文档 首先确定是否存在环境变量 正常情况cmd中执行cli 如果提示 cli 不是内部或外部命令&#xff0c;也不是可运行的程序或批处理文件。请先配置环境变量 Freestyle Project项目在Build Steps中增加Execute Windows batch command命令如下 d: cd D:\devsof…

基于Zynq FPGA对雷龙SD NAND的测试

一、SD NAND特征 1.1 SD卡简介 雷龙的SD NAND有很多型号&#xff0c;在测试中使用的是CSNP4GCR01-AMW与CSNP32GCR01-AOW。芯片是基于NAND FLASH和 SD控制器实现的SD卡。具有强大的坏块管理和纠错功能&#xff0c;并且在意外掉电的情况下同样能保证数据的安全。 其特点如下&…