SwiftUI交易:根据外部状态制作一个按钮,使其动画化或静止

myzjeezk  于 2023-06-04  发布在  Swift
关注(0)|答案(1)|浏览(163)

我尝试创建一个视图,它根据另一个视图的状态有条件地进行动画(永远重复)。
下面的按钮可以在一个视图中完成所有操作...但这种状态都是内部的。我希望它是“外部的”。

struct ButtonBouncerView: View {
    @State var active: Bool = false

    var body: some View {
        Circle()
            .scaleEffect(active ? 1.08: 1)
            .animation(Animation.default.repeatForever(autoreverses: true), value: active)
            .frame(width: 100, height: 100)
            .onTapGesture {
                useTransaction()
            }
            .onAppear {
                active = true
            }
    }

    func useTransaction() {
        var transaction = Transaction()
        transaction.disablesAnimations = active ? true : false

        withTransaction(transaction) {
            withAnimation {
                active.toggle()
            }
        }
    }
}

我试着这样做,使用Transactions API。然而,这只是有做奇怪的动画的效果,当我点击,基本上做某种奇怪的摆动一样的议案。

struct OutsideControllableButtonView: View {
    @State private var active: Bool = false

    var body: some View {
        VStack {
            OutsideControllableButtonScaler(active: $active)
            Button(action: { // CONTROLLER BUTTON!
                active.toggle()
            }) {
                Text("Control Button")
            }
            .padding()
            .background(Color.green)
            .foregroundColor(.white)
        }
    }
}

struct OutsideControllableButtonScaler: View {
    // When Active, the button
    @Binding var active: Bool

    var body: some View {
        Circle()
            .scaleEffect(active ? 1.08: 1)
            .animation(Animation.default.repeatForever(autoreverses: true), value: active)
            .frame(width: 100, height: 100)
            .onChange(of: active) { newValue in
                var transaction = Transaction(animation: newValue ? Animation.default.repeatForever(autoreverses: true) : nil)
                transaction.disablesAnimations = true
                withTransaction(transaction) {
                    self.active = newValue
                }
            }
    }
}

有什么办法解决吗?

ev7lccsx

ev7lccsx1#

你可以做一些类似下面的事情,在这里你设置你想要使用的基于active的动画。我不相信你可以通过设置为零来停止repeatForever动画,你实际上需要将其更新为默认值...
或者,您可以在Animation上编写一个扩展,使其更干净/可重用。但在快速测试中,下面的开始和停止动画,我相信你正在尝试这样做。

struct OutsideControllableButtonView: View {
    @State private var active: Bool = false
    
    var body: some View {
        VStack {
            OutsideControllableButtonScaler(active: $active)
            Button(action: { // CONTROLLER BUTTON!
                self.active.toggle()
            }) {
                Text("Control Button")
            }
            .padding()
            .background(Color.green)
            .foregroundColor(.white)
        }
    }
}

struct OutsideControllableButtonScaler: View {
    // When Active, the button
    @Binding var active: Bool
    
    var body: some View {
        Circle()
            .scaleEffect(active ? 1.08 : 1)
            .animation(active ? Animation.default.repeatForever(autoreverses: true) : .default, value: active)
            .frame(width: 100, height: 100)
    }
}

相关问题