个人主页: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.dart
class LoadingPage extends StatefulWidget {
const LoadingPage({super.key});
State<LoadingPage> createState() => _LoadingPageState();
}
class _LoadingPageState extends State<LoadingPage> {
bool _isLoading = true;
String? _data;
void initState() {
super.initState();
_fetchData();
}
Future<void> _fetchData() async {
// 模拟网络请求
await Future.delayed(const Duration(seconds: 2));
if (mounted) {
setState(() {
_isLoading = false;
_data = '加载成功!';
});
}
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('环形加载指示器')),
body: Center(
child: _isLoading
? CircularProgressIndicator(
color: Theme.of(context).colorScheme.primary, // ← 使用主题色
strokeWidth: 4,
)
: Text(_data!, style: const TextStyle(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.dart
class UploadPage extends StatefulWidget {
const UploadPage({super.key});
State<UploadPage> createState() => _UploadPageState();
}
class _UploadPageState extends State<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++) {
await Future.delayed(const Duration(milliseconds: 300));
if (mounted) {
setState(() => _progress = i / 10);
}
}
if (mounted) {
setState(() {
_isUploading = false;
_progress = 0.0;
});
// 显示成功提示
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('上传成功!')),
);
}
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('线性进度指示器')),
body: Padding(
padding: const EdgeInsets.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),
),
const SizedBox(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';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
return MaterialApp(
title: '进度指示器 – OpenHarmony',
theme: ThemeData(useMaterial3: true, colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue)),
home: const ProgressDemoPage(),
);
}
}
class ProgressDemoPage extends StatelessWidget {
const ProgressDemoPage({super.key});
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
appBar: AppBar(
title: const Text('进度指示器示例'),
bottom: const TabBar(tabs: [
Tab(text: '环形加载'),
Tab(text: '线性进度'),
]),
),
body: const TabBarView(
children: [
CircularDemo(),
LinearDemo(),
],
),
),
);
}
}
// 环形加载页
class CircularDemo extends StatefulWidget {
const CircularDemo({super.key});
State<CircularDemo> createState() => _CircularDemoState();
}
class _CircularDemoState extends State<CircularDemo> {
bool loading = false;
Future<void> simulateLoad() async {
setState(() => loading = true);
await Future.delayed(const Duration(seconds: 2));
if (mounted) setState(() => loading = false);
}
Widget build(BuildContext context) {
return Center(
child: loading
? CircularProgressIndicator(
color: Theme.of(context).colorScheme.primary,
)
: ElevatedButton(
onPressed: simulateLoad,
child: const Text('触发加载'),
),
);
}
}
// 线性进度页
class LinearDemo extends StatefulWidget {
const LinearDemo({super.key});
State<LinearDemo> createState() => _LinearDemoState();
}
class _LinearDemoState extends State<LinearDemo> {
double progress = 0.0;
bool uploading = false;
Future<void> simulateUpload() async {
setState(() => uploading = true);
for (int i = 1; i <= 100; i += 10) {
await Future.delayed(const Duration(milliseconds: 200));
if (mounted) setState(() => progress = i / 100);
}
if (mounted) setState(() => uploading = false);
}
Widget build(BuildContext context) {
return Center(
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),
),
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: uploading ? null : simulateUpload,
child: Text(uploading ? '上传中' : '开始上传'),
),
],
),
);
}
}
代码示例:

四、面向 OpenHarmony 手机的工程化建议
1. 统一封装加载组件
避免重复代码,创建可复用的加载 Widget:
// widgets/loading_indicator.dart
class AppCircularProgress extends StatelessWidget {
const AppCircularProgress({super.key});
Widget build(BuildContext context) {
return CircularProgressIndicator(
color: Theme.of(context).colorScheme.primary,
strokeWidth: 3,
);
}
}
class AppLinearProgress extends StatelessWidget {
final double value;
const AppLinearProgress({super.key, required this.value});
Widget build(BuildContext context) {
return LinearProgressIndicator(
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
网硕互联帮助中心



评论前必须登录!
注册