美文网首页
iOS开发之UI篇(5)—— 添加手势

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

作者: 看影成痴 | 来源:发表于2017-11-15 09:13 被阅读83次

    版本

    Xcode 9.1

    1. 六种常用手势:

    • UITapGestureRecognizer:点击手势
    • UIPinchGestureRecognizer:捏合手势(放大缩小)
    • UIRotationGestureRecognizer:旋转手势
    • UISwipeGestureRecognizer:滑动手势
    • UIPanGestureRecognizer:拖动手势
    • UILongPressGestureRecognizer:长按手势

    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
    
    效果图

    相关文章

      网友评论

          本文标题:iOS开发之UI篇(5)—— 添加手势

          本文链接:https://www.haomeiwen.com/subject/ahxcvxtx.html