SwiftUI 創作圓點工作指示器
xcode 13.4.1, swift 5.5, iOS 15.4
2022-08-16
使用簡單的動畫就可以創作以下的圓點工作指示器。
1. 首先先創建一個綠色圓點。
import SwiftUI
struct DotLoadingExample : View {
var body: some View {
Circle()
.foregroundColor(.green)
.frame(width: 20)
}
}
2. 然後使用scaleEffect來設置圓點的大小:
import SwiftUI
struct DotLoadingExample : View {
var body: some View {
Circle()
.foregroundColor(.green)
.frame(width: 20)
.scaleEffect(0.5)
}
}
3. 再來就是試試用animation來作圓點大小的動畫:
import SwiftUI
struct DotLoadingExample : View {
@State var scaleEffect : CGFloat = 0.01
var body: some View {
Circle()
.foregroundColor(.green)
.frame(width: 20)
.scaleEffect(scaleEffect)
.animation(.linear(duration: 0.5).repeatForever(autoreverses: true), value: scaleEffect)
.onAppear {
scaleEffect = 1.0
}
}
}
4. 現在把小圓點包裝成一個元件,并同時放置兩個小圓點元件,看看效果。
import SwiftUI
struct DotAnimation : View {
@State var scaleEffect : CGFloat = 0.01
var body: some View {
Circle()
.foregroundColor(.green)
.frame(width: 20)
.scaleEffect(scaleEffect)
.animation(.linear(duration: 0.5).repeatForever(autoreverses: true), value: scaleEffect)
.onAppear {
scaleEffect = 1.0
}
}
}
struct DotLoadingExample : View {
var body: some View {
HStack {
DotAnimation()
DotAnimation()
}
}
}
5. 上面看到兩個小圓點同時進行在作相同的變化,為了讓每個小圓點的變化有先後順序的感覺,在每個小圓點開始動畫之前設置一個延遲時間值,避免所有小圓點一起作相同的變化。
import SwiftUI
struct DotAnimation : View {
let delay : Double
@State var scaleEffect : CGFloat = 0.01
var body: some View {
Circle()
.foregroundColor(.green)
.frame(width: 20)
.scaleEffect(scaleEffect)
.animation(.linear(duration: 0.5).repeatForever(autoreverses: true), value: scaleEffect)
.onAppear {
DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
scaleEffect = 1.0
}
}
}
}
struct DotLoadingExample : View {
var body: some View {
HStack {
DotAnimation(delay: 0.1)
DotAnimation(delay: 0.2)
}
}
}
6. 最後把9個小圓點放在一起,每個小圓點相隔0.1秒才開始動畫,實作如下:
import SwiftUI
struct DotAnimation : View {
let delay : Double
@State var scaleEffect : CGFloat = 0.01
var body: some View {
Circle()
.foregroundColor(.green)
.frame(width: 20)
.scaleEffect(scaleEffect)
.animation(.linear(duration: 0.5).repeatForever(autoreverses: true), value: scaleEffect)
.onAppear {
DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
scaleEffect = 1.0
}
}
}
}
struct DotLoadingExample : View {
var body: some View {
HStack {
ForEach(1...9, id:\.self) { index in
DotAnimation1(delay: 0.1 * CGFloat(index))
}
}
}
}