Animating Text in Swift UI

前端 未结 2 1025
说谎
说谎 2021-02-08 04:16

How would it be possible to animate Text or TextField views from Swift UI?

By animation I mean, that when the text changes it will \"count up\

2条回答
  •  闹比i
    闹比i (楼主)
    2021-02-08 04:55

    There is a pure way of animating text in SwiftUI. Here's an implementation of your progress indicator using the AnimatableModifier protocol in SwiftUI:

    I've written an extensive article documenting the use of AnimatableModifier (and its bugs). It includes the progress indicator too. You can read it here: https://swiftui-lab.com/swiftui-animations-part3/

    struct ContentView: View {
        @State private var percent: CGFloat = 0
    
        var body: some View {
            VStack {
                Spacer()
                Color.clear.overlay(Indicator(pct: self.percent))
    
                Spacer()
                HStack(spacing: 10) {
                    MyButton(label: "0%", font: .headline) { withAnimation(.easeInOut(duration: 1.0)) { self.percent = 0 } }
    
                    MyButton(label: "27%", font: .headline) { withAnimation(.easeInOut(duration: 1.0)) { self.percent = 0.27 } }
    
                    MyButton(label: "100%", font: .headline) { withAnimation(.easeInOut(duration: 1.0)) { self.percent = 1.0 } }
                }
            }.navigationBarTitle("Example 10")
        }
    }
    
    struct Indicator: View {
        var pct: CGFloat
    
        var body: some View {
            return Circle()
                .fill(LinearGradient(gradient: Gradient(colors: [.blue, .purple]), startPoint: .topLeading, endPoint: .bottomTrailing))
                .frame(width: 150, height: 150)
                .modifier(PercentageIndicator(pct: self.pct))
        }
    }
    
    struct PercentageIndicator: AnimatableModifier {
        var pct: CGFloat = 0
    
        var animatableData: CGFloat {
            get { pct }
            set { pct = newValue }
        }
    
        func body(content: Content) -> some View {
            content
                .overlay(ArcShape(pct: pct).foregroundColor(.red))
                .overlay(LabelView(pct: pct))
        }
    
        struct ArcShape: Shape {
            let pct: CGFloat
    
            func path(in rect: CGRect) -> Path {
    
                var p = Path()
    
                p.addArc(center: CGPoint(x: rect.width / 2.0, y:rect.height / 2.0),
                         radius: rect.height / 2.0 + 5.0,
                         startAngle: .degrees(0),
                         endAngle: .degrees(360.0 * Double(pct)), clockwise: false)
    
                return p.strokedPath(.init(lineWidth: 10, dash: [6, 3], dashPhase: 10))
            }
        }
    
        struct LabelView: View {
            let pct: CGFloat
    
            var body: some View {
                Text("\(Int(pct * 100)) %")
                    .font(.largeTitle)
                    .fontWeight(.bold)
                    .foregroundColor(.white)
            }
        }
    }
    

提交回复
热议问题