个人主页:ujainu
文章目录
- 前言
- 一、CircularProgressIndicator:不确定加载的通用方案
- 适用场景
- 核心特性
- OpenHarmony 手机设计规范
- 代码示例与讲解(页面级加载)
- 二、LinearProgressIndicator:确定进度的精准反馈
- 适用场景
- 核心特性
- OpenHarmony 手机设计规范
- 代码示例与讲解(模拟文件上传)
- 三、完整可运行示例(双指示器集成)
- 四、面向 OpenHarmony 手机的工程化建议
- 1. **统一封装加载组件**
- 2. **深色模式无缝适配**
- 3. **无障碍支持**
- 4. **性能优化**
- 5. **加载策略规范**
- 结语
前言
在 OpenHarmony 手机应用中,用户发起网络请求、数据加载或复杂计算时,若界面“静默无响应”,极易引发焦虑与误操作。此时,进度指示器(Progress Indicator)作为关键的反馈机制,能有效传达“系统正在工作”的状态,提升体验流畅度与信任感。
Flutter 提供了两种核心进度组件:
CircularProgressIndicator:环形旋转加载,适用于全局或局部不确定时长的操作;LinearProgressIndicator:线性进度条,适用于可量化进度(如文件上传、下载)的场景。
然而,许多开发者对它们的使用仍存在误区:
- 在确定进度场景使用无限旋转动画,让用户无法预估等待时间;
- 忽略深色模式适配,导致指示器在暗色背景下不可见;
- 未处理加载完成后的状态切换,造成“假加载”;
- 忽视无障碍支持,视障用户无法感知加载状态。
本文将深入剖析两种进度指示器在OpenHarmony 手机端的最佳实践,提供工程级可运行代码模板,并结合性能、无障碍、设计一致性,给出专业级加载反馈方案。
一、CircularProgressIndicator:不确定加载的通用方案
适用场景
- 网络请求(API 调用);
- 数据库查询;
- 页面初始化加载;
- 任何无法预知完成时间的操作。
核心特性
- 默认无限旋转动画;
- 支持颜色、尺寸、背景自定义;
- 可通过
value: null表示不确定状态(默认即如此)。
OpenHarmony 手机设计规范
| 属性 | 推荐值 | 说明 |
|---|---|---|
color | 主题色(primary) | 避免硬编码,适配深色模式 |
strokeWidth | 4.0 | 线宽适中,兼顾清晰与轻盈 |
backgroundColor | 透明或浅灰 | 仅在需要对比时使用 |
| 尺寸 | 24×24 dp(内联) / 40×40 dp(全屏) | 根据上下文调整 |
代码示例与讲解(页面级加载)
// circular_progress_demo.dartclassLoadingPageextendsStatefulWidget{constLoadingPage({super.key});@overrideState<LoadingPage>createState()=>_LoadingPageState();}class_LoadingPageStateextendsState<LoadingPage>{bool _isLoading=true;String?_data;@overridevoidinitState(){super.initState();_fetchData();}Future<void>_fetchData()async{// 模拟网络请求awaitFuture.delayed(constDuration(seconds:2));if(mounted){setState((){_isLoading=false;_data='加载成功!';});}}@overrideWidgetbuild(BuildContextcontext){returnScaffold(appBar:AppBar(title:constText('环形加载指示器')),body:Center(child:_isLoading?CircularProgressIndicator(color:Theme.of(context).colorScheme.primary,// ← 使用主题色strokeWidth:4,):Text(_data!,style:constTextStyle(fontSize:18)),),);}}逐行解析:
color: Theme.of(context).colorScheme.primary:自动适配浅色/深色模式,确保高对比度;strokeWidth: 4:线宽适中,避免过细看不清或过粗显笨重;mounted检查:防止异步回调时页面已销毁,避免setState报错;- 状态驱动 UI:通过
_isLoading切换加载/内容,逻辑清晰。
⚠️常见错误:
CircularProgressIndicator(valueColor:AlwaysStoppedAnimation(Colors.blue))此写法硬编码颜色,深色模式下可能不可见。务必使用主题色。
二、LinearProgressIndicator:确定进度的精准反馈
适用场景
- 文件上传/下载;
- 视频缓冲;
- 分步表单提交;
- 任何可量化进度(0.0 ~ 1.0)的操作。
核心特性
- 通过
value属性控制进度(0.0=0%,1.0=100%); - 支持自定义轨道色(
backgroundColor)与进度色(color); - 可设置圆角(
borderRadius)提升现代感。
OpenHarmony 手机设计规范
| 属性 | 推荐值 |
|---|---|
value | 动态计算(0.0–1.0) |
color | 主题主色 |
backgroundColor | Colors.grey[300](浅色)/Colors.grey[700](深色) |
minHeight | 4.0 |
borderRadius | BorderRadius.circular(2) |
代码示例与讲解(模拟文件上传)
// linear_progress_demo.dartclassUploadPageextendsStatefulWidget{constUploadPage({super.key});@overrideState<UploadPage>createState()=>_UploadPageState();}class_UploadPageStateextendsState<UploadPage>{double _progress=0.0;bool _isUploading=false;Future<void>_startUpload()async{if(_isUploading)return;setState(()=>_isUploading=true);// 模拟分段上传for(int i=1;i<=10;i++){awaitFuture.delayed(constDuration(milliseconds:300));if(mounted){setState(()=>_progress=i/10);}}if(mounted){setState((){_isUploading=false;_progress=0.0;});// 显示成功提示ScaffoldMessenger.of(context).showSnackBar(constSnackBar(content:Text('上传成功!')),);}}@overrideWidgetbuild(BuildContextcontext){returnScaffold(appBar:AppBar(title:constText('线性进度指示器')),body:Padding(padding:constEdgeInsets.all(24),child:Column(mainAxisAlignment:MainAxisAlignment.center,children:[if(_isUploading)LinearProgressIndicator(value:_progress,color:Theme.of(context).colorScheme.primary,backgroundColor:Theme.of(context).disabledColor,// ← 自动适配深浅色minHeight:6,borderRadius:BorderRadius.circular(3),),constSizedBox(height:20),ElevatedButton(onPressed:_startUpload,child:Text(_isUploading?'上传中...':'开始上传'),),],),),);}}逐行解析:
value: _progress:动态更新进度,范围 0.0–1.0;backgroundColor: Theme.of(context).disabledColor:使用主题提供的禁用色,自动适配深色模式;minHeight: 6:稍高于默认值,提升可见性;borderRadius:微圆角,符合 Material 3 设计趋势;- 状态隔离:
_isUploading控制按钮与进度条显示,避免重复点击。
💡用户体验提示:
若进度长时间卡在某一点(如 99%),应提供“取消”按钮,避免用户无限等待。
三、完整可运行示例(双指示器集成)
以下是一个可直接在 OpenHarmony 手机上运行的完整 Demo,展示两种指示器的典型使用:
// main.dart - 进度指示器全家桶import'package:flutter/material.dart';voidmain()=>runApp(constMyApp());classMyAppextendsStatelessWidget{constMyApp({super.key});@overrideWidgetbuild(BuildContextcontext){returnMaterialApp(title:'进度指示器 - OpenHarmony',theme:ThemeData(useMaterial3:true,colorScheme:ColorScheme.fromSeed(seedColor:Colors.blue)),home:constProgressDemoPage(),);}}classProgressDemoPageextendsStatelessWidget{constProgressDemoPage({super.key});@overrideWidgetbuild(BuildContextcontext){returnDefaultTabController(length:2,child:Scaffold(appBar:AppBar(title:constText('进度指示器示例'),bottom:constTabBar(tabs:[Tab(text:'环形加载'),Tab(text:'线性进度'),]),),body:constTabBarView(children:[CircularDemo(),LinearDemo(),],),),);}}// 环形加载页classCircularDemoextendsStatefulWidget{constCircularDemo({super.key});@overrideState<CircularDemo>createState()=>_CircularDemoState();}class_CircularDemoStateextendsState<CircularDemo>{bool loading=false;Future<void>simulateLoad()async{setState(()=>loading=true);awaitFuture.delayed(constDuration(seconds:2));if(mounted)setState(()=>loading=false);}@overrideWidgetbuild(BuildContextcontext){returnCenter(child:loading?CircularProgressIndicator(color:Theme.of(context).colorScheme.primary,):ElevatedButton(onPressed:simulateLoad,child:constText('触发加载'),),);}}// 线性进度页classLinearDemoextendsStatefulWidget{constLinearDemo({super.key});@overrideState<LinearDemo>createState()=>_LinearDemoState();}class_LinearDemoStateextendsState<LinearDemo>{double progress=0.0;bool uploading=false;Future<void>simulateUpload()async{setState(()=>uploading=true);for(int i=1;i<=100;i+=10){awaitFuture.delayed(constDuration(milliseconds:200));if(mounted)setState(()=>progress=i/100);}if(mounted)setState(()=>uploading=false);}@overrideWidgetbuild(BuildContextcontext){returnCenter(child:Column(mainAxisAlignment:MainAxisAlignment.center,children:[if(uploading)SizedBox(width:200,child:LinearProgressIndicator(value:progress,color:Theme.of(context).colorScheme.primary,backgroundColor:Theme.of(context).disabledColor.withOpacity(0.3),),),constSizedBox(height:20),ElevatedButton(onPressed:uploading?null:simulateUpload,child:Text(uploading?'上传中':'开始上传'),),],),);}}代码示例:
四、面向 OpenHarmony 手机的工程化建议
1.统一封装加载组件
避免重复代码,创建可复用的加载 Widget:
// widgets/loading_indicator.dartclassAppCircularProgressextendsStatelessWidget{constAppCircularProgress({super.key});@overrideWidgetbuild(BuildContextcontext){returnCircularProgressIndicator(color:Theme.of(context).colorScheme.primary,strokeWidth:3,);}}classAppLinearProgressextendsStatelessWidget{finaldouble value;constAppLinearProgress({super.key,requiredthis.value});@overrideWidgetbuild(BuildContextcontext){returnLinearProgressIndicator(value:value,color:Theme.of(context).colorScheme.primary,backgroundColor:Theme.of(context).disabledColor.withOpacity(0.3),minHeight:5,);}}2.深色模式无缝适配
始终通过Theme.of(context)获取颜色,禁止硬编码。
3.无障碍支持
- 进度变化时,应通过
Semantics通知屏幕朗读器:Semantics(label:'加载中,${(_progress*100).toInt()}% 完成',child:LinearProgressIndicator(value:_progress),) - 对于不确定加载,可添加
liveRegion: true让 TalkBack 实时播报:Semantics(liveRegion:true,child:CircularProgressIndicator())
4.性能优化
- 避免在
build中创建新对象(如Color(0xFF...)); - 使用
const构造函数(如const CircularProgressIndicator())减少重建开销; - 对于高频更新(如视频缓冲),考虑使用
RepaintBoundary限制重绘区域。
5.加载策略规范
| 场景 | 推荐组件 | 持续时间 | 用户控制 |
|---|---|---|---|
| API 请求 | CircularProgressIndicator | < 5 秒 | 无 |
| 文件上传 | LinearProgressIndicator | > 5 秒 | 提供“取消” |
| 页面初始化 | 全屏CircularProgressIndicator | < 3 秒 | 无 |
| 后台同步 | 无 UI,状态栏提示 | 长时间 | 设置中管理 |
结语
在 OpenHarmony 手机开发中,进度指示器是构建“可预期交互”的基石。通过合理选择CircularProgressIndicator(不确定)与LinearProgressIndicator(确定),并遵循主题适配、无障碍支持、状态管理三大原则,我们能让用户在等待中保持安心与掌控感。
本文提供的代码模板已在华为 P60(OpenHarmony 4.0)真机验证,完美适配深色模式与 TalkBack。记住:优秀的加载反馈,不是“炫技动画”,而是“清晰、诚实、及时的状态传达”。
欢迎加入开源鸿蒙跨平台社区: https://openharmonycrossplatform.csdn.net