如何对子视图进行绑定动画

时间:2020-05-30 03:54:32

标签: ios swift swiftui

对于为什么此代码无法按预期工作的原因有些困惑。

一些通用的动画视图:

struct SomeAnimatableView: View, Animatable {
    var percent: Double

    var body: some View {
        GeometryReader { geo in
            ZStack {
                Rectangle()
                    .fill(Color.blue)
                    .frame(height: 120)
                Rectangle()
                    .fill(Color.red)
                    .frame(width: geo.size.width * CGFloat(self.percent), height: 116)
            }
            .frame(width: geo.size.width, height: geo.size.height)
        }
    }

    var animatableData: Double {
        set { percent = newValue }
        get { percent }
    }
}

包含上述动画视图的视图:

struct ProgressRectangle: View {
    @Binding var percent: Double

    var body: some View {
        SomeAnimatableView(percent: percent)
    }
}

最后一个视图,将其视为父视图:

struct ContentView: View {
    @State var percent: Double

    var body: some View {
        VStack {
            ProgressRectangle(percent: $percent.animation())
            Text("Percent: \(percent * 100)")
        }
        .onTapGesture {
            self.percent = 1
        }
    }
}

问题⚠️为什么进度没有动画? $percent.animation()是否应该引起动画?很多问题...

修复?:

    .onTapGesture {
        withAnimation {
            self.percent = 1
        }
    }

但是,这实际上并不能解决问题,也无法回答为什么绑定没有动画的问题。因为这似乎也可以使整个视图动起来,所以在此示例中,请注意将其宽度设置为动画的按钮:

An animated image of a progress rectangle growing, starting at the center and expanding outwards towards the right and left. At the bottom, a label with the words: Percent. Followed by the current percent in the animation. The animation loops back to the start when reaching the edges.

有什么想法吗?

1 个答案:

答案 0 :(得分:2)

这是有效的解决方案。使用Xcode 11.4 / iOS 13.4进行了测试

demo

@State var percent: Double = .zero
var body: some View {
    VStack {
        ProgressRectangle(percent: $percent)
            .animation(.default)            // << place here !!
            .onTapGesture {
                    self.percent = self.percent == .zero ? 1 : .zero
            }
        Text("Percent: \(percent * 100)")
    }
}