iOS开发之UI篇(5)—— 添加手势

2017-11-15  本文已影响83人  看影成痴

版本

Xcode 9.1

1. 六种常用手势:

2. 解决手势冲突

手势识别实际上是调用触摸事件来实现的。如果一个手势A的识别部分是另一个手势B的子部分时,默认情况下A就会先识别,B就无法识别了,造成手势冲突。例如拖动手势(UIPanGestureRecognizer)的操作事件是在手势的开始状态(UIGestureRecognizerStateBegan)开始执行的,而滑动手势(UISwipeGestureRecognizer)的操作事件只有在手势结束状态(UIGestureRecognizerStateEnded)才能执行,因此能识别拖动手势而不能识别滑动手势。
解决手势冲突办法:

使用requireGestureRecognizerToFail:方法,指定某个手势执行的前提是另一个手势失败后才会执行。

例如:

    /* 解决手势冲突 */
    // 解决 单击 与 双击 之间的冲突
    [singleTap requireGestureRecognizerToFail:doubleTap];
    // 解决 拖动 与 滑动 之间的冲突
    [pan requireGestureRecognizerToFail:swipeToLeft];
    [pan requireGestureRecognizerToFail:swipeToRight];
    // 解决 拖动 和 长按 之间的冲突
    [longPress requireGestureRecognizerToFail:pan];

3. 手势在视图控件之间的传递(响应链)

和触摸事件一样,默认情况下,子视图(上层视图)触摸事件执行后就不再向父视图(下层视图)传递。如果想继续往下传递手势,可利用代理方法gestureRecognizer: shouldRecognizeSimultaneouslyWithGestureRecognizer:来实现。此代理方法默认返回NO,会阻断继续向下识别手势,如果返回YES则可以继续向下传递手势。

示例
注意UIImageView默认userInteractionEnabled为NO,这就无法识别手势。本例使用storyboard创建UIImageView并设置userInteractionEnabled为YES。

GestureVC.m

#import "GestureVC.h"

@interface GestureVC () <UIGestureRecognizerDelegate> {
    
    NSInteger _currentIndex;
}

@property (weak, nonatomic) IBOutlet UILabel *label;
@property (weak, nonatomic) IBOutlet UIImageView *imageView;

@end

@implementation GestureVC

- (void)viewDidLoad {
    [super viewDidLoad];
        
    /* ----- 点击手势 ----- */
    // 默认单击
    UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapGesture:)];
    [self.imageView addGestureRecognizer:singleTap];
    // 双击
    UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTapGesture:)];
    doubleTap.numberOfTapsRequired = 2;
    // 需要2根手指一起敲击
//    tap.numberOfTouchesRequired = 2;
    // 把点击手势添加到imageView上
    [self.imageView addGestureRecognizer:doubleTap];
    
    /* ----- 捏合手势 ----- */
    // 模拟器触发:按住option键,再点鼠标左键
    UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinchGesture:)];
    [self.imageView addGestureRecognizer:pinch];
    
    /* ----- 旋转手势 ----- */
    // 模拟器触发:也是按住option键
    UIRotationGestureRecognizer *rotation = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(rotationGesture:)];
    [self.imageView addGestureRecognizer:rotation];
    
    /* ----- 滑动手势 ----- */
    // 默认往右滑
    UISwipeGestureRecognizer *swipeToRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeToRightGesture:)];
    [self.imageView addGestureRecognizer:swipeToRight];
    // 改成往左滑
    UISwipeGestureRecognizer *swipeToLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeToLeftGesture:)];
    swipeToLeft.direction = UISwipeGestureRecognizerDirectionLeft;
    [self.imageView addGestureRecognizer:swipeToLeft];
    // 支持两个方向(左+右/上+下),不同时支持横向和竖向,优先支持横向
//    swipe.direction = UISwipeGestureRecognizerDirectionLeft|UISwipeGestureRecognizerDirectionRight;
    
    /* ----- 拖动手势 ----- */
    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGesture:)];
    [self.imageView addGestureRecognizer:pan];
    
    /* ----- 长按手势 ----- */
    UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressGesture:)];
    // 设置长按时间
    longPress.minimumPressDuration = 1.0f;
    [self.imageView addGestureRecognizer:longPress];
    
    /* 解决手势冲突 */
    // 解决 单击 与 双击 之间的冲突
    [singleTap requireGestureRecognizerToFail:doubleTap];
    // 解决 拖动 与 滑动 之间的冲突
    [pan requireGestureRecognizerToFail:swipeToLeft];
    [pan requireGestureRecognizerToFail:swipeToRight];
    // 解决 拖动 和 长按 之间的冲突
    [longPress requireGestureRecognizerToFail:pan];
}


#pragma mark - 手势识别响应方法

// 单击手势
- (void)singleTapGesture:(UITapGestureRecognizer *)gesture {
    
    NSLog(@"singleTapGesture");
    
    self.label.hidden = !self.label.hidden;
}


// 双击手势
- (void)doubleTapGesture:(UITapGestureRecognizer *)gesture {
    
    NSLog(@"doubleTapGesture");
    
    // 取消一切形变
    self.imageView.transform = CGAffineTransformIdentity;
}


// 捏合手势
- (void)pinchGesture:(UIPinchGestureRecognizer *)gesture {
    
    NSLog(@"pinchGesture");
    
    if (gesture.state == UIGestureRecognizerStateChanged) {         // 手势进行中
        // 捏合手势中scale属性记录了缩放比例
        self.imageView.transform = CGAffineTransformMakeScale(gesture.scale, gesture.scale);
    }else if(gesture.state == UIGestureRecognizerStateEnded) {      // 手势结束
    }
}


// 旋转手势
- (void)rotationGesture:(UIRotationGestureRecognizer *)gesture {
    
    NSLog(@"rotationGesture");

    if (gesture.state == UIGestureRecognizerStateChanged) {         // 手势进行中
        // 旋转手势中rotation属性记录了旋转弧度
        self.imageView.transform = CGAffineTransformMakeRotation(gesture.rotation);
    }else if(gesture.state == UIGestureRecognizerStateEnded) {      // 手势结束
    }
}


// 向左滑动手势
- (void)swipeToLeftGesture:(UISwipeGestureRecognizer *)gesture {
    
    NSLog(@"swipeToLeftGesture");
    
    // 上一张图片
    _currentIndex--;
    if (_currentIndex < 0) {
        _currentIndex = 2;
    }else if (_currentIndex >2) {
        _currentIndex = 0;
    }
    self.imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"%ld.jpg",_currentIndex]];
}


// 向右滑动手势
- (void)swipeToRightGesture:(UISwipeGestureRecognizer *)gesture {
    
    NSLog(@"swipeToRightGesture");

    // 下一张图片
    _currentIndex++;
    if (_currentIndex < 0) {
        _currentIndex = 2;
    }else if (_currentIndex >2) {
        _currentIndex = 0;
    }
    self.imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"%ld.jpg",_currentIndex]];
}


// 拖动手势
- (void)panGesture:(UIPanGestureRecognizer *)gesture {
    
    NSLog(@"panGesture");

    if (gesture.state == UIGestureRecognizerStateChanged) {     // 手势进行中
        // 取得在相对根视图(self.view)的移动
        CGPoint translation = [gesture translationInView:self.view];
        // 改变imageView坐标
        self.imageView.transform = CGAffineTransformMakeTranslation(translation.x, translation.y);
    }else if(gesture.state == UIGestureRecognizerStateEnded){
        // 0.5s后取消一切形变
        [UIView animateWithDuration:0.5 animations:^{
            self.imageView.transform = CGAffineTransformIdentity;
        }];
    }
}


// 长按手势
- (void)longPressGesture:(UILongPressGestureRecognizer *)gesture {
    
    NSLog(@"longPressGesture");

    // 此方法会调用两次(Began & Ended),需判断其手势状态
    if (gesture.state == UIGestureRecognizerStateBegan) {

        // 创建alertController
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"提示" message:@"确定删除这张图片吗?" preferredStyle:UIAlertControllerStyleActionSheet];
        // 添加确认按钮
        [alertController addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action){
            // 这里啥也不做
        }]];
        // 添加取消按钮
        [alertController addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
            // 这里啥也不做
        }]];
        // 显示alertController
        [self presentViewController:alertController animated:YES completion:nil];
    }
}


@end
效果图
上一篇下一篇

猜你喜欢

热点阅读