ios - 使用 SwiftUI,如何为饼图进度条制作动画

标签 ios xcode swiftui

我已经创建了显示饼图进度条的代码。我需要给这个进度条添加一个动画。我试过线性动画,但没有用。我被卡住了,不知道如何让它动画化。有人可以帮忙吗?这是代码。

import SwiftUI

struct PieProgress: View {
    @State var progress: Float

    var body: some View {
        GeometryReader { geometry in
            VStack(spacing:20) {
                HStack{
                    Text("0%")
                    Slider(value: self.$progress)
                    Text("100%")
                }.padding()
                Circle()
                    .stroke(Color.gray, lineWidth: 1)
                    .frame(width: geometry.size.width, height: geometry.size.width, alignment: .center)
                    .padding()
                    .overlay(
                        PieShape(progress: Double(self.progress))
                            .frame(width: geometry.size.width - 10, height: geometry.size.width - 10 , alignment: .center)
                            .foregroundColor(.blue)
                    )
            }
        }
    }
}

struct PieShape: Shape {
    var progress: Double = 0.0
    private let startAngle: Double = (Double.pi) * 1.5
    private var endAngle: Double {
        get {
            return self.startAngle + Double.pi * 2 * self.progress
        }
    }

    func path(in rect: CGRect) -> Path {
        var path = Path()
        let arcCenter =  CGPoint(x: rect.size.width / 2, y: rect.size.width / 2)
        let radius = rect.size.width / 2
        path.move(to: arcCenter)
        path.addArc(center: arcCenter, radius: radius, startAngle: Angle(radians: startAngle), endAngle: Angle(radians: endAngle), clockwise: false)
        path.closeSubpath()
        return path
    }
}

最佳答案

Xcode 13.4/iOS 15.5

更新过时的方法,现在没有硬编码

demo

Circle()
    .stroke(Color.gray, lineWidth: 1)
    .overlay(
        PieShape(progress: Double(self.progress))
            .padding(4)
            .foregroundColor(.blue)
    )
    .frame(maxWidth: .infinity)
    .animation(Animation.linear, value: progress) // << here !!
    .aspectRatio(contentMode: .fit)

Test code is here

原创

这是可能的方法(经过测试并适用于 Xcode 11.2/iOS 13.2):

  1. 您需要为您的形状指定animatableData,如下所示

    结构 PieShape:形状 { var 进度:Double = 0.0

     var animatableData: Double {
         get {
             self.progress
         }
         set {
             self.progress = newValue
         }
     }
     ...
    
  2. 然后给Circle添加动画

    圆圈() .stroke(Color.gray, lineWidth: 1) .frame(宽度:geometry.size.width,高度:geometry.size.width,对齐方式:.center) 。填充() 。覆盖( PieShape(进度:Double(self.progress)) .frame(宽度:geometry.size.width - 10,高度:geometry.size.width - 10,对齐方式:.center) .foregroundColor(.blue) ) .animation(Animation.linear)//<< 这里 !!

就是这样。为了测试(仅!),您可以在 PieProgress

中添加以下内容
.onAppear {
    DispatchQueue.main.asyncAfter(deadline: .now() + 10) {
        self.progress = 0.72
    }
}

注意:要将 PieProgress 用作重用组件,将 progress 设置为 @Binding 是合理的,以防万一。

关于ios - 使用 SwiftUI,如何为饼图进度条制作动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60258004/

相关文章:

iphone - Google Analytics 不显示对我的应用程序的跟踪

ios - 尝试为同一索引路径使多个单元格出队,这是 Swift 不允许的

ios - Foreach 如果所有字段都是 "0",返回一个 View

iOS 14 WidgetKit 可用内存

ios - BLE特性通知属性的本质是什么?

ios - UITableView和UISegmentedControl

objective-c - 如何从界面生成器访问窗口 View ?

python - PythonKit错误“找不到Python库。设置PYTHON_LIBRARY环境变量和Python库的路径”

ios - Facebook SDK 不是动态库

ios - 具有状态和绑定(bind)的 ForEach NavigationLink