我在一个带有动画偏移量的堆栈中有一些按钮.由于某些原因,对于动画偏移按钮,它们是不可点击的.当偏移量约为250左右时,这些按钮似乎可以点击一秒钟,然后在低于该值的偏移量处再次变为不可点击……任何帮助都是非常感谢的!

struct ContentView: View {
    @State var offset: CGFloat = -300
    var body: some View {
        HStack {
            Button(action: {
                print("clickable")
            }, label: {
                Text("Click me")
            })
            Button(action: {
                print("clickable2")
            }, label: {
                Text("Click me2")
            })
            Button(action: {
                print("clickable3")
            }, label: {
                Text("Click me3")
            })
        }.offset(x: offset)
        .onAppear(perform: {
            withAnimation(.linear(duration: 10).repeatForever()) {
                offset = 300
            }
        })
    }
}   

推荐答案

How Offsetting works?

首先,这是一种expected行为.因为当你用offset,SwiftUI shifts the displayed contents的时候.简而言之,这意味着SwiftUI shifts the 104 itself

既然是onTapGesture only recognizes the touches on the view,这也解释了为什么您可以click到偏移视图

offset

How Animation Works?

在您的代码中,您首先是offsetting/View,然后是应用动画.当您使用withAnimationSwiftUI recomputes the view's body with provided animation,但请记住,它does not会更改预先应用于View的任何内容.

animation

请注意当进入红色矩形时,Click Me是如何变为可点击的.这是因为红色矩形表示Click Me按钮的最终偏移量.(因此它只是一个占位符)

所以View本身和offset必须匹配,因为当您首先偏移您的视图时,SwiftUI需要您的视图there来触发点击手势.

Possible solution

既然我们了解了问题,我们就能解决它.所以,问题发生是因为我们是offsetting our view first, then applying animation岁.

因此,如果这不起作用,一种可能的解决方案是使用动画以周期为单位更改偏移量(例如,每个周期使用0.1秒),因为这将导致SwiftUI在每次更改偏移量时重新定位视图,因此应该不会发生奇怪的错误.

代码:

struct ContentView: View {
    @State private var increment : CGFloat = 1
    @State private var offset : CGFloat = 0
    var body: some View {
        ZStack {
            Button("Click Me") {
                print("Click")
            }
            .fontWeight(.black)
        }
        .tappableOffsetAnimation(offset: $offset, animation: .linear, duration: 5, finalOffsetAmount: 300)
        
    }
}

struct TappableAnimationModifier : ViewModifier {
    @Binding var offset : CGFloat

    var duration : Double
    var finalOffsetAmount : Double
    var animation : Animation
    let timer = Timer.publish(every: 0.1, on: .main, in: .common).autoconnect()
    
    func body(content: Content) -> some View {
        content
            .animation(animation, value: offset)
            .offset(x: offset)
            .onReceive(timer) { input in
                /*
                 * a simple math here, we're dividing duration by 0.1 because our timer gets triggered
                 * in every 0.1 seconds, so dividing this result will always produce the
                 * proper value to finish offset animation in `x` seconds
                 * example: 300 / (5 / 0.1) = 300 / 50 = 6 increment per 0.1 second
                 */
                if (offset >= finalOffsetAmount) {
                    // you could implement autoReverses by not canceling the timer here
                    // and substracting finalOffsetAmount / (duration / 0.1) until it reaches zero
                    // then you can again start incrementing it.
                    timer.upstream.connect().cancel()
                    return
                }
                offset += finalOffsetAmount / (duration / 0.1)
            }
    }
}
extension View {
    func tappableOffsetAnimation(offset: Binding<CGFloat>, animation: Animation, duration: Double, finalOffsetAmount: Double) -> some View {
        modifier(TappableAnimationModifier(offset: offset, duration: duration, finalOffsetAmount: finalOffsetAmount, animation: animation))
    }
}

下面是它看起来的样子:

solution

您的视图正在运行,请将其捕捉到x)

Swift相关问答推荐

RealityKit如何获得两个相对大小相同的ModelEntity?

查找数组中 ** 元素 ** 的属性的最小值和最大值

不能将符合协议的SWIFT类的实例分配给需要该协议的Objective-C属性

使 tabview 垂直将视图移动到右侧 swift ui

在Equatable上引用运算符函数==要求Dictionary.Values符合Equatable

在 RealityKit 中查找特定模型的 findEntity(named:) 方法的替代方法?

如何让默认函数参数引用另一个函数参数?

如何将视图添加到多行文本视图的末尾?

将内容与工作表顶部而不是中间对齐

如何使 SwiftUI Picker 换行文本

Vapor 4,如何按外键过滤?

.onTapGesture 不适用于 Stepper,仅适用于其文本

单元测试和私有变量

swift:修改字典中的数组

Xcode 7.3 Swift 的语法高亮和代码完成问题

从 NSData 对象在 Swift 中创建一个数组

'#selector' 的参数不引用 '@objc' 方法、属性或初始化程序

Swift 3:小数到 Int

如何从 UITableViewCell 类中引用 UITableViewController?

将 UIImage 剪成圆形