gpt4 book ai didi

ios - 如何在动画期间使按钮处于非事件状态

转载 作者:行者123 更新时间:2023-12-05 09:32:10 25 4
gpt4 key购买 nike

我想在动画完成之前停用按钮。我希望它在动画结束时处于事件状态。

我写了以下内容,但没有用。它会立即激活。

import SwiftUI

struct ContentView: View {
@State private var scale: CGFloat = 1
@State private var isDisable = false

var body: some View {
VStack {
Button(
action: {
isDisable = true
withAnimation(
.linear(duration: 1)
) {
scale = scale - 0.1
isDisable = false
}
},
label: {
Text("Tap Me")
}
)
.disabled(
isDisable
)
RectangleView().scaleEffect(
scale
)
}
}
}

struct RectangleView: View {
var body: some View {
Rectangle().fill(
Color.blue
)
.frame(
width:200,
height: 150
)
}
}

struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}

最佳答案

SwiftUI 动画没有完成处理程序,但您可以监视动画属性的状态并监听对其的更改。这可以满足您的需要,并且与动画的时间无关

SwiftUI 具有 AnimatableModifier,您可以使用它来创建一个在动画完成时调用函数的修饰符。

你可以在withAnimation completion callback with animatable modifiers看到这方面的解释。

struct ContentView: View {
@State private var scale: CGFloat = 1
@State private var isDisable = false

var body: some View {
VStack {
Button(
action: {
self.isDisable = true
withAnimation(
.linear(duration: 1)
) {
scale = scale - 0.1
}
},
label: {
Text("Tap Me")
}
)
.disabled(
isDisable
)
RectangleView()
.scaleEffect(scale)
.onAnimationCompleted(for: scale) {
isDisable = false
}
}
}
}

struct RectangleView: View {
var body: some View {
Rectangle().fill(
Color.blue
)
.frame(
width:200,
height: 150
)
}
}

/// An animatable modifier that is used for observing animations for a given animatable value.
struct AnimationCompletionObserverModifier<Value>: AnimatableModifier where Value: VectorArithmetic {

/// While animating, SwiftUI changes the old input value to the new target value using this property. This value is set to the old value until the animation completes.
var animatableData: Value {
didSet {
notifyCompletionIfFinished()
}
}

/// The target value for which we're observing. This value is directly set once the animation starts. During animation, `animatableData` will hold the oldValue and is only updated to the target value once the animation completes.
private var targetValue: Value

/// The completion callback which is called once the animation completes.
private var completion: () -> Void

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

/// Verifies whether the current animation is finished and calls the completion callback if true.
private func notifyCompletionIfFinished() {
guard animatableData == targetValue else { return }

/// Dispatching is needed to take the next runloop for the completion callback.
/// This prevents errors like "Modifying state during view update, this will cause undefined behavior."
DispatchQueue.main.async {
self.completion()
}
}

func body(content: Content) -> some View {
/// We're not really modifying the view so we can directly return the original input value.
return content
}
}

extension View {

/// Calls the completion handler whenever an animation on the given value completes.
/// - Parameters:
/// - value: The value to observe for animations.
/// - completion: The completion callback to call once the animation completes.
/// - Returns: A modified `View` instance with the observer attached.
func onAnimationCompleted<Value: VectorArithmetic>(for value: Value, completion: @escaping () -> Void) -> ModifiedContent<Self, AnimationCompletionObserverModifier<Value>> {
return modifier(AnimationCompletionObserverModifier(observedValue: value, completion: completion))
}
}

关于ios - 如何在动画期间使按钮处于非事件状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68396027/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com