简体   繁体   English

有没有办法在 SwiftUI 中创建新的手势?

[英]Is there any way to create a new Gesture in SwiftUI?

SwiftUI is missing a Pan gesture (that is, both scale and offset), so I was trying to create one. SwiftUI 缺少​​平移手势(即缩放和偏移),所以我试图创建一个。 However, it appears that the Gesture struct depends on private classes.但是,似乎 Gesture 结构依赖于私有类。 For example:例如:

public struct PinchGesture: Gesture {

    public struct PinchGestureValue: Equatable {
        var scale: CGFloat
        var anchor: UnitPoint
        var offset: CGSize
        var isPinching: Bool
    }
    
    public typealias Value = PinchGestureValue
    public typealias Body = Never
    
    var minimumScaleDelta: CGFloat
    var minimumDistance: CGFloat
    var coordinateSpace: CoordinateSpace
    
    
    public init(minimumScaleDelta: CGFloat = 0.01, minimumDistance: CGFloat = 10, coordinateSpace: CoordinateSpace = .local) {
        self.minimumScaleDelta = minimumScaleDelta
        self.minimumDistance = minimumDistance
        self.coordinateSpace = coordinateSpace
    }
    
    public static func _makeGesture(gesture: _GraphValue<PinchGesture>, inputs: _GestureInputs) -> _GestureOutputs<PinchGestureValue> {
      // Unable to complete
    }

}

This code cannot be completed, as the _GraphValue, _GestureInputs, and _GestureOutputs are private.此代码无法完成,因为 _GraphValue、_GestureInputs 和 _GestureOutputs 是私有的。 Before I give in completely, I wanted to see if anyone has figured out a workaround.在我完全屈服之前,我想看看是否有人找到了解决方法。

SwiftUI provides a default implementation of _makeGesture : SwiftUI提供的默认实现_makeGesture

extension Gesture where Self.Value == Self.Body.Value {
  public static func _makeGesture(gesture: SwiftUI._GraphValue<Self>, inputs: SwiftUI._GestureInputs) -> SwiftUI._GestureOutputs<Self.Body.Value>
}

The difficulty here is the constraint Self.Value === Self.Body.Value .这里的困难是约束Self.Value === Self.Body.Value That means your gesture's body can't be declared to return some Gesture , because some Gesture can't satisfy the constraint (even if its Value would match).这意味着你的手势body不能被声明为返回some Gesture ,因为some Gesture不能满足约束(即使它的Value匹配)。 So you have to give body a specific type.所以你必须给body一个特定的类型。 The easiest solution is to use the AnyGesture type eraser:最简单的解决方案是使用AnyGesture类型的橡皮擦:

public struct PinchGesture: Gesture {

    ...

    public var body: AnyGesture<PinchGestureValue> {
        AnyGesture(
            DragGesture(minimumDistance: 0, coordinateSpace: .global)
               .map { PinchGestureValue($0) }
        )
    }
}

In this code, Swift can infer PinchGesture.Value = PinchGestureValue and PinchGesture.Body = AnyGesture<PinchGestureValue> .在这段代码中,Swift 可以推断出PinchGesture.Value = PinchGestureValuePinchGesture.Body = AnyGesture<PinchGestureValue> Then it can prove AnyGesture<PinchGestureValue>.Value == PinchGesture.Value , so it can use the default implementation of _makeGesture provided by SwiftUI.然后它可以证明AnyGesture<PinchGestureValue>.Value == PinchGesture.Value ,所以它可以使用_makeGesture提供的 _makeGesture 的默认实现。

Unfortunately, I doubt you can use this to create your PinchGesture .不幸的是,我怀疑您是否可以使用它来创建您的PinchGesture Ultimately, your body is still restricted to combining SwiftUI's primitive gestures, which don't give you access the current UIEvent or UITouch objects.最终,您的body仍然仅限于组合 SwiftUI 的原始手势,这不会让您访问当前的UIEventUITouch对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM