UIPanGestureIdentiizer-仅垂直或水平

我有一个视图,它有一个 UIPanGestureRecognizer来垂直拖动该视图。所以在识别器回调中,我只更新 y 坐标来移动它。这个视图的超级视图有一个 UIPanGestureRecognizer,它将水平拖动视图,只是更新 x 坐标。

问题是,第一个 UIPanGestureRecognizer采用事件来垂直移动视图,所以我不能使用 Superview 姿态。

我试过了

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldRecognizeSimultaneouslyWithGestureRecognizer:
(UIGestureRecognizer *)otherGestureRecognizer;

两者都能成功,但我不想那样。我希望只有当运动明显是水平的时候才能检测到水平运动。所以如果 UIPanGestureRecognizer具有方向性就太好了。

我怎样才能做到这一点呢? 我发现这些文件很令人困惑,所以也许有人可以在这里更好地解释一下。

74377 次浏览

我解决了创建 UIPanGestureIdentiizer 的子类的问题

识别器:

#import <Foundation/Foundation.h>
#import <UIKit/UIGestureRecognizerSubclass.h>


typedef enum {
DirectionPangestureRecognizerVertical,
DirectionPanGestureRecognizerHorizontal
} DirectionPangestureRecognizerDirection;


@interface DirectionPanGestureRecognizer : UIPanGestureRecognizer {
BOOL _drag;
int _moveX;
int _moveY;
DirectionPangestureRecognizerDirection _direction;
}


@property (nonatomic, assign) DirectionPangestureRecognizerDirection direction;


@end

识别:

#import "DirectionPanGestureRecognizer.h"


int const static kDirectionPanThreshold = 5;


@implementation DirectionPanGestureRecognizer


@synthesize direction = _direction;


- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesMoved:touches withEvent:event];
if (self.state == UIGestureRecognizerStateFailed) return;
CGPoint nowPoint = [[touches anyObject] locationInView:self.view];
CGPoint prevPoint = [[touches anyObject] previousLocationInView:self.view];
_moveX += prevPoint.x - nowPoint.x;
_moveY += prevPoint.y - nowPoint.y;
if (!_drag) {
if (abs(_moveX) > kDirectionPanThreshold) {
if (_direction == DirectionPangestureRecognizerVertical) {
self.state = UIGestureRecognizerStateFailed;
}else {
_drag = YES;
}
}else if (abs(_moveY) > kDirectionPanThreshold) {
if (_direction == DirectionPanGestureRecognizerHorizontal) {
self.state = UIGestureRecognizerStateFailed;
}else {
_drag = YES;
}
}
}
}


- (void)reset {
[super reset];
_drag = NO;
_moveX = 0;
_moveY = 0;
}


@end

这只有在用户开始拖动选定的行为时才会触发手势。将 direct 属性设置为正确的值,就可以全部设置了。

只要做到这一点的垂直泛手势识别器,它为我工作:

- (BOOL)gestureRecognizerShouldBegin:(UIPanGestureRecognizer *)panGestureRecognizer {
CGPoint velocity = [panGestureRecognizer velocityInView:someView];
return fabs(velocity.y) > fabs(velocity.x);
}

至于斯威夫特:

func gestureRecognizerShouldBegin(_ gestureRecognizer: UIPanGestureRecognizer) -> Bool {
let velocity = gestureRecognizer.velocity(in: someView)
return abs(velocity.x) > abs(velocity.y)
}

您可以找到在 UIView上通过 UIPanGestureRecognizer拖动的方向。请按照代码操作。

 - (void)viewDidLoad {
[super viewDidLoad];
flipFoward = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(doFlipForward:)];
[flipFoward setMaximumNumberOfTouches:1];
[flipFoward setMinimumNumberOfTouches:1];
[flipFoward setDelegate:self];
[self.view addGestureRecognizer:flipFoward];
flipBack = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(doFlipBack:)];
[flipBack setMaximumNumberOfTouches:1];
[flipBack setMinimumNumberOfTouches:1];
[flipBack setDelegate:self];
[self.view addGestureRecognizer:flipBack];
}


#pragma mark -
#pragma mark RESPONDER


-(void)doFlipForward:(UIGestureRecognizer *)aGestureRecognizer{
NSLog(@"doFlipForward");
if([(UIPanGestureRecognizer*)aGestureRecognizer state] == UIGestureRecognizerStateBegan) {
NSLog(@"UIGestureRecognizerStateBegan");
}
if([(UIPanGestureRecognizer*)aGestureRecognizer state] == UIGestureRecognizerStateChanged) {
NSLog(@"UIGestureRecognizerStateChanged");
}
if([(UIPanGestureRecognizer*)aGestureRecognizer state] == UIGestureRecognizerStateEnded) {
NSLog(@"UIGestureRecognizerStateEnded");
}
}


-(void)doFlipBack:(UIGestureRecognizer *)aGestureRecognizer{
NSLog(@"doFlipBack");
if([(UIPanGestureRecognizer*)aGestureRecognizer state] == UIGestureRecognizerStateBegan) {
NSLog(@"UIGestureRecognizerStateBegan1");
}
if([(UIPanGestureRecognizer*)aGestureRecognizer state] == UIGestureRecognizerStateChanged) {
NSLog(@"UIGestureRecognizerStateChanged1");
}
if([(UIPanGestureRecognizer*)aGestureRecognizer state] == UIGestureRecognizerStateEnded) {
NSLog(@"UIGestureRecognizerStateEnded1");
}
}


#pragma mark -
#pragma mark DELEGATE


-(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
CGSize size = [self.view bounds].size;
CGFloat touchX = [gestureRecognizer locationInView:self.view].x;
if((gestureRecognizer == flipFoward)
&& touchX >= (size.width - 88.0f))
{
return YES;
}
if((gestureRecognizer == flipBack)
&& touchX <= 88.0f)
{
return YES;
}
return NO;
}

PanGestureRecognizer接口包含以下定义:

unsigned int    _canPanHorizontally:1;
unsigned int    _canPanVertically:1;

我没有检查这个,但也许可以通过子类访问它。

下面的解决方案解决了我的问题:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
if ([gestureRecognizer.view isEqual:self.view] && [otherGestureRecognizer.view isEqual:self.tableView]) {
return NO;
}
return YES;
}

这实际上只是检查 pan 是使用 main view 还是 tableView。

我是这样决定的:

首先,我启用了同步的手势识别。

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {


return YES;

然后,我分离水平和垂直平移手势(累加器是 NSMutableArray 属性) :

- (void)verticalPan :(UIPanGestureRecognizer *) sender {


CGPoint touch  = [sender translationInView:self];
NSValue *value = [NSValue valueWithCGPoint:touch];
[accumulator addObject:value];


int firstXObjectValue = (int)[[accumulator objectAtIndex:0] CGPointValue].x ;
int lastXObjectValue =  (int)[[accumulator lastObject] CGPointValue].x;


int firstYObjectValue = (int)[[accumulator objectAtIndex:0] CGPointValue].y;
int lastYObjectValue =  (int)[[accumulator lastObject] CGPointValue].y;


if (abs(lastYObjectValue - firstYObjectValue) < 4 && abs(lastXObjectValue - firstXObjectValue) > 4) {
NSLog(@"Horizontal Pan");


//do something here
}
else if (abs(lastYObjectValue - firstYObjectValue) > 4 && abs(lastXObjectValue - firstXObjectValue) < 4){
NSLog(@"Vertical Pan");


//do something here
}


if (accumulator.count > 3)
[accumulator removeAllObjects];

我举了一个例子:

在 scrollview 中添加自定义平底锅

我尝试使用 UIPanGestureIdentiizer 水平约束有效区域。

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]) {


UIPanGestureRecognizer *panGesture = (UIPanGestureRecognizer *)gestureRecognizer;
CGPoint velocity = [panGesture velocityInView:panGesture.view];


double radian = atan(velocity.y/velocity.x);
double degree = radian * 180 / M_PI;


double thresholdAngle = 20.0;
if (fabs(degree) > thresholdAngle) {
return NO;
}
}
return YES;
}

然后,只有在 < em > 阈值/角度 度水平滑动才能触发这个平移姿势。

对于所有 Swift 的用户来说,这个就足够了:)

import Foundation
import UIKit.UIGestureRecognizerSubclass




class DirectionPanGestureRecognizer: UIPanGestureRecognizer {


let kDirectionPanThreshold = CGFloat(5)
var drag = true
var moveX = CGFloat(0)
var moveY = CGFloat(0)


override init(target: AnyObject, action: Selector) {
super.init(target: target, action: action)
}


override func touchesMoved(touches: NSSet, withEvent event: UIEvent) {
super.touchesMoved(touches, withEvent: event)
if state == .Failed {
return
}


let nowPoint = touches.anyObject()?.locationInView(view)
let prevPoint = touches.anyObject()?.previousLocationInView(view)
moveX += prevPoint!.x - nowPoint!.x
moveY += prevPoint!.y - nowPoint!.y
if !drag {
if abs(moveX) > kDirectionPanThreshold {
state = .Failed
} else {
drag = true
}


}


}


override func reset() {
super.reset()
moveX = 0
moveY = 0
drag = false
}








}

我创建了一个带有子类的解决方案,就像@LocoMike 提供的答案一样,但是使用了@Hejazi 提供的通过初始速度的更有效的检测机制。我也使用 Swift,但是如果需要的话,这应该很容易翻译成 Obj-C。

相对于其他解决方案的优势:

  • 比其他子类化解决方案更简单、更简洁。不需要管理额外的状态。
  • 方向检测发生在发送 Began 操作之前,因此如果滑动错误的方向,您的平移手势选择器将不会收到任何消息。
  • 确定初始方向后,不再参考方向逻辑。如果初始方向是正确的,这将导致激活识别器的普遍期望行为,但如果用户的手指没有沿着正确的方向完美移动,则不会取消已经开始的手势。

密码是这样的:

import UIKit.UIGestureRecognizerSubclass


enum PanDirection {
case vertical
case horizontal
}


class PanDirectionGestureRecognizer: UIPanGestureRecognizer {


let direction: PanDirection


init(direction: PanDirection, target: AnyObject, action: Selector) {
self.direction = direction
super.init(target: target, action: action)
}


override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
super.touchesMoved(touches, with: event)


if state == .began {
let vel = velocity(in: view)
switch direction {
case .horizontal where fabs(vel.y) > fabs(vel.x):
state = .cancelled
case .vertical where fabs(vel.x) > fabs(vel.y):
state = .cancelled
default:
break
}
}
}
}

用法示例:

let panGestureRecognizer = PanDirectionGestureRecognizer(direction: .horizontal, target: self, action: #selector(handlePanGesture(_:)))
panGestureRecognizer.cancelsTouchesInView = false
self.view.addGestureRecognizer(panGestureRecognizer)


func handlePanGesture(_ pan: UIPanGestureRecognizer) {
let percent = max(pan.translation(in: view).x, 0) / view.frame.width


switch pan.state {
case .began:
...
}

您可以使用简单的 panGestureRecognizer。不需要使用 就用 translationInview的 y 值 下面的代码只向上和向下移动拖动视图

- (void)gesturePan_Handle:(UIPanGestureRecognizer *)gesture {
if (gesture.state == UIGestureRecognizerStateChanged) {
CGPoint translation = [gesture translationInView:gesture.view];
recognizer.view.center = CGPointMake(recognizer.view.center.x, recognizer.view.center.y + translation.y);
[gesture setTranslation:CGPointMake(0, 0) inView:gesture.view];
}
}
let pangesture = UIPanGestureRecognizer(target: self, action: "dragview:")
yourview.addGestureRecognizer(pangesture)




func dragview(panGestureRecognizer:UIPanGestureRecognizer)
{
let touchlocation = panGestureRecognizer.locationInView(parentview)
yourview.center.y = touchlocation.y //x for horizontal
}
- (void)dragAction:(UIPanGestureRecognizer *)gesture{
UILabel *label = (UILabel *)gesture.view;
CGPoint translation = [gesture translationInView:label];
label.center = CGPointMake(label.center.x + translation.x,
label.center.y + 0);
[gesture setTranslation:CGPointZero inView:label];}

我为只需要水平滚动的对象创建了 PanGestureIdentiizer@selector 操作方法。

 UIPanGestureRecognizer *gesture = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(smileyDragged:)];
[buttonObject addGestureRecognizer:gesture];

斯威夫特3版李对懒人的回答

import UIKit
import UIKit.UIGestureRecognizerSubclass


enum PanDirection {
case vertical
case horizontal
}


class UIPanDirectionGestureRecognizer: UIPanGestureRecognizer {


let direction : PanDirection


init(direction: PanDirection, target: AnyObject, action: Selector) {
self.direction = direction
super.init(target: target, action: action)
}


override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
super.touchesMoved(touches, with: event)


if state == .began {


let vel = velocity(in: self.view!)
switch direction {
case .horizontal where fabs(vel.y) > fabs(vel.x):
state = .cancelled
case .vertical where fabs(vel.x) > fabs(vel.y):
state = .cancelled
default:
break
}
}
}
}

我采取了一个优秀的 回答由李古德里奇和移植到斯威夫特3

import UIKit
import UIKit.UIGestureRecognizerSubclass


enum PanDirection {
case vertical
case horizontal
}


class PanDirectionGestureRecognizer: UIPanGestureRecognizer {


let direction : PanDirection


init(direction: PanDirection, target: AnyObject, action: Selector) {
self.direction = direction
super.init(target: target, action: action)
}


override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {


super.touchesMoved(touches, with: event)


if state == .began {


let vel = velocity(in: self.view!)


switch direction {


case .horizontal where fabs(vel.y) > fabs(vel.x):
state = .cancelled


case .vertical where fabs(vel.x) > fabs(vel.y):
state = .cancelled


default:
break


}


}
}
}

迅捷3.0的答案: 只是处理做垂直的手势

    override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
if let pan = gestureRecognizer as? UIPanGestureRecognizer {
let velocity = pan.velocity(in: self)
return fabs(velocity.y) > fabs(velocity.x)
}
return true


}

快点

override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
if let panGestureRecognizer = gestureRecognizer as? UIPanGestureRecognizer {
return isVerticalGesture(panGestureRecognizer)
}
return false
}


private func isVerticalGesture(_ recognizer: UIPanGestureRecognizer) -> Bool {
let translation = recognizer.translation(in: superview!)
if fabs(translation.y) > fabs(translation.x) {
return true
}
return false
}

我很乐意分享我的方法,因为所有其他方法都是基于 UIGestureRecognizerDelegate或子类 UIPanGestureRecognizer的。

我的方法是基于运行时和调整。我不能100% 肯定这种方法,但是您可以自己测试和改进它。

用一行代码设置任意 UIPanGestureRecognizer的方向:

UITableView().panGestureRecognizer.direction = UIPanGestureRecognizer.Direction.vertical

使用 pod 'UIPanGestureRecognizerDirection'或代码:

public extension UIPanGestureRecognizer {


override open class func initialize() {
super.initialize()
guard self === UIPanGestureRecognizer.self else { return }
func replace(_ method: Selector, with anotherMethod: Selector, for clаss: AnyClass) {
let original = class_getInstanceMethod(clаss, method)
let swizzled = class_getInstanceMethod(clаss, anotherMethod)
switch class_addMethod(clаss, method, method_getImplementation(swizzled), method_getTypeEncoding(swizzled)) {
case true:
class_replaceMethod(clаss, anotherMethod, method_getImplementation(original), method_getTypeEncoding(original))
case false:
method_exchangeImplementations(original, swizzled)
}
}
let selector1 = #selector(UIPanGestureRecognizer.touchesBegan(_:with:))
let selector2 = #selector(UIPanGestureRecognizer.swizzling_touchesBegan(_:with:))
replace(selector1, with: selector2, for: self)
let selector3 = #selector(UIPanGestureRecognizer.touchesMoved(_:with:))
let selector4 = #selector(UIPanGestureRecognizer.swizzling_touchesMoved(_:with:))
replace(selector3, with: selector4, for: self)
}


@objc private func swizzling_touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
self.swizzling_touchesBegan(touches, with: event)
guard direction != nil else { return }
touchesBegan = true
}


@objc private func swizzling_touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
self.swizzling_touchesMoved(touches, with: event)
guard let direction = direction, touchesBegan == true else { return }
defer {
touchesBegan = false
}
let forbiddenDirectionsCount = touches
.flatMap({ ($0.location(in: $0.view) - $0.previousLocation(in: $0.view)).direction })
.filter({ $0 != direction })
.count
if forbiddenDirectionsCount > 0 {
state = .failed
}
}
}


public extension UIPanGestureRecognizer {


public enum Direction: Int {


case horizontal = 0
case vertical
}


private struct UIPanGestureRecognizerRuntimeKeys {
static var directions = "\(#file)+\(#line)"
static var touchesBegan = "\(#file)+\(#line)"
}


public var direction: UIPanGestureRecognizer.Direction? {
get {
let object = objc_getAssociatedObject(self, &UIPanGestureRecognizerRuntimeKeys.directions)
return object as? UIPanGestureRecognizer.Direction
}
set {
let policy = objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC
objc_setAssociatedObject(self, &UIPanGestureRecognizerRuntimeKeys.directions, newValue, policy)
}
}


fileprivate var touchesBegan: Bool {
get {
let object = objc_getAssociatedObject(self, &UIPanGestureRecognizerRuntimeKeys.touchesBegan)
return (object as? Bool) ?? false
}
set {
let policy = objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC
objc_setAssociatedObject(self, &UIPanGestureRecognizerRuntimeKeys.touchesBegan, newValue, policy)
}
}
}


fileprivate extension CGPoint {


var direction: UIPanGestureRecognizer.Direction? {
guard self != .zero else { return nil }
switch fabs(x) > fabs(y) {
case true:  return .horizontal
case false: return .vertical
}
}


static func -(lhs: CGPoint, rhs: CGPoint) -> CGPoint {
return CGPoint(x: lhs.x - rhs.x, y: lhs.y - rhs.y)
}
}

我把 李 · 古德里奇回答和延长,因为我需要一个具体的单向盘。像这样使用: let pan = PanDirectionGestureRecognizer(direction: .vertical(.up), target: self, action: #selector(handleCellPan(_:)))

我还添加了一些评论,以便更清楚地说明实际上正在做出哪些决定。

import UIKit.UIGestureRecognizerSubclass


enum PanVerticalDirection {
case either
case up
case down
}


enum PanHorizontalDirection {
case either
case left
case right
}


enum PanDirection {
case vertical(PanVerticalDirection)
case horizontal(PanHorizontalDirection)
}


class PanDirectionGestureRecognizer: UIPanGestureRecognizer {


let direction: PanDirection


init(direction: PanDirection, target: AnyObject, action: Selector) {
self.direction = direction
super.init(target: target, action: action)
}


override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
super.touchesMoved(touches, with: event)


if state == .began {
let vel = velocity(in: view)
switch direction {


// expecting horizontal but moving vertical, cancel
case .horizontal(_) where fabs(vel.y) > fabs(vel.x):
state = .cancelled


// expecting vertical but moving horizontal, cancel
case .vertical(_) where fabs(vel.x) > fabs(vel.y):
state = .cancelled


// expecting horizontal and moving horizontal
case .horizontal(let hDirection):
switch hDirection {


// expecting left but moving right, cancel
case .left where vel.x > 0: state = .cancelled


// expecting right but moving left, cancel
case .right where vel.x < 0: state = .cancelled
default: break
}


// expecting vertical and moving vertical
case .vertical(let vDirection):
switch vDirection {
// expecting up but moving down, cancel
case .up where vel.y > 0: state = .cancelled


// expecting down but moving up, cancel
case .down where vel.y < 0: state = .cancelled
default: break
}
}
}
}
}

我试过这样做: 这对我很有效,就像问题描述的那样

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
if gestureRecognizer is UIPanGestureRecognizer {
return true
} else {
return false
}
}

Swift 4.2

解决方案是只支持锅姿态垂直,水平相同。

let pan = UIPanGestureRecognizer(target: self, action: #selector(test1))
pan.cancelsTouchesInView = false
panView.addGestureRecognizer(pan)

解决方案1 :

@objc func panAction(pan: UIPanGestureRecognizer) {


let velocity = pan.velocity(in: panView)
guard abs(velocity.y) > abs(velocity.x) else {
return
}
}

解决方案2:

  [UISwipeGestureRecognizer.Direction.left, .right].forEach { direction in
let swipe = UISwipeGestureRecognizer(target: self, action: #selector(swipeAction))
swipe.direction = direction
panView.addGestureRecognizer(swipe)
pan.require(toFail: swipe)
}

当然,你不需要在 swipeAction中做任何事情。

SWIFT 4.2

我走得更远,制定了一个方向,潘氏手势:

enum PanDirection {
case up
case left
case right
case down
}


class PanDirectionGestureRecognizer: UIPanGestureRecognizer {
    

fileprivate let direction: PanDirection
    

init(direction: PanDirection, target: AnyObject, action: Selector) {
self.direction = direction
super.init(target: target, action: action)
}
    

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
super.touchesMoved(touches, with: event)
        

guard state != .failed else { return }


let vel = velocity(in: view)


let velocities: [PanDirection: CGFloat]
= [.up: -vel.y,
.left: -vel.x,
.right: vel.x,
.down: vel.y]


let sortedKeys = velocities.sorted { $0.1 < $1.1 }


if let key = sortedKeys.last?.key,
key != direction {
state = .cancelled
}
}
}

(使用: https://github.com/fastred/SloppySwiperhttps://stackoverflow.com/a/30607392/5790492)

下面是 斯威夫特中的一个自定义平移手势

可以约束它的方向和最大角度的方向,也可以约束它的最小速度的方向。

enum PanDirection {
case vertical
case horizontal
}


struct Constaint {
let maxAngle: Double
let minSpeed: CGFloat


static let `default` = Constaint(maxAngle: 50, minSpeed: 50)
}




class PanDirectionGestureRecognizer: UIPanGestureRecognizer {


let direction: PanDirection


let constraint: Constaint




init(direction orientation: PanDirection, target: AnyObject, action: Selector, constraint limits: Constaint = Constaint.default) {
direction = orientation
constraint = limits
super.init(target: target, action: action)
}


override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
super.touchesMoved(touches, with: event)
let tangent = tan(constraint.maxAngle * Double.pi / 180)
if state == .began {
let vel = velocity(in: view)
switch direction {
case .horizontal where abs(vel.y)/abs(vel.x) > CGFloat(tangent) || abs(vel.x) < constraint.minSpeed:
state = .cancelled
case .vertical where abs(vel.x)/abs(vel.y) > CGFloat(tangent) || abs(vel.y) < constraint.minSpeed:
state = .cancelled
default:
break
}
}
}
}

像这样打电话:

    let pan = PanDirectionGestureRecognizer(direction: .vertical, target: self, action: #selector(self.push(_:)))
view.addGestureRecognizer(pan)


@objc func push(_ gesture: UIPanGestureRecognizer){
if gesture.state == .began{
// command for once
}
}

或者

    let pan = PanDirectionGestureRecognizer(direction: .horizontal, target: self, action: #selector(self.push(_:)), constraint: Constaint(maxAngle: 5, minSpeed: 80))
view.addGestureRecognizer(pan)