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

embedded/2024/11/17 11:50:06/

        使用 `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/embedded/138243.html

相关文章

React Query在现代前端开发中的应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 React Query在现代前端开发中的应用 React Query在现代前端开发中的应用 React Query在现代前端开发中的应用 引言 React Query …

LLMs 训练经验篇

LLMs 训练经验篇 分布式训练框架选择&#xff1f; 多用 DeepSpeed&#xff0c;少用 Pytorch 原生的 torchrun。在节点数量较少的情况下&#xff0c;使用何种训练框架并不是特别重要&#xff1b;然而&#xff0c;一旦涉及到数百个节点&#xff0c;DeepSpeed 显现出其强大之处&…

RabbitMQ教程:工作队列(Work Queues)(二)

RabbitMQ教程&#xff1a;工作队列&#xff08;Work Queues&#xff09;&#xff08;二&#xff09; 一、引言 在快节奏的软件开发世界中&#xff0c;我们经常面临需要异步处理任务的场景&#xff0c;比如在Web应用中处理耗时的图片处理或数据分析任务。这些任务如果直接在用…

Jetson ros默认依赖opencv与系统安装opencv、推流、cv_bridge等存在BUG

下载源码&#xff0c;源码编译支持系统opencv git clone -b noetic https://github.com/ros-perception/vision_opencv.gitset(_opencv_version 4) #设置为系统opencv find_package(OpenCV 4 QUIET) if(NOT OpenCV_FOUND)message(STATUS "Did not find OpenCV 4, tryin…

基于的图的异常检测算法OddBall

OddBall异常检测算法出自2010年的论文《OddBall: Spotting Anomalies in Weighted Graphs》&#xff0c;它是一个在加权图(weighted graph)上检测异常点的算法&#xff0c;基本思路为计算每一个点的一度邻域特征&#xff0c;然后在整个图上用这些特征拟合出一个函数&#xff0c…

Django中的URL配置与动态参数传递(多种方法比较)

Django中的URL配置与动态参数传递(多种方法比较) 目录 ✨ 基础URL配置与re_path()的解读&#x1f527; path()与re_path()的对比分析&#x1f680; 动态参数处理方案详解&#x1f4d8; 正则表达式匹配的优势与劣势&#x1f9e9; 利用path()进行路径参数处理的实现与优劣&…

蓝桥杯——杨辉三角

代码 package day3;public class Demo2 {public static void main(String[] args) {// TODO Auto-generated method stub// for (int i 0; i < 10; i) {// for (int j 0; j < 10; j) {// System.out.print("外&#xff1a;"i"内&#xff1a;&qu…

网页web无插件播放器EasyPlayer.js H.265流媒体播放器的decoder.js报Unexpected token ‘<‘错误

EasyPlayer.js H.265流媒体播放器属于一款高效、精炼、稳定且免费的流媒体播放器&#xff0c;可支持多种流媒体协议播放&#xff0c;支持H.264与H.265编码格式&#xff0c;性能稳定、播放流畅&#xff1b;支持WebSocket-FLV、HTTP-FLV&#xff0c;HLS&#xff08;m3u8&#xff…