微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在 .animation() 期间访问 @Binding 的当前值

如何解决如何在 .animation() 期间访问 @Binding 的当前值

如何访问此动画属性 scaleAmount 的当前值?

struct ContentView: View {
    @State private var scaleAmount: CGFloat = 1

    var body: some View {
        vstack {
            Stepper("Scale amount",value: $scaleAmount.animation(),in: 1...5)
            Circle()
                    .fill(Color.red)
                    .frame(width: 50,height: 50)
                    .scaleEffect(scaleAmount)
                    .onChange(of: scaleAmount) { value in
                        print(value)
                    }
        }
    }
}

输出

2.0
3.0
4.0
5.0

这些是可动画属性的最终值 - 而不是用于动画的内插值。这些就是我需要的。

可以这样做吗?我还尝试将 .onChange 块替换为

                    .onChange(of: $scaleAmount.animation()) { value in
                        print(value)
                    }

但是编译器说 .animation() 调用返回的 Binding 必须符合 Equatable。

我还尝试将 Circle 视图分解为自定义视图,并只为其提供一个 CGFloat 来使用,然后动画就会发生。但是绘制圆圈的视图中没有绑定。这给出了与第一个代码片段相同的输出

struct ContentView: View {
    @State private var scaleAmount: CGFloat = 1

    var body: some View {
        vstack {
            Stepper("Scale amount",in: 1...5)
            MyCircle(scaleAmount: scaleAmount)
        }
    }
}

struct MyCircle: View {
    var scaleAmount: CGFloat

    var body: some View {
        print(scaleAmount)
        return Circle()
                .fill(Color.red)
                .frame(width: 50,height: 50)
                .scaleEffect(scaleAmount)
    }

}

那么,问题又来了:是否可以在动画中获取 scaleAmount 属性的当前值?

解决方法

//
// Created by Eric Lightfoot on 2021-06-24.
//

import SwiftUI

/// Use .onBody(observedValue:onBody:) by passing an
/// animatable property along with a closure to execute
/// whenever that property is changed throughout the
/// animation
/// ---
// struct ContentView: View {
//    @State private var scaleAmount: CGFloat = 1
//    @State var scaleText: String = "1.000"
//
//    var body: some View {
//        VStack {
//            Stepper("Scale amount",value: $scaleAmount.animation(),in: 1...5)
//            ZStack {
//                Circle()
//                        .fill(Color.red)
//                        .frame(width: 50,height: 50)
//                Text(scaleText)
//                        .onBody(for: scaleAmount,onBody: { scaleText = "\($0)" })
//             }
//                    .scaleEffect(scaleAmount)
//         }
//     }
// }
/// ---

struct AnimationProgressObserverModifier<Value>: AnimatableModifier where Value: VectorArithmetic {

    /// Some experimenting led to observing the behaviour
    /// that wrapping the observedValue with animatableData
    /// (to conform to the protocol) caused this property
    /// to be set continuously during the animation,instead
    /// of only at the end
    var animatableData: Value {
        get {
            observedValue
        }
        set {
            observedValue = newValue
            runCallbacks()
        }
    }

    /// The animatable property to be observed
    /// passed in at init
    private var observedValue: Value

    /// The block to execute on each animation progress
    /// update
    private var onBody: (Value) -> Void

    init (observedValue: Value,onBody: @escaping (Value) -> Void) {
        self.onBody = onBody
        self.observedValue = observedValue
    }

    /// Run the onBody block provided at init
    /// specifically passing animatable data,/// NOT observedValue
    private func runCallbacks () {
        DispatchQueue.main.async {
            onBody(animatableData)
        }
    }

    func body (content: Content) -> some View {
        /// No modification to view content
        content
    }
}

extension View {
    /// Convenience method on View
    func onBody<Value: VectorArithmetic> (for value: Value,onBody: @escaping (Value) -> Void)
                    -> ModifiedContent<Self,AnimationProgressObserverModifier<Value>> {
        modifier(AnimationProgressObserverModifier(observedValue: value,onBody: onBody))
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?