Flutter + OpenHarmony 进度条组件开发实战
欢迎加入开源鸿蒙跨平台社区→ https://openharmonycrosplatform.youkuaiyun.com
一、效果展示
📱 运行效果预览
在鸿蒙虚拟机上运行后的实际效果如下:
线性进度条 :
-
水平方向的进度条,显示"下载进度"
-
滑动下方滑块可实时调整进度值
-
右侧显示百分比标签(如65%)
-
带有淡入和滑动动画效果
圆形进度条 : -
三种尺寸并排展示:小(40px)、中(60px)、大(100px)
-
圆环中心显示百分比数字
-
支持滑动调整进度
-
使用TweenAnimationBuilder实现平滑过渡动画
分段进度条 : -
8个独立的小方块组成
-
显示"步骤完成"标签和"5/8"计数
-
每个方块有独立的淡入和缩放动画
-
视觉效果清晰直观
渐变进度条 : -
使用紫-蓝-青三色渐变
-
显示"渐变效果"标签
-
支持自定义任意渐变方案
-
动画流畅自然
不确定进度 : -
线性和圆形两种不确定进度指示器
-
持续旋转/移动,表示加载中状态
-
适用于无法预估时间的场景
🎨 四种样式对比图示
线性进度条:
┌───────────────────────────────────
─┐
│████████████████░░░░░░░░░░░░░░░░░░░
░│ 65%
└───────────────────────────────────
─┘
圆形进度条:
╭───────╮
╱ ╲
│ │
│ 75% │ ← 中心显示百分比
│ │
╲ ╱
╰───────╯
分段进度条:
┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐┌──┐
│██││██││██││██││██││░░││░░││░░│
└──┘└──┘└──┘└──┘└──┘└──┘└──┘└──┘
5/8 段已完成
渐变进度条:
┌───────────────────────────────────
─┐
│▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░░░░░░░░░░░░░░░░│
80%
└───────────────────────────────────
─┘
↑ 紫→蓝→青 渐变效果
二、组件概述
进度条(Progress Indicator)是用户界面中最基础也是最重要的反馈元素之一。它用于向用户展示操作的完成进度、加载状态或等待时间。在 OpenHarmony 环境下开发 Flutter 应用时,一个高质量的进度条组件需要支持多种视觉样式、尺寸规格、动画效果和自定义能力。
本文将详细介绍如何在 Flutter + OpenHarmony 项目中实现一个功能完善的进度条组件系统,涵盖线性、圆形、分段和渐变四种主流样式。
三、核心功能特性
本组件专为鸿蒙生态设计,具备以下核心优势:
✅ 四种进度样式 - 线性、圆形、分段、渐变,覆盖所有场景
✅ 三种尺寸规格 - 小、中、大,适配不同布局需求
✅ 渐变效果支持 - 支持任意多色渐变方案
✅ 百分比标签显示 - 可选的进度数值展示
✅ 流畅动画过渡 - 基于 flutter_animate 的专业动效
✅ 完全可定制 - 颜色、粗细、圆角、高度全部可配
✅ 不确定进度支持 - 加载中状态的无限循环动画
四、技术实现架构
4.1 进度样式枚举
enum ProgressStyle {
linear, // 线性进度条 - 最常用
circular, // 圆形进度环 - 适合空间受
限
segmented, // 分段进度条 - 步骤指示
gradient // 渐变进度条 - 视觉强调
}
4.2 尺寸规格枚举
enum ProgressSize {
small, // 小尺寸 - 紧凑布局
medium, // 中尺寸 - 默认选择
large // 大尺寸 - 强调显示
}
4.3 核心属性配置
class CustomProgress extends
StatelessWidget {
final double?
value; // 进度值 0.
0-1.0
final ProgressStyle
style; // 进度样式
final ProgressSize
size; // 尺寸规格
final Color?
backgroundColor; // 背景色
final Color?
progressColor; // 进度色
final double
strokeWidth; // 圆形进度条
线宽
final double
borderRadius; // 圆角半径
final bool
showLabel; // 是否显示
标签
final String?
label; // 自定义标签文
本
final Widget?
indicator; // 自定义指示器
final Gradient?
gradient; // 渐变配置
final double
height; // 线性进度条
高度
final int
segments; // 分段数量
final double
segmentGap; // 分段间距
const CustomProgress({
super.key,
this.value,
this.style = ProgressStyle.
linear,
this.size = ProgressSize.medium,
// ... 其他参数
});
}
五、线性进度条实现
5.1 核心渲染逻辑
Widget _buildLinearProgress(Color
bgColor, Color pColor, bool isDark)
{
final progressHeight = _getHeight
();
final actualValue = value?.clamp
(0.0, 1.0) ?? 0.0;
return Column(
mainAxisSize: MainAxisSize.min,
children: [
// 可选的标签行
if (showLabel || label !=
null)
Padding(
padding: const EdgeInsets.
only(bottom: 8),
child: Row(
mainAxisAlignment:
MainAxisAlignment.
spaceBetween,
children: [
Text(
label ?? '进度',
style: TextStyle(
fontSize: 14,
color: isDark ?
Colors.grey[300]
: Colors.grey
[700],
),
),
Text(
'${(actualValue *
100).toInt()}%',
style: TextStyle(
fontSize: 14,
fontWeight:
FontWeight.w600,
color: pColor,
),
),
],
),
),
// 进度条容器
Container(
height: progressHeight,
decoration: BoxDecoration(
color: bgColor,
borderRadius:
BorderRadius.circular
(borderRadius),
),
child: LayoutBuilder(
builder: (context,
constraints) {
return Stack(
children: [
// 进度填充
AnimatedContainer(
duration: const
Duration
(milliseconds:
300),
width:
constraints.
maxWidth *
actualValue,
decoration:
BoxDecoration(
color: pColor,
borderRadius:
BorderRadius.
circular
(borderRadius),
),
).animate()
.fadeIn(duration:
300.ms)
.slideX(begin: -0.
1, end: 0),
// 可选的自定义指示器
if (indicator !=
null)
Positioned(
left:
constraints.
maxWidth *
actualValue -
12,
top: -20,
child:
indicator!,
),
],
);
},
),
),
],
);
}
技术要点 :
- clamp(0.0, 1.0) 确保进度值在合法范围内
- AnimatedContainer 实现平滑的宽度变化
- LayoutBuilder 获取父容器宽度用于计算进度条宽度
- Stack 支持叠加自定义指示器
5.2 尺寸自适应
double _getHeight() {
switch (size) {
case ProgressSize.small:
return height * 0.6; // 小尺
寸:基准高度×0.6
case ProgressSize.medium:
return height; // 中尺
寸:基准高度
case ProgressSize.large:
return height * 1.5; // 大尺
寸:基准高度×1.5
}
}
六、圆形进度条实现
6.1 双层圆环设计
Widget _buildCircularProgress(Color
bgColor, Color pColor, bool isDark)
{
final actualValue = value?.clamp
(0.0, 1.0) ?? 0.0;
final size = _getCircularSize();
return SizedBox(
width: size,
height: size,
child: Stack(
alignment: Alignment.center,
children: [
// 背景圆环(灰色)
SizedBox(
width: size,
height: size,
child:
CircularProgressIndicator(
value: 1.0, // 完整圆环
strokeWidth:
strokeWidth,
valueColor:
AlwaysStoppedAnimation<C
olor>(bgColor),
),
),
// 进度圆环(主题色)
SizedBox(
width: size,
height: size,
child:
TweenAnimationBuilder<doub
le>(
tween: Tween(begin: 0.
0, end: actualValue),
duration: const Duration
(milliseconds: 800),
curve: Curves.
easeOutCubic,
builder: (context,
animatedValue, child) {
return
CircularProgressIndica
tor(
value:
animatedValue,
strokeWidth:
strokeWidth,
valueColor:
AlwaysStoppedAnimati
on<Color>(pColor),
strokeCap:
StrokeCap.
round, // 圆角端点
);
},
),
),
// 中心百分比标签
if (showLabel)
Text(
'${(actualValue * 100).
toInt()}%',
style: TextStyle(
fontSize: size > 60 ?
16 : 12,
fontWeight:
FontWeight.w600,
color: isDark ?
Colors.white : Colors.
black87,
),
),
],
),
);
}
技术要点 :
- 使用两个 CircularProgressIndicator 叠加
- 底层为完整背景圆环,上层为进度圆环
- TweenAnimationBuilder 实现从0到目标值的平滑动画
- Curves.easeOutCubic 提供自然的减速效果
- strokeCap: StrokeCap.round 让端点更圆润
6.2 圆形尺寸映射
double _getCircularSize() {
switch (size) {
case ProgressSize.small:
return 40; // 小尺寸:40px
case ProgressSize.medium:
return 60; // 中尺寸:60px
case ProgressSize.large:
return 100; // 大尺寸:100px
}
}
七、分段进度条实现
7.1 多方块布局
Widget _buildSegmentedProgress
(Color bgColor, Color pColor, bool
isDark) {
final actualValue = value?.clamp
(0.0, 1.0) ?? 0.0;
final filledSegments =
(actualValue * segments).round();
return Column(
mainAxisSize: MainAxisSize.min,
children: [
// 标签行
if (showLabel || label !=
null)
Padding(
padding: const EdgeInsets.
only(bottom: 8),
child: Row(
mainAxisAlignment:
MainAxisAlignment.
spaceBetween,
children: [
Text(label ?? '进度',
style: TextStyle
(fontSize: 14)),
Text('$filledSegments/
$segments', style:
TextStyle(fontSize:
14, fontWeight:
FontWeight.w600)),
],
),
),
// 分段方块行
Row(
children: List.generate
(segments, (index) {
final isFilled = index <
filledSegments;
return Expanded(
child: Container(
height: _getHeight(),
margin: EdgeInsets.
only(right: index <
segments - 1 ?
segmentGap : 0),
decoration:
BoxDecoration(
color: isFilled ?
pColor : bgColor,
borderRadius:
BorderRadius.
circular
(borderRadius),
),
).animate()
.fadeIn(delay: (index
* 50).ms) // 延迟淡入
.scale(begin: const
Offset(0.8, 0.8), end:
const Offset(1, 1));
});
}),
),
],
);
}
技术要点 :
- List.generate 动态生成指定数量的方块
- Expanded 让每个方块平均分配宽度
- margin 控制方块间距(最后一个不加)
- 延迟动画( index * 50.ms )产生波浪式入场效果
- 缩放动画让方块从小到大弹出
7.2 分段计算逻辑
final filledSegments = (actualValue
* segments).round();
例如:进度值0.7,分段数10,则填充7个方块。
八、渐变进度条实现
8.1 渐变效果渲染
Widget _buildGradientProgress(Color
bgColor, bool isDark) {
final actualValue = value?.clamp
(0.0, 1.0) ?? 0.0;
final progressHeight = _getHeight
();
return Column(
mainAxisSize: MainAxisSize.min,
children: [
// 标签行
if (showLabel || label !=
null)
Padding(
padding: const EdgeInsets.
only(bottom: 8),
child: Row(
mainAxisAlignment:
MainAxisAlignment.
spaceBetween,
children: [
Text(label ?? '进度',
style: TextStyle
(fontSize: 14)),
Text(
'${(actualValue *
100).toInt()}%',
style: TextStyle(
fontSize: 14,
fontWeight:
FontWeight.w600,
color: gradient?.
colors.first ??
Theme.of(context).
colorScheme.
primary,
),
),
],
),
),
// 渐变进度条
Container(
height: progressHeight,
decoration: BoxDecoration(
color: bgColor,
borderRadius:
BorderRadius.circular
(borderRadius),
),
child: LayoutBuilder(
builder: (context,
constraints) {
return Stack(
children: [
AnimatedContainer(
duration: const
Duration
(milliseconds:
300),
width:
constraints.
maxWidth *
actualValue,
decoration:
BoxDecoration(
gradient:
gradient ??
LinearGradient(
colors: [
Theme.of
(context).
colorScheme.
primary,
Theme.of
(context).
colorScheme.
secondary,
],
),
borderRadius:
BorderRadius.
circular
(borderRadius),
),
).animate()
.fadeIn(duration:
300.ms)
.slideX(begin: -0.
1, end: 0),
],
);
},
),
),
],
);
}
技术要点 :
- 使用 LinearGradient 实现渐变效果
- 支持自定义任意颜色组合
- 默认使用主题色→次要主题色渐变
- 与线性进度条结构相似,只是填充使用渐变
8.2 渐变配置示例
CustomProgress(
value: 0.8,
style: ProgressStyle.gradient,
gradient: const LinearGradient(
colors: [Colors.purple, Colors.
blue, Colors.cyan],
),
)
九、OpenHarmony 平台集成指南
9.1 在鸿蒙项目中引入组件
# 1. 将 custom_progress_widget.dart
文件复制到 lib/widgets/ 目录
cp custom_progress_widget.dart lib/
widgets/
# 2. 在需要使用的页面导入
import 'package:demo1/widgets/
custom_progress_widget.dart';
9.2 在设置页面添加入口
// settings_page.dart 中添加导航项
_buildNavigationTile(
isDark,
icon: Icons.linear_scale,
title: '进度条',
subtitle: '多种进度样式',
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder:
(context) => const
ProgressPreviewPage()),
);
},
),
9.3 在鸿蒙虚拟机运行测试
# 连接鸿蒙虚拟设备
flutter devices
# 运行应用
flutter run -d 127.0.0.1:5555
十、使用示例集锦
示例1:基础线性进度条
CustomProgress(
value: 0.65,
style: ProgressStyle.linear,
showLabel: true,
label: '下载进度',
)
运行效果 :显示"下载进度 65%"的水平进度条。
示例2:圆形进度环
CustomProgress(
value: 0.75,
style: ProgressStyle.circular,
size: ProgressSize.large,
showLabel: true,
strokeWidth: 8,
)
运行效果 :100px的大圆形进度环,中心显示75%,线宽8px。
示例3:步骤指示分段进度
CustomProgress(
value: 0.625,
style: ProgressStyle.segmented,
segments: 8,
showLabel: true,
label: '步骤完成',
)
运行效果 :8个方块,5个填充,显示"步骤完成 5/8"。
示例4:彩虹渐变进度条
CustomProgress(
value: 0.8,
style: ProgressStyle.gradient,
showLabel: true,
label: '渐变效果',
gradient: const LinearGradient(
colors: [Colors.red, Colors.
orange, Colors.yellow, Colors.
green, Colors.blue],
),
)
运行效果 :五色彩虹渐变的进度条。
示例5:自定义颜色和尺寸
CustomProgress(
value: 0.5,
style: ProgressStyle.linear,
size: ProgressSize.large,
backgroundColor: Colors.grey[300],
progressColor: Colors.deepPurple,
height: 12,
borderRadius: 6,
)
运行效果 :12px高的深紫色进度条,圆角6px。
示例6:不确定进度(加载中)
// 线性不确定进度
LinearProgressIndicator(
minHeight: 8,
backgroundColor: Colors.grey[200],
valueColor:
AlwaysStoppedAnimation<Color>
(Colors.blue),
)
// 圆形不确定进度
CircularProgressIndicator(
strokeWidth: 4,
backgroundColor: Colors.grey[200],
valueColor:
AlwaysStoppedAnimation<Color>
(Colors.blue),
)
运行效果 :持续移动/旋转的加载指示器,不显示具体进度。
十一、性能优化策略
11.1 动画优化
- AnimatedContainer :自动处理属性变化的过渡动画
- TweenAnimationBuilder :精确控制动画的起止值和曲线
- 延迟动画 :分段进度条的波浪式入场效果
- flutter_animate :声明式动画,代码简洁高效
11.2 渲染优化
- LayoutBuilder :按需计算宽度,避免硬编码
- Stack + Positioned :高效的层叠布局
- const 构造函数 :减少不必要的重建
- clamp 约束 :防止非法值导致的渲染错误
11.3 内存管理
- StatelessWidget :无状态组件,性能更优
- 及时释放 :AnimationController 在 dispose 中释放
- 避免重建 :使用 key 稳定组件身份
十二、常见问题解答
Q1: 如何让进度条从右向左填充?
设置 TextDirection.rtl 或使用 Transform 翻转:
Transform.flip(flipX: true, child:
CustomProgress(...))
Q2: 如何实现条纹动画进度条?
使用 LinearGradient 配合动画控制器:
AnimatedBuilder(
animation: controller,
builder: (context, child) {
return Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [color1, color2,
color1],
stops: [0, value, 1],
),
),
);
},
)
Q3: 如何隐藏百分比标签?
设置 showLabel: false 即可。
Q4: 如何自定义圆形进度条的起始角度?
使用 Transform.rotate 包装:
Transform.rotate(angle: -pi/2,
child: CustomProgress(style:
ProgressStyle.circular))
Q5: 分段进度条可以不同颜色吗?
可以修改 _buildSegmentedProgress 方法,根据 index 返回不同颜色:
color: isFilled ? colors[index %
colors.length] : bgColor,
虚拟机运行截图

十三、总结与展望
本文详细介绍了如何在 Flutter + OpenHarmony 环境中开发一个功能完善的进度条组件系统。该组件具备以下技术亮点:
🎯 完整的功能矩阵 - 4种样式 × 3种尺寸 = 12种组合
🎨 专业的视觉设计 - 渐变、分段、圆角、阴影
⚡ 卓越的性能表现 - GPU加速动画 + 内存安全
🔧 极简的使用方式 - 声明式API,零学习成本
🌐 完美的平台适配 - 自动适配亮暗主题
实际应用价值 :
-
文件下载/上传进度
-
表单填写步骤指示
-
数据加载状态
-
任务完成度展示
-
游戏经验值/血量条
后续扩展方向 : -
支持条纹动画效果
-
添加波纹/脉冲动画
-
实现多进度条组合
-
支持RTL布局
-
添加无障碍访问支持
2627



被折叠的 条评论
为什么被折叠?



