I need to reuse the pangesture methods for all my views, because i don't want to repeat the methods in all the views.
So, i want to create a generic UIPanGestureRecognizer class to register the view and call the delegate methods to respective view.
Actually, i have tried but getting some issue. So, guide me with any suggestion or references.
Ok, here is my code,
@objc protocol PanGestureRecognizerDelegate: UIGestureRecognizerDelegate{
/// Called when the pan gesture recognizer starts.
@objc optional func panGestureRecognizer(didStart gestureRecognizer: PanGestureRecognizer)
/// Called when the pan gesture recognizer updates.
@objc optional func panGestureRecognizer(didUpdate gestureRecognizer: PanGestureRecognizer)
/// Called when the pan gesture recognizer cancels. A pan gesture recognizer may cancel if its translation or velocity in `initialDirection` is less than the value of `minimumTranslation` or `minimumVelocity`, respectively.
@objc optional func panGestureRecognizer(didCancel gestureRecognizer: PanGestureRecognizer)
/// Called when the pan gesture recognizer finishes. A pan gesture recognizer may finish if its translation and velocity in `initialDirection` are greater than or equal to the value of `minimumTranslation` or `minimumVelocity`, respectively.
@objc optional func panGestureRecognizer(didFinish gestureRecognizer: PanGestureRecognizer)
}
class PanGestureRecognizer: UIPanGestureRecognizer {
public enum Direction {
/// The pan gesture recognizer's touches move upwards.
case up
/// The pan gesture recognizer's touches move leftwards.
case left
/// The pan gesture recognizer's touches move downwards.
case down
/// The pan gesture recognizer's touches move rightwards.
case right
}
@IBInspectable open var minimumTranslation: CGFloat = 0.0
/// Minimum velocity (in `initialDirection`) required for the gesture to finish. Defaults to `0.0`.
@IBInspectable open var minimumVelocity: CGFloat = 0.0
// MARK: Internal variables
/// The current location in `view` when the pan gesture recognizer begins. Defaults to `nil`. Resets to `nil` when `reset()` is called.
open fileprivate(set) var initialLocation: CGPoint?
/// The current direction in `view` when the pan gesture recognizer begins. Defaults to `nil`. Resets to `nil` when `reset()` is called.
open fileprivate(set) var initialDirection: Direction?
// MARK: Delegation
open override var delegate: UIGestureRecognizerDelegate? {
didSet {
self.addTarget(self, action: #selector(handlePan))
}
}
internal var panDelegate: PanGestureRecognizerDelegate? {
return delegate as? PanGestureRecognizerDelegate
}
// MARK: Initialization
/// Initialize the pan gesture recognizer with no target or action set.
public convenience init() {
self.init(target: nil, action: nil)
}
// MARK: Overrides
open override func reset() {
super.reset()
initialLocation = nil
initialDirection = nil
}
// MARK: Actions
internal func handlePan() {
if (state == .began) {
initialLocation = location
initialDirection = direction
}
switch state {
case .began:
panDelegate?.panGestureRecognizer?(didStart: self)
case .changed:
panDelegate?.panGestureRecognizer?(didUpdate: self)
case .cancelled:
panDelegate?.panGestureRecognizer?(didCancel: self)
case .ended where shouldCancel():
panDelegate?.panGestureRecognizer?(didCancel: self)
case .ended:
panDelegate?.panGestureRecognizer?(didFinish: self)
default:
break
}
// set recognizer translation to zero
self.setTranslation(CGPoint.zero, in: view)
}
// MARK: Cancellation
fileprivate func shouldCancel() -> Bool {
return translation() < minimumTranslation || velocity() < minimumVelocity
}
}
// MARK: - Dynamic variables
extension PanGestureRecognizer {
/// The pan gesture recognizer's current location in `view`, calculated using `location(in:)`. Returns `nil` if `view` is `nil`.
public var location: CGPoint? {
guard let view = view else {
return nil
}
return location(in:view)
}
/// The pan gesture recognizer's current direction in `view`, calculated using `translation(in:)`. Returns `nil` if `view` is `nil`.
public var direction: Direction? {
guard let view = view else {
return nil
}
let translation = self.translation(in: view)
if (translation == .zero) {
return nil
} else if (fabs(translation.x) < fabs(translation.y)) {
return translation.y > 0.0 ? .down : .up
} else {
return translation.x > 0.0 ? .right : .left
}
}
}
// MARK: - Directional helpers
extension PanGestureRecognizer {
public func translation(inDirection direction: Direction? = nil) -> CGFloat {
guard let direction = direction ?? initialDirection, let view = view else {
return 0.0
}
return translation(in: view).magnitude(inDirection: direction)
}
public func velocity(in direction: Direction? = nil) -> CGFloat {
guard let direction = direction ?? initialDirection, let view = view else {
return 0.0
}
return velocity(in: view).magnitude(inDirection: direction)
}
public func translationPoint() -> CGPoint {
return translation(in: view)
}
public func velocityPoint() -> CGPoint {
return velocity(in: view)
}
}
And, i have added the pangesture in storyboard and subclassed it.
@IBOutlet weak var panGestureRecognizer: PanGestureRecognizer!
Updating my view like below,
// MARK: View state
public func updateView() {
let translation = self.panGestureRecognizer.translationPoint()
//let velocity = self.panGestureRecognizer.velocity(in: direction)
let originY = self.view.frame.origin.y + translation.y
let MIN :CGFloat = 0
let MAX :CGFloat = (self.view.height - kMaxTranslation)
if(originY <= MIN || originY >= MAX){
return
}
self.view.frame.origin.y = originY
}
I am calling the delegate methods as below,
// MARK: - UIGestureRecognizerDelegate
extension MyViewController : UIGestureRecognizerDelegate {
public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
guard let g = self.panGestureRecognizer else { return false }
guard g.view is UIScrollView else { return false }
return true
}
public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldBeRequiredToFailBy
otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return false
}
}
// MARK: - Pan gesture recognizer delegate
extension MyViewController: PanGestureRecognizerDelegate {
@objc(panGestureRecognizerWithDidStart:) func panGestureRecognizer(didStart gestureRecognizer: PanGestureRecognizer) {
updateView()
}
@objc(panGestureRecognizerWithDidUpdate:) func panGestureRecognizer(didUpdate gestureRecognizer: PanGestureRecognizer) {
updateView()
}
@objc(panGestureRecognizerWithDidCancel:) func panGestureRecognizer(didCancel gestureRecognizer: PanGestureRecognizer) {
updateView()
}
@objc(panGestureRecognizerWithDidFinish:) func panGestureRecognizer(didFinish gestureRecognizer: PanGestureRecognizer) {
updateView()
}
}
I have added a generic view controller with pangesture in it and extending it to all my viewcontrollers.
Now, it's working fine.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.