ForceTouchGestureRecognizer.swift 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. #if canImport(UIKit)
  2. import UIKit.UIGestureRecognizerSubclass
  3. import RxSwift
  4. import RxCocoa
  5. public class ForceTouchGestureRecognizer: UIGestureRecognizer {
  6. private var touch: UITouch?
  7. public var force: CGFloat {
  8. touch?.force ?? 0
  9. }
  10. public var maximumPossibleForce: CGFloat {
  11. touch?.maximumPossibleForce ?? 0
  12. }
  13. public var absoluteFractionCompleted: CGFloat {
  14. guard maximumPossibleForce > 0 else {
  15. return 0
  16. }
  17. return force / maximumPossibleForce
  18. }
  19. public var minimumFractionCompletedRequired: CGFloat = 0
  20. public var maximumFractionCompletedRequired: CGFloat = 1
  21. public var fractionCompleted: CGFloat {
  22. lerp(
  23. mapMin: minimumFractionCompletedRequired, to: 0,
  24. mapMax: maximumFractionCompletedRequired, to: 1,
  25. value: absoluteFractionCompleted
  26. )
  27. }
  28. public override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
  29. super.touchesBegan(touches, with: event)
  30. guard state == .possible else { return }
  31. guard touch == nil else { return }
  32. guard let first = touches.first(where: { $0.phase == .began }) else { return }
  33. touch = first
  34. state = .began
  35. }
  36. public override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
  37. super.touchesMoved(touches, with: event)
  38. guard let touch = touch, touches.contains(touch), touch.phase == .moved else { return }
  39. state = .changed
  40. }
  41. public override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent) {
  42. super.touchesEnded(touches, with: event)
  43. guard let touch = touch, touches.contains(touch), touch.phase == .ended else { return }
  44. self.touch = nil
  45. state = .ended
  46. }
  47. public override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent) {
  48. super.touchesCancelled(touches, with: event)
  49. guard let touch = touch, touches.contains(touch), touch.phase == .cancelled else { return }
  50. self.touch = nil
  51. state = .cancelled
  52. }
  53. }
  54. public typealias ForceTouchConfiguration = Configuration<ForceTouchGestureRecognizer>
  55. public typealias ForceTouchControlEvent = ControlEvent<ForceTouchGestureRecognizer>
  56. public typealias ForceTouchObservable = Observable<ForceTouchGestureRecognizer>
  57. extension Factory where Gesture == RxGestureRecognizer {
  58. /**
  59. Returns an `AnyFactory` for `ForceTouchGestureRecognizer`
  60. - parameter configuration: A closure that allows to fully configure the gesture recognizer
  61. */
  62. public static func forceTouch(configuration: ForceTouchConfiguration? = nil) -> AnyFactory {
  63. make(configuration: configuration).abstracted()
  64. }
  65. }
  66. extension Reactive where Base: RxGestureView {
  67. /**
  68. Returns an observable `ForceTouchGestureRecognizer` events sequence
  69. - parameter configuration: A closure that allows to fully configure the gesture recognizer
  70. */
  71. public func forceTouchGesture(configuration: ForceTouchConfiguration? = nil) -> ForceTouchControlEvent {
  72. gesture(make(configuration: configuration))
  73. }
  74. }
  75. extension ObservableType where Element: ForceTouchGestureRecognizer {
  76. /**
  77. Maps the observable `GestureRecognizer` events sequence to an observable sequence of force values.
  78. */
  79. public func asForce() -> Observable<CGFloat> {
  80. self.map { $0.force }
  81. }
  82. public func when(fractionCompletedExceeds threshold: CGFloat) -> Observable<Element> {
  83. let source = asObservable()
  84. return source
  85. .when(.began)
  86. .flatMapLatest { [unowned source] _ in
  87. source
  88. .when(.changed)
  89. .filter {
  90. if threshold == 0 {
  91. return $0.fractionCompleted > threshold
  92. } else {
  93. return $0.fractionCompleted >= threshold
  94. }
  95. }
  96. .take(1)
  97. }
  98. }
  99. }
  100. private func lerp<T : FloatingPoint>(_ v0: T, _ v1: T, _ t: T) -> T {
  101. v0 + (v1 - v0) * t
  102. }
  103. private func lerp<T : FloatingPoint>(mapMin: T, to min: T, mapMax: T, to max: T, value: T) -> T {
  104. lerp(min, max, (value - mapMin) / (mapMax - mapMin))
  105. }
  106. #endif