news 2026/4/15 13:29:07

FlutterOpenHarmony商城App下拉刷新组件开发

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
FlutterOpenHarmony商城App下拉刷新组件开发

#

前言

下拉刷新是移动应用中最常见的交互模式之一,用户通过下拉手势触发数据刷新,获取最新内容。在商城应用中,商品列表、订单列表、消息列表等页面都需要支持下拉刷新功能。一个设计良好的下拉刷新组件需要提供流畅的手势响应和清晰的状态反馈。本文将详细介绍如何在Flutter和OpenHarmony平台上开发下拉刷新组件。

下拉刷新的设计需要考虑手势的灵敏度、刷新状态的展示、刷新完成的反馈等多个方面。用户期望下拉时能够看到明确的视觉反馈,知道何时可以释放触发刷新,刷新过程中能够看到加载状态,刷新完成后能够得到结果提示。

Flutter下拉刷新基础实现

首先了解Flutter内置的RefreshIndicator:

classRefreshableListextendsStatefulWidget{finalFuture<void>Function()onRefresh;finalWidgetchild;constRefreshableList({Key?key,requiredthis.onRefresh,requiredthis.child,}):super(key:key);@overrideState<RefreshableList>createState()=>_RefreshableListState();}class_RefreshableListStateextendsState<RefreshableList>{@overrideWidgetbuild(BuildContextcontext){returnRefreshIndicator(onRefresh:widget.onRefresh,color:constColor(0xFFE53935),backgroundColor:Colors.white,displacement:40,child:widget.child,);}}

RefreshIndicator是Flutter提供的Material风格下拉刷新组件。onRefresh回调返回Future,刷新指示器会在Future完成后自动隐藏。color设置指示器颜色为主题红色,backgroundColor设置背景为白色。displacement设置指示器下拉的最大位移。child是需要支持下拉刷新的滚动组件。这种实现方式简单快捷,适合大多数场景。

自定义下拉刷新组件

enumRefreshState{idle,// 空闲pulling,// 下拉中ready,// 可以刷新refreshing,// 刷新中completed,// 刷新完成}classCustomRefreshHeaderextendsStatelessWidget{finalRefreshStatestate;finaldouble pullDistance;finaldouble refreshTriggerDistance;constCustomRefreshHeader({Key?key,requiredthis.state,requiredthis.pullDistance,this.refreshTriggerDistance=80,}):super(key:key);@overrideWidgetbuild(BuildContextcontext){returnContainer(height:pullDistance,alignment:Alignment.center,child:_buildContent(),);}}

CustomRefreshHeader组件实现自定义的下拉刷新头部。RefreshState枚举定义了刷新的五种状态,从空闲到刷新完成覆盖了完整的刷新流程。pullDistance是当前下拉距离,refreshTriggerDistance是触发刷新的阈值距离。Container高度随下拉距离变化,_buildContent方法根据状态显示不同内容。这种设计提供了完全自定义的刷新头部样式。

刷新头部内容:

Widget_buildContent(){switch(state){caseRefreshState.idle:returnconstSizedBox.shrink();caseRefreshState.pulling:returnRow(mainAxisSize:MainAxisSize.min,children:[Icon(Icons.arrow_downward,size:18,color:Colors.grey[600],),constSizedBox(width:8),Text('下拉刷新',style:TextStyle(fontSize:13,color:Colors.grey[600],),),],);caseRefreshState.ready:returnRow(mainAxisSize:MainAxisSize.min,children:[Icon(Icons.arrow_upward,size:18,color:Colors.grey[600],),constSizedBox(width:8),Text('释放刷新',style:TextStyle(fontSize:13,color:Colors.grey[600],),),],);caseRefreshState.refreshing:returnRow(mainAxisSize:MainAxisSize.min,children:[constSizedBox(width:18,height:18,child:CircularProgressIndicator(strokeWidth:2),),constSizedBox(width:8),Text('正在刷新...',style:TextStyle(fontSize:13,color:Colors.grey[600],),),],);caseRefreshState.completed:returnRow(mainAxisSize:MainAxisSize.min,children:[constIcon(Icons.check_circle,size:18,color:Color(0xFF4CAF50),),constSizedBox(width:8),Text('刷新完成',style:TextStyle(fontSize:13,color:Colors.grey[600],),),],);}}

根据刷新状态显示不同的内容和图标。下拉中显示向下箭头和"下拉刷新"提示,可以刷新时显示向上箭头和"释放刷新"提示,刷新中显示加载指示器和"正在刷新…"提示,刷新完成显示绿色对勾和"刷新完成"提示。Row水平排列图标和文字,mainAxisSize.min使内容宽度自适应。这种状态反馈让用户清楚地知道当前的刷新进度。

下拉刷新控制器

classRefreshController{RefreshState_state=RefreshState.idle;final_stateController=StreamController<RefreshState>.broadcast();Stream<RefreshState>getstateStream=>_stateController.stream;RefreshStategetstate=>_state;voidstartRefresh(){_state=RefreshState.refreshing;_stateController.add(_state);}voidcompleteRefresh(){_state=RefreshState.completed;_stateController.add(_state);Future.delayed(constDuration(milliseconds:500),(){_state=RefreshState.idle;_stateController.add(_state);});}voiddispose(){_stateController.close();}}

RefreshController管理刷新状态的变化。使用StreamController广播状态变化,组件可以通过监听stateStream获取状态更新。startRefresh方法开始刷新,completeRefresh方法完成刷新并在500毫秒后恢复空闲状态。dispose方法关闭流控制器释放资源。这种控制器模式使刷新状态的管理更加灵活,可以在任何地方触发刷新。

上拉加载更多组件

classLoadMoreFooterextendsStatelessWidget{finalbool isLoading;finalbool hasMore;finalVoidCallback?onLoadMore;constLoadMoreFooter({Key?key,requiredthis.isLoading,requiredthis.hasMore,this.onLoadMore,}):super(key:key);@overrideWidgetbuild(BuildContextcontext){if(!hasMore){returnContainer(padding:constEdgeInsets.all(16),alignment:Alignment.center,child:Text('没有更多了',style:TextStyle(fontSize:13,color:Colors.grey[500],),),);}returnGestureDetector(onTap:isLoading?null:onLoadMore,child:Container(padding:constEdgeInsets.all(16),alignment:Alignment.center,child:isLoading?Row(mainAxisSize:MainAxisSize.min,children:[constSizedBox(width:16,height:16,child:CircularProgressIndicator(strokeWidth:2),),constSizedBox(width:8),Text('加载中...',style:TextStyle(fontSize:13,color:Colors.grey[500],),),],):Text('上拉加载更多',style:TextStyle(fontSize:13,color:Colors.grey[500],),),),);}}

LoadMoreFooter组件显示在列表底部,提供上拉加载更多功能。isLoading表示是否正在加载,hasMore表示是否还有更多数据。当没有更多数据时显示"没有更多了"提示,加载中时显示加载指示器和"加载中…"提示,空闲时显示"上拉加载更多"提示。GestureDetector处理点击事件,加载中时禁用点击。这种设计为用户提供了清晰的加载状态反馈。

OpenHarmony下拉刷新实现

@Componentstruct RefreshableList{@StateisRefreshing:boolean=false@StaterefreshState:string='idle'privateonRefresh:()=>Promise<void>=async()=>{}@BuilderParamcontent:()=>voidbuild(){Refresh({refreshing:$$this.isRefreshing}){this.content()}.onStateChange((state:RefreshStatus)=>{this.handleStateChange(state)}).onRefreshing(async()=>{awaitthis.onRefresh()this.isRefreshing=false})}handleStateChange(state:RefreshStatus){switch(state){caseRefreshStatus.Inactive:this.refreshState='idle'breakcaseRefreshStatus.Drag:this.refreshState='pulling'breakcaseRefreshStatus.OverDrag:this.refreshState='ready'breakcaseRefreshStatus.Refresh:this.refreshState='refreshing'breakcaseRefreshStatus.Done:this.refreshState='completed'break}}}

OpenHarmony提供了原生的Refresh组件实现下拉刷新。$$this.isRefreshing使用双向绑定,刷新状态会自动同步。onStateChange回调在刷新状态变化时触发,可以根据状态更新UI。onRefreshing回调在触发刷新时执行,完成后将isRefreshing设为false结束刷新。@BuilderParam接收列表内容作为子组件。这种实现方式比Flutter更加简洁。

自定义刷新头部ArkUI实现:

@BuilderRefreshHeader(){Row(){if(this.refreshState==='pulling'){Image($r('app.media.arrow_down')).width(18).height(18)Text('下拉刷新').fontSize(13).fontColor('#999999').margin({left:8})}elseif(this.refreshState==='ready'){Image($r('app.media.arrow_up')).width(18).height(18)Text('释放刷新').fontSize(13).fontColor('#999999').margin({left:8})}elseif(this.refreshState==='refreshing'){LoadingProgress().width(18).height(18)Text('正在刷新...').fontSize(13).fontColor('#999999').margin({left:8})}elseif(this.refreshState==='completed'){Image($r('app.media.check')).width(18).height(18)Text('刷新完成').fontSize(13).fontColor('#999999').margin({left:8})}}.width('100%').height(60).justifyContent(FlexAlign.Center)}

@Builder装饰器定义了自定义刷新头部的构建方法。根据refreshState显示不同的图标和文字。Image加载本地图标资源,LoadingProgress显示加载动画。Row水平排列图标和文字,justifyContent设为FlexAlign.Center使内容居中。这种实现方式与Flutter版本的视觉效果一致。

加载更多ArkUI实现

@BuilderLoadMoreFooter(){Row(){if(!this.hasMore){Text('没有更多了').fontSize(13).fontColor('#999999')}elseif(this.isLoadingMore){LoadingProgress().width(16).height(16)Text('加载中...').fontSize(13).fontColor('#999999').margin({left:8})}else{Text('上拉加载更多').fontSize(13).fontColor('#999999')}}.width('100%').height(50).justifyContent(FlexAlign.Center)}

加载更多底部组件根据加载状态和数据状态显示不同内容。hasMore为false时显示"没有更多了",isLoadingMore为true时显示加载动画和"加载中…“,否则显示"上拉加载更多”。LoadingProgress是ArkUI提供的加载动画组件。这种实现方式简洁高效,与Flutter版本功能一致。

完整列表组件

classRefreshableListViewextendsStatefulWidget{finalFuture<void>Function()onRefresh;finalFuture<void>Function()?onLoadMore;finalbool hasMore;finalList<Widget>children;constRefreshableListView({Key?key,requiredthis.onRefresh,this.onLoadMore,this.hasMore=true,requiredthis.children,}):super(key:key);@overrideState<RefreshableListView>createState()=>_RefreshableListViewState();}class_RefreshableListViewStateextendsState<RefreshableListView>{bool _isLoadingMore=false;finalScrollController_scrollController=ScrollController();@overridevoidinitState(){super.initState();_scrollController.addListener(_onScroll);}void_onScroll(){if(_scrollController.position.pixels>=_scrollController.position.maxScrollExtent-100){_loadMore();}}Future<void>_loadMore()async{if(_isLoadingMore||!widget.hasMore||widget.onLoadMore==null){return;}setState(()=>_isLoadingMore=true);awaitwidget.onLoadMore!();setState(()=>_isLoadingMore=false);}@overrideWidgetbuild(BuildContextcontext){returnRefreshIndicator(onRefresh:widget.onRefresh,child:ListView(controller:_scrollController,children:[...widget.children,LoadMoreFooter(isLoading:_isLoadingMore,hasMore:widget.hasMore,),],),);}}

RefreshableListView组件整合了下拉刷新和上拉加载更多功能。ScrollController监听滚动位置,当距离底部小于100像素时触发加载更多。_isLoadingMore防止重复加载,hasMore控制是否还有更多数据。RefreshIndicator包裹ListView提供下拉刷新,LoadMoreFooter放在列表底部显示加载状态。这种设计提供了完整的列表刷新和加载功能。

总结

本文详细介绍了Flutter和OpenHarmony平台上下拉刷新组件的开发过程。下拉刷新作为移动应用的基础交互模式,其设计质量直接影响用户的操作体验。通过自定义刷新头部、加载更多底部、刷新控制器等组件的合理设计,我们为用户提供了流畅的刷新交互体验。在实际项目中,还可以进一步添加刷新动画、震动反馈、刷新时间显示等功能。

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/10 7:51:05

LCD1602只亮不显示的电路设计缺陷全面讲解

LCD1602只亮不显示&#xff1f;别再误判故障&#xff0c;这5个电路设计坑你踩过几个&#xff01; 在单片机开发的“新手村”&#xff0c;几乎每位工程师都曾遭遇同一个谜题&#xff1a; LCD1602背光明明亮着&#xff0c;为什么屏幕上一个字都不显示&#xff1f; 不是代码没烧…

作者头像 李华
网站建设 2026/4/9 17:55:51

MySQL 视图:把复杂变简单的“虚拟化”艺术

1. 什么是视图&#xff1f;&#xff08;定义与本质&#xff09; 在数据库的世界里&#xff0c;视图&#xff08;View&#xff09; 是一张虚拟表。 它和我们平常用的物理表&#xff08;Base Table&#xff09;不同&#xff1a;物理表里存的是实实在在的数据&#xff0c;占硬盘空…

作者头像 李华
网站建设 2026/4/14 4:07:03

OrCAD等长布线通俗解释:高速信号同步控制方法

OrCAD等长布线实战解析&#xff1a;如何让高速信号“步调一致”你有没有遇到过这样的情况&#xff1f;电路板明明按图施工&#xff0c;元件也都是正品原装&#xff0c;可一上电&#xff0c;DDR就是初始化失败&#xff0c;数据读写错乱&#xff1b;或者高速接口跑不起来&#xf…

作者头像 李华
网站建设 2026/4/2 2:45:23

Steamless终极指南:快速移除Steam游戏DRM限制的完整方案

你是否曾经遇到过这样的情况&#xff1a;购买的正版Steam游戏在某些特殊环境下无法正常运行&#xff1f;或者希望减少对Steam平台的依赖&#xff0c;获得更多的运行自由度&#xff1f;Steamless正是为解决这些问题而生的专业工具&#xff0c;它能够高效移除Steam游戏的DRM保护&…

作者头像 李华
网站建设 2026/4/1 6:36:23

VSCode Python扩展终极指南:从零到精通的完整教程

VSCode Python扩展终极指南&#xff1a;从零到精通的完整教程 【免费下载链接】vscode-python Python extension for Visual Studio Code 项目地址: https://gitcode.com/gh_mirrors/vs/vscode-python VSCode Python扩展是微软官方开发的Python开发利器&#xff0c;为Py…

作者头像 李华
网站建设 2026/4/15 13:10:01

终极指南:如何通过WuWa-Mod模组彻底改变《鸣潮》游戏体验

终极指南&#xff1a;如何通过WuWa-Mod模组彻底改变《鸣潮》游戏体验 【免费下载链接】wuwa-mod Wuthering Waves pak mods 项目地址: https://gitcode.com/GitHub_Trending/wu/wuwa-mod 痛点洞察&#xff1a;游戏中的那些困扰时刻 你是否曾在《鸣潮》游戏中遇到这些令…

作者头像 李华