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

Posted

技术标签:

【中文标题】有没有办法在 SwiftUI 中创建一个新的手势?【英文标题】:Is there any way to create a new Gesture in SwiftUI? 【发布时间】:2020-09-27 14:15:22 【问题描述】:

SwiftUI 缺少​​平移手势(即缩放和偏移),所以我试图创建一个。但是,Gesture 结构似乎依赖于私有类。例如:

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
    


此代码无法完成,因为 _GraphValue、_GestureInputs 和 _GestureOutputs 是私有的。在我完全放弃之前,我想看看是否有人找到了解决方法。

【问题讨论】:

你有没有运气解决这个问题?我也想创建一个新的手势。 不-抱歉。目前看来没有办法做到这一点。为了这个特殊的需要,我最终创建了一个全新的 ScrollView...☹️ 【参考方案1】:

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>

这里的困难是约束Self.Value === Self.Body.Value。这意味着您的手势body 不能被声明为返回some Gesture,因为some Gesture 不能满足约束(即使它的Value 会匹配)。所以你必须给body一个特定的类型。最简单的解决方案是使用AnyGesture 类型的橡皮擦:

public struct PinchGesture: Gesture 

    ...

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

在这段代码中,Swift 可以推断出PinchGesture.Value = PinchGestureValuePinchGesture.Body = AnyGesture&lt;PinchGestureValue&gt;。那么它可以证明AnyGesture&lt;PinchGestureValue&gt;.Value == PinchGesture.Value,所以它可以使用SwiftUI提供的_makeGesture的默认实现。

不幸的是,我怀疑你可以用它来创建你的PinchGesture。最终,您的 body 仍然仅限于组合 SwiftUI 的原始手势,这无法让您访问当前的 UIEventUITouch 对象。

【讨论】:

以上是关于有没有办法在 SwiftUI 中创建一个新的手势?的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI - 有没有办法在不覆盖子视图的任何手势的情况下向视图添加手势?

有没有办法在 SwiftUI 中复制手势或处理它们并将它们传递给子视图?

SWIFTUI:- 有没有办法在滚动滚动视图时关闭弹跳?

在 SwiftUI DocumentGroup macOS 中创建并打开一个新文档

跨多个子视图的 SwiftUI 拖动手势

如何在 swiftUI 中创建具有多列的列表?