SwiftUI自定义分段进度条如何实现条形从左到右绿色填充动画

实现方法
要实现单个条形从左到右绿色填充的动画,只需要调整单个条形的绘制逻辑,配合SwiftUI内置动画即可,不需要引入额外依赖。
核心逻辑
原实现是直接切换整个条形的填充色,只能得到整体变色的效果。要实现从左到右填充,需要把每个条形拆成两层:
- 底层是固定的灰色胶囊,作为未选中的底色
- 上层是绿色胶囊,默认宽度为0,对齐到条形左侧,当条形被选中时,宽度从0动画过渡到条形全宽,自然呈现从左到右填满的视觉效果
可直接运行的修改后代码
struct ContentView: View { // 业务使用时把这个状态替换成你自己的进度绑定值即可 @State private var currentIndex = 4 var body: some View { ProgressBar(lastIndex: 8, currentIndex: currentIndex) .padding(.horizontal, 23) .padding(.top, 10) // 测试用按钮,点击可推进进度查看动画效果,正式使用可删除 Button("推进到下一个节点") { // duration控制单个条形的填充速度,数值越大填充越慢 withAnimation(.linear(duration: 0.3)) { currentIndex = min(currentIndex + 1, 8) } } .padding(.top, 50) Spacer() } } struct ProgressBar: View { var lastIndex: Int var currentIndex: Int var body: some View { HStack(alignment: .center, spacing: 4) { ForEach(0...lastIndex, id: \.self) { i in BarElement(selected: i <= currentIndex) } } } } struct BarElement: View { var selected: Bool // 条形尺寸和原代码保持一致 private let barWidth: CGFloat = 33 private let barHeight: CGFloat = 5 var body: some View { ZStack(alignment: .leading) { // 灰色底层 Capsule() .fill(Color(UIColor.lightGray)) // 绿色填充层 Capsule() .fill(.green) .frame(width: selected ? barWidth : 0) } .frame(width: barWidth, height: barHeight) .clipShape(Capsule()) } }
自定义调整
- 调整填充速度:修改
withAnimation里的duration参数即可,比如设为0.5就是半秒填满一个条形 - 实现依次填充效果:如果想要前一个条形完全填满后下一个再开始填充,可以给每个BarElement的动画加对应索引的延迟,延迟值 = 索引 * 单条填充时长
- 调整填充动效曲线:把
.linear换成.easeIn/.easeOut/.spring()等,就能得到不同的填充手感,比如弹性填充效果
内容的提问来源于stack exchange,提问作者tHatpart
相关产品推荐
相关产品推荐

