【发布时间】:2022-01-21 17:13:49
【问题描述】:
我的目标是在偏移更改动画完成时实现回调。所以,我在网上找到了一个解决方法,它使用AnimatableModifier 来检查animatableData 何时等于目标值。
struct OffsetAnimation: AnimatableModifier{
typealias T = CGFloat
var animatableData: T{
get { value }
set {
value = newValue
print("animating \(value)")
if watchForCompletion && value == targetValue {
DispatchQueue.main.async { [self] in onCompletion() }
}
}
}
var watchForCompletion: Bool
var value: T
var targetValue: T
init(value: T, watchForCompletion: Bool, onCompletion: @escaping()->()){
self.targetValue = value
self.value = value
self.watchForCompletion = watchForCompletion
self.onCompletion = onCompletion
}
var onCompletion: () -> ()
func body(content: Content) -> some View {
return content.offset(x: 0, y: value).animation(nil)
}
}
struct DemoView: View {
@State var offsetY: CGFloat = .zero
var body: some View {
Rectangle().frame(width: 100, height: 100, alignment: .center)
.modifier(
OffsetAnimation(value: offsetY,
watchForCompletion: true,
onCompletion: {print("translation complete")}))
.onAppear{
withAnimation{ offsetY = 100 }
}
}
}
但事实证明AnimatableModifier 现在已被弃用。而且我找不到它的替代品。
我知道GeometryEffect 将适用于这种偏移更改的情况,您可以使用ProjectionTransform 来解决问题。但我更关心的是官方推荐“直接使用Animatable”。
说真的,我可以在网上找到有关Animatable 协议的教程都使用了Shape 结构的示例,它隐式地实现了Animatable 协议。我使用Animatable 协议即兴创作的以下代码甚至没有做“动画”。
struct RectView: View, Animatable{
typealias T = CGFloat
var animatableData: T{
get { value }
set {
value = newValue
print("animating \(value)")
}
}
var value: T
var body: some View{
Rectangle().frame(width: 100, height: 100, alignment: .center)
.offset(y:value).animation(nil)
}
}
struct DemoView: View{
@State var offsetY: CGFloat = .zero
var body: some View {
RectView(value: offsetY)
.onAppear{
withAnimation{ offsetY = 100 }
}
}
}
感谢您的阅读,也许还有即将到来的答案!
【问题讨论】:
-
第二个例子工作正常。 Xcode 13.2 / iOS 15.2。模拟器/设备。
-
似乎第二个示例适用于 iOS 15 但不适用于 iOS 14
标签: ios animation swiftui deprecated