The Util Designer
SwiftUI 創建進度圈
xcode 13.3.1, swift 5.5, iOS 15.4
2022-08-09
進度圈在很多地方都會用到,這篇我們會講講怎樣用SwiftUI Animation簡單的創建進度圈。
首先先畫一個寬度為50的綠色的圓圈
struct CircleExample : View {
    var lineWidth = 50.0
    
    var body: some View {
        Circle()
            .inset(by: lineWidth/2.0)
            .stroke(lineWidth: lineWidth)
            .foregroundColor(.green)
            .background(
                Circle().foregroundColor(.white)
            )
    }
}
然後可以使用一個bool變量去trim(from:to)的to從0升到1。
struct CircleExample : View {
    var lineWidth = 50.0
    @State var animationFlag = false
    
    var body: some View {
        Circle()
            .inset(by: lineWidth/2.0)
            .trim(from: 0.0, to: animationFlag ? 1.0 : 0.0)
            .stroke(lineWidth: lineWidth)
            .foregroundColor(.green)
            .background(
                Circle().foregroundColor(.white)
            )
            .onTapGesture {
                animationFlag = true
            }
    }
}
當我們tap一下屏幕中間位置,綠色圓圈一下子就出現在屏幕上,並不是像進度條那樣慢慢畫成一個完整個圓圈。
SwiftUI提供了一個很簡單的方法,只要把需要的控制變量放在withAnimation中,就可以把與其有關的變量,比如to的值從0.0慢慢的變成1.0,從而達到動畫的效果。
代碼如下:
import SwiftUI

struct CircleExample : View {
    var lineWidth = 50.0
    @State var animationFlag = false
    
    var body: some View {
        Circle()
            .inset(by: lineWidth/2.0)
            .trim(from: 0.0, to: animationFlag ? 1.0 : 0.0)
            .stroke(lineWidth: lineWidth)
            .foregroundColor(.green)
            .background(
                Circle().foregroundColor(.white)
            )
            .onTapGesture {
                withAnimation {
                    animationFlag = true
                }
            }
    }
}
現在動畫很快,一下子就變成一個完整個圓圈,為了控制整個動畫的時間,我們可以使用animation方法,這個方法不但可以不同形式的動畫,還可以控制整個動畫的時間。
以下實作把整個動畫時間控制在2秒鐘,並使用了線性方式:
struct CircleExample : View {
    var lineWidth = 50.0
    @State var animationFlag = false
    
    var body: some View {
        Circle()
            .inset(by: lineWidth/2.0)
            .trim(from: 0.0, to: animationFlag ? 1.0 : 0.0)
            .stroke(lineWidth: lineWidth)
            .foregroundColor(.green)
            .background(
                Circle().foregroundColor(.white)
            )
            .animation(.linear(duration: 2), value: animationFlag)
            .onTapGesture {
                animationFlag = true
            }
    }
}