You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

93 lines
3.0 KiB

import UIKit.UIGestureRecognizerSubclass
import RxSwift
import RxCocoa
@available(iOS 9.0, *)
public class ForceTouchGestureRecognizer: UIGestureRecognizer {
public var numberOfTouchesRequired: Int = 1
public private(set) var force: CGFloat = 0
public private(set) var maximumPossibleForce: CGFloat = 0
public var fractionCompleted: CGFloat {
guard maximumPossibleForce > 0 else {
return 0
}
return force / maximumPossibleForce
}
public override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
super.touchesBegan(touches, with: event)
state = .began
setForce(for: touches)
}
public override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
super.touchesMoved(touches, with: event)
state = .changed
setForce(for: touches)
}
public override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent) {
super.touchesEnded(touches, with: event)
state = .ended
setForce(for: touches)
}
private func setForce(for touches: Set<UITouch>) {
guard touches.count == numberOfTouchesRequired, let touch = touches.first else {
state = .failed
return
}
force = Array(touches)[1...]
.lazy
.map { $0.force}
.reduce(touch.force, +) / CGFloat(touches.count)
maximumPossibleForce = Array(touches)[1...]
.lazy
.map { $0.maximumPossibleForce}
.reduce(touch.maximumPossibleForce, +) / CGFloat(touches.count)
}
}
@available(iOS 9.0, *)
public typealias ForceTouchConfiguration = Configuration<ForceTouchGestureRecognizer>
@available(iOS 9.0, *)
public typealias ForceTouchControlEvent = ControlEvent<ForceTouchGestureRecognizer>
@available(iOS 9.0, *)
public typealias ForceTouchObservable = Observable<ForceTouchGestureRecognizer>
@available(iOS 9.0, *)
extension Factory where Gesture == GestureRecognizer {
/**
Returns an `AnyFactory` for `ForceTouchGestureRecognizer`
- parameter configuration: A closure that allows to fully configure the gesture recognizer
*/
public static func forceTouch(configuration: ForceTouchConfiguration? = nil) -> AnyFactory {
return make(configuration: configuration).abstracted()
}
}
@available(iOS 9.0, *)
extension Reactive where Base: View {
/**
Returns an observable `ForceTouchGestureRecognizer` events sequence
- parameter configuration: A closure that allows to fully configure the gesture recognizer
*/
public func forceTouchGesture(configuration: ForceTouchConfiguration? = nil) -> ForceTouchControlEvent {
return gesture(make(configuration: configuration))
}
}
@available(iOS 9.0, *)
extension ObservableType where Element: ForceTouchGestureRecognizer {
/**
Maps the observable `GestureRecognizer` events sequence to an observable sequence of force values.
*/
public func asForce() -> Observable<CGFloat> {
return self.map { $0.force }
}
}