简体   繁体   English

iOS:为多个视图重用UIPanGestureRecognizer类/方法的正确方法?

[英]IOS : Correct way to reuse UIPanGestureRecognizer class / methods for multiple view?

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. 因此,我想创建一个通用的UIPanGestureRecognizer类来注册视图并调用委托方法到相应的视图。

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. 现在,它工作正常。

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

相关问题 UIPanGestureRecognizer通过swift在多个视图上 - UIPanGestureRecognizer on multiple view by swift iOS:从其他视图的类更改视图的正确方法是什么? - IOS: What is the correct way to change a view from the class of a different view? 制作类似于新版Google Maps iOS应用程序的向上滑动视图,使用多个UIPanGestureRecognizer会遇到麻烦 - Making a slide up view similar to the new Google Maps iOS app, troubles with multiple UIPanGestureRecognizer 如何从iOS中的UIPanGestureRecognizer的选择器引用视图的控制器? - How to reference a view's controller from the UIPanGestureRecognizer's selector in iOS? [Swift-iOS]使用 UIPanGestureRecognizer 向下拖动视图,不拉伸 - [Swift-iOS]Dragging down view using UIPanGestureRecognizer, not stretching ios-UIPanGestureRecognizer如何获得相对于[gestureRecognizer视图]的触摸坐标 - ios - UIPanGestureRecognizer how to get the touched coordinate relative to [gestureRecognizer view] 重用静态表格检视(iOS) - Reuse static table view (iOS) 用整个应用程序使用的方法编写类的正确方法是什么 - What's the correct way to write a class with methods used by the whole app UIPanGestureRecognizer有时无法在iOS 7上运行 - UIPanGestureRecognizer sometimes not working on iOS 7 iOS UIPanGestureRecognizer可防止滚动 - iOS UIPanGestureRecognizer prevents scroll
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM