SwiftUI 使用Capsule創建進度條
xcode 13.3.1, swift 5.5, iOS 15.4
2022-08-10
進度條在很多地方都會用到,這篇會介紹在SwiftUI 可以很簡單的做出進度條。
1. 使用Capsule創建一個高為20的白色膠囊形狀,並使用overlay疊加一個2個單位的灰色外框。
struct CapsuleProgressExample: View {
var body: some View {
Capsule()
.fill(.white)
.frame(height: 20)
.overlay(
Capsule()
.stroke(.gray, lineWidth: 2.0)
)
}
}
2. 再使用overlay在原有Capsule上面疊加一個綠色的長條。
struct CapsuleProgressExample: View {
var body: some View {
Capsule()
.fill(.white)
.frame(height: 20)
.overlay(
Capsule()
.stroke(.gray, lineWidth: 2.0)
)
.overlay(
Capsule()
.inset(by: 1)
.fill(.green)
)
}
}
3. 疊加的綠色條是用來顯示當前進度的情況,我們可以用frame(width,height)來進行控制。
struct CapsuleProgressExample: View {
var body: some View {
Capsule()
.fill(.white)
.frame(height: 20)
.overlay(
Capsule()
.stroke(.gray, lineWidth: 2.0)
)
.overlay(
Capsule()
.inset(by: 1)
.fill(.green)
.frame(width: 100)
)
}
}
4. 從上圖所看到控制了綠色條的長度,但我們需要把綠色長放到最左邊,另外我們也要取到整個控制條可以設置的長度,這時可以使用SwiftUI提供的一個控件GeometryReader,從GeometryReader元件可以取得的座標尺寸。
struct CapsuleProgressExample: View {
var body: some View {
Capsule()
.fill(.white)
.frame(height: 20)
.overlay(
Capsule()
.stroke(.gray, lineWidth: 2.0)
)
.overlay(
GeometryReader { proxy in
Capsule()
.inset(by: 1)
.fill(.green)
.frame(width: proxy.size.width)
}
)
}
}
從GeometryReader的size取後當前元件所佔的寬度和長度。
5. 知道從GeometryReader.size.width取得進度條可設的最大長度後,現在就可以增加一個百份比的變量percent設置其綠色條的佔比了,比如percent=0.5就是顯示一半的綠色條。由於我們以 overlay 將 GeometryReader 疊加上在原有的 Capsule 上,所以它的位置大小即是 原有Capsule 的空間。
struct CapsuleProgressExample: View {
@State var percent = 0.5
var body: some View {
Capsule()
.fill(.white)
.frame(height: 20)
.overlay(
Capsule()
.stroke(.gray, lineWidth: 2.0)
)
.overlay(
GeometryReader { proxy in
Capsule()
.inset(by: 1)
.fill(.green)
.frame(width: proxy.size.width * percent)
}
)
}
}
6. 現在就可以用動畫把percent從0改到1,來演示整個進度條的效果。
struct CapsuleProgressExample: View {
@State var percent = 0.0
var body: some View {
Capsule()
.fill(.white)
.frame(height: 20)
.overlay(
Capsule()
.stroke(.gray, lineWidth: 2.0)
)
.overlay(
GeometryReader { proxy in
Capsule()
.inset(by: 1)
.fill(.green)
.frame(width: proxy.size.width * percent)
.animation(.linear(duration: 3.0), value: percent)
}
)
.onTapGesture {
percent = 1.0
}
}
}
7. 把上述代碼包成一個元件,就可以複用到其他地方。
struct CapsuleProgress: View {
@State var percent = 0.0
var body: some View {
Capsule()
.fill(.white)
.frame(height: 20)
.overlay(
Capsule()
.stroke(.gray, lineWidth: 2.0)
)
.overlay(
GeometryReader { proxy in
Capsule()
.inset(by: 1)
.fill(.green)
.frame(width: proxy.size.width * percent)
.animation(.linear(duration: 3.0), value: percent)
}
)
.onTapGesture {
percent = 1.0
}
}
}
struct CapsuleProgressExample: View {
var body: some View {
VStack {
CapsuleProgress()
CapsuleProgress()
}
}
}