繁体   English   中英

如何使用 SwiftUI 对 BezierPath 定义的自定义 cornerRadius 的更改进行动画处理?

[英]How can I animate changes to a BezierPath defined custom cornerRadius with SwiftUI?

我正在使用以下方法将圆角添加到 x 个角的视图中:

圆角 SwiftUI

extension View {
    func cornerRadius(_ radius: CGFloat, corners: UIRectCorner) -> some View {
        clipShape( RoundedCorner(radius: radius, corners: corners) )
    }
}

struct RoundedCorner: Shape {

    var radius: CGFloat = .infinity
    var corners: UIRectCorner = .allCorners

    func path(in rect: CGRect) -> Path {
        let path = UIBezierPath(roundedRect: rect, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
        return Path(path.cgPath)
    }
}

这非常有效。 不幸的是,当我将此视图设置为另一个没有任何圆角的 Frame 时,cornerRadius 没有动画。 所有其他动画工作正常。

为了说明这一点,以下显示了使用标准 .cornerRadius 修改器和使用上述扩展名使用自定义 .cornerRadius 修改器的拐角半径动画:

struct ContentView: View {
    
    @State var radius: CGFloat = 50

    var body: some View {
        VStack {
            Button {
                withAnimation(.easeInOut(duration: 2)) {
                    if radius == 50 {
                        radius = 0
                    } else {
                        radius = 50
                    }
                }
                
            } label: {
                Text("Change Corner Radius")
            }

            Color.red
                .frame(width: 100, height: 100)
                .cornerRadius(radius, corners: [.topLeft, .bottomRight])
            
            Color.blue
                .frame(width: 100, height: 100)
                .cornerRadius(radius)
        }
    }
}

在此处输入图片说明

问题出在RoundedCorner结构中。 它不是在考虑动画的情况下编写的。 虽然符合Shape协议的结构是可动画的,但如果没有var animatableData为系统提供了解如何为Shape设置动画的能力,它就不会动画。 我不知道为什么不需要实现它,因为它通常很简单,就像在这种情况下一样。

RoundedCorner结构更改为以下内容,它将按照您的意愿进行动画处理:

struct RoundedCorner: Shape {

    var radius: CGFloat
    var corners: UIRectCorner
    var animatableData: CGFloat {
        get { return radius }
        set { radius = newValue }
    }

    func path(in rect: CGRect) -> Path {
        let path = UIBezierPath(roundedRect: rect, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
        return Path(path.cgPath)
    }
}

在此处输入图片说明

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM