iOS轻点、触摸和手势代码开发

 更新时间:2016年10月12日 15:31:10   作者:tutu的dudu  
这篇文章主要为大家详细介绍了iOS轻点、触摸和手势代码开发,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

一、响应者链

以UIResponder作为超类的任何类都是响应者。UIView和UIControl是UIReponder的子类,因此所有视图和所有控件都是响应者。

1、初始相应器
事件首先会传递给UIApplication对象,接下来会传递给应用程序的UIWindow,UIWindow会选择一个初始相应器来处理事件。初始响应器会选择下面的方式选择1、对于触摸事件,UIWindow会确定用户触摸的视图,然后将事件交给注册了这个视图的手势识别器或则注册视图层级更高的手势识别器。只要存在能处理事件的识别器,就不会再继续找了。如果没有的话,被触摸视图就是初始相应器,事件也会传递给它。

2、对于用户摇晃设备产生的或者是来自远程遥控设备事件,将会传递给第一响应器
如果初始响应器不处理时间,它会将事件传递给它的父视图(如果存在的话),或者传递给视图控制器(如果此视图是视图控制器的视图)。如果视图控制器不处理事件,它将沿着响应器链的层级继续传给父视图控制器(如果存在的话)。
如果在整个视图层级中都没与能处理事件的视图或控制器,事件就会被传递给应用程序的窗口。如果窗口不能处理事件,而应用委托是UIResponder的子类,UIApplication对象就会将其传递给应用程序委托。最后,如果应用委托不是UIResponder的子类,或者不处理这个事件,那么这个事件将会被丢弃。

4个手势通知方法

#pragma mark - Touch Event Methods
// 用户第一次触摸屏幕时被调用
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{

}

// 当发生某些事件(如来电呼叫)导致手势中断时被调用
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{

}

// 当用户手指离开屏幕时被调用
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{

}

// 当用户手指移动时触发
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{

}

二、检测扫描事件

1、手动检测

//
// ViewController.m
// Swipes
//
// Created by Jierism on 16/8/4.
// Copyright © 2016年 Jierism. All rights reserved.
//

#import "ViewController.h"
// 设置检测范围
static CGFloat const kMinimmGestureLength = 25;
static CGFloat const kMaximmVariance = 5;

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UILabel *label;
@property (nonatomic) CGPoint gestureStartPoint;
@end

@implementation ViewController


- (void)viewDidLoad {
  [super viewDidLoad];
  // Do any additional setup after loading the view, typically from a nib.
}

- (void)didReceiveMemoryWarning {
  [super didReceiveMemoryWarning];
  // Dispose of any resources that can be recreated.
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
  UITouch *touch = [touches anyObject];
  self.gestureStartPoint = [touch locationInView:self.view];
}

- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
  UITouch *touch = [touches anyObject];
  CGPoint currentPosition = [touch locationInView:self.view];
  // 返回一个float的绝对值
  CGFloat deltaX = fabsf(self.gestureStartPoint.x - currentPosition.x);
  CGFloat deltaY = fabsf(self.gestureStartPoint.y - currentPosition.y);
  
  // 获得两个增量后,判断用户在两个方向上移动过的距离,检测用户是否在一个方向上移动得足够远但在另一个方向移动得不够来形成轻扫动作
  if (deltaX >= kMinimmGestureLength && deltaY <= kMaximmVariance) {
    self.label.text = @"Horizontal swipe detected";
    // 2s后擦除文本
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)),
            dispatch_get_main_queue(),
            ^{
      self.label.text = @"";
    });
  }else if (deltaY >= kMinimmGestureLength && deltaX <= kMaximmVariance){
    self.label.text = @"Vertical swipe detected";
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
      self.label.text = @"";
    });
  }
}

@end

2、识别器检测

//
// ViewController.m
// Swipes
//
// Created by Jierism on 16/8/4.
// Copyright © 2016年 Jierism. All rights reserved.
//

#import "ViewController.h"


@interface ViewController ()
@property (weak, nonatomic) IBOutlet UILabel *label;
@property (nonatomic) CGPoint gestureStartPoint;
@end

@implementation ViewController


- (void)viewDidLoad {
  [super viewDidLoad];
  // Do any additional setup after loading the view, typically from a nib.
  //创建两个手势识别器
  // 1、水平方向识别器
  UISwipeGestureRecognizer *horizontal = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(reportHorizontalSwipe:)];

  horizontal.direction = UISwipeGestureRecognizerDirectionLeft | UISwipeGestureRecognizerDirectionRight;
  [self.view addGestureRecognizer:horizontal];
  
  // 2、垂直方向识别器
  UISwipeGestureRecognizer *vertical = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(reportVerticalSwipe:)];
  vertical.direction = UISwipeGestureRecognizerDirectionUp | UISwipeGestureRecognizerDirectionDown;
  [self.view addGestureRecognizer:vertical];
}

- (void)didReceiveMemoryWarning {
  [super didReceiveMemoryWarning];
  // Dispose of any resources that can be recreated.
}

- (void)reportHorizontalSwipe:(UIGestureRecognizer *)recognizer
{

  self.label.text = @"Horizontal swipe detected";
  // 2s后擦除文本
  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)),
          dispatch_get_main_queue(),
          ^{
            self.label.text = @"";
          });
}

- (void)reportVerticalSwipe:(UIGestureRecognizer *)recognizer
{
  self.label.text = @"Vertical swipe detected";
  // 2s后擦除文本
  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)),
          dispatch_get_main_queue(),
          ^{
            self.label.text = @"";
          });
}

@end

三、实现多指轻扫

//
// ViewController.m
// Swipes
//
// Created by Jierism on 16/8/4.
// Copyright © 2016年 Jierism. All rights reserved.
//

#import "ViewController.h"



@interface ViewController ()
@property (weak, nonatomic) IBOutlet UILabel *label;
@property (nonatomic) CGPoint gestureStartPoint;
@end

@implementation ViewController


- (void)viewDidLoad {
  [super viewDidLoad];
  // Do any additional setup after loading the view, typically from a nib.
  
  for (NSUInteger touchCount = 1; touchCount <= 5; touchCount++) {
    //创建两个手势识别器
    // 1、水平方向识别器
    UISwipeGestureRecognizer *horizontal = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(reportHorizontalSwipe:)];
    
    horizontal.direction = UISwipeGestureRecognizerDirectionLeft | UISwipeGestureRecognizerDirectionRight;
    [self.view addGestureRecognizer:horizontal];
    
    // 2、垂直方向识别器
    UISwipeGestureRecognizer *vertical = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(reportVerticalSwipe:)];
    vertical.direction = UISwipeGestureRecognizerDirectionUp | UISwipeGestureRecognizerDirectionDown;
    [self.view addGestureRecognizer:vertical];
  }
  
}

- (void)didReceiveMemoryWarning {
  [super didReceiveMemoryWarning];
  // Dispose of any resources that can be recreated.
}

- (NSString *)descriptionForTouchCount:(NSUInteger)touchCount
{
  switch (touchCount) {
    case 1:
      return @"Single";
    case 2:
      return @"Double";
    case 3:
      return @"Triple";
    case 4:
      return @"Quadruple";
    case 5:
      return @"Quintuple";
      
    default:
      return @"";
  }
}

- (void)reportHorizontalSwipe:(UIGestureRecognizer *)recognizer
{

  self.label.text = [NSString stringWithFormat:@"%@ Horizontal swipe detected",[self descriptionForTouchCount:[recognizer numberOfTouches]]];
  // 2s后擦除文本
  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)),
          dispatch_get_main_queue(),
          ^{
            self.label.text = @"";
          });
}

- (void)reportVerticalSwipe:(UIGestureRecognizer *)recognizer
{
  self.label.text = [NSString stringWithFormat:@"%@ Vertical swipe detected",[self descriptionForTouchCount:[recognizer numberOfTouches]]];
  // 2s后擦除文本
  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)),
          dispatch_get_main_queue(),
          ^{
            self.label.text = @"";
          });
}

@end

四、检测多次轻点

//
// ViewController.m
// TapTaps
//
// Created by Jierism on 16/8/4.
// Copyright © 2016年 Jierism. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UILabel *singleLabel;
@property (weak, nonatomic) IBOutlet UILabel *doubleLabel;
@property (weak, nonatomic) IBOutlet UILabel *tripleLabel;
@property (weak, nonatomic) IBOutlet UILabel *quadrupleLabel;

@end

@implementation ViewController

- (void)viewDidLoad {
  [super viewDidLoad];
  // Do any additional setup after loading the view, typically from a nib.
  // 创建4个点击手势识别器
  UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTap)];
  singleTap.numberOfTapsRequired = 1;
  singleTap.numberOfTouchesRequired = 1;
  // 附加到视图
  [self.view addGestureRecognizer:singleTap];
  
  UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTap)];
  doubleTap.numberOfTapsRequired = 2;
  doubleTap.numberOfTouchesRequired = 1;
  [self.view addGestureRecognizer:doubleTap];
  // 当doubleTap响应“失败”才运行singleTap
  [singleTap requireGestureRecognizerToFail:doubleTap];
  
  UITapGestureRecognizer *tripleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tripleTap)];
  tripleTap.numberOfTapsRequired = 3;
  tripleTap.numberOfTouchesRequired = 1;
  [self.view addGestureRecognizer:tripleTap];
  [doubleTap requireGestureRecognizerToFail:tripleTap];
  
  UITapGestureRecognizer *quadrupleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(quadrupleTap)];
  quadrupleTap.numberOfTapsRequired = 4;
  quadrupleTap.numberOfTouchesRequired = 1;
  [self.view addGestureRecognizer:quadrupleTap];
  [tripleTap requireGestureRecognizerToFail:quadrupleTap];
}

- (void)singleTap
{
  self.singleLabel.text = @"Single Tap Detected";
  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    self.singleLabel.text = @"";
  });
}

- (void)doubleTap
{
  self.doubleLabel.text = @"Double Tap Detected";
  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    self.doubleLabel.text = @"";
  });
}

- (void)tripleTap
{
  self.tripleLabel.text = @"Triple Tap Detected";
  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    self.tripleLabel.text = @"";
  });
}

- (void)quadrupleTap
{
  self.quadrupleLabel.text = @"Quadruple Tap Detected";
  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    self.quadrupleLabel.text = @"";
  });
}


@end

五、检测捏合和旋转

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController<UIGestureRecognizerDelegate>


@end

//
// ViewController.m
// PinchMe
//
// Created by Jierism on 16/8/4.
// Copyright © 2016年 Jierism. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()

@property (strong,nonatomic) UIImageView *imageView;

@end

@implementation ViewController

// 当前缩放比例,先前缩放比例
CGFloat scale,previousScale;
// 当前旋转角度,先前旋转角度
CGFloat rotation,previousRotation;

- (void)viewDidLoad {
  [super viewDidLoad];
  // Do any additional setup after loading the view, typically from a nib.
  previousScale = 1;
  
  UIImage *image = [UIImage imageNamed:@"yosemite-meadows"];
  self.imageView = [[UIImageView alloc] initWithImage:image];
  // 对图像启用交互功能
  self.imageView.userInteractionEnabled = YES;
  self.imageView.center = self.view.center;
  [self.view addSubview:self.imageView];
  
  // 建立捏合手势识别器
  UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(doPinch:)];
  pinchGesture.delegate = self;
  [self.imageView addGestureRecognizer:pinchGesture];
  
  // 建立旋转手势识别器
  UIRotationGestureRecognizer *rotationGesture = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(doRorate:)];
  rotationGesture.delegate = self;
  [self.imageView addGestureRecognizer:rotationGesture];
}


- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
  // 允许捏合手势和旋转手势同时工作。否则,先开始的手势识别器会屏蔽另一个
  return YES;
}

// 根据手势识别器中获得的缩放比例和旋转角度对图像进行变换
- (void)transformImageView
{
  CGAffineTransform t = CGAffineTransformMakeScale(scale * previousScale, scale * previousScale);
  t = CGAffineTransformRotate(t, rotation + previousRotation);
  self.imageView.transform = t;
}

- (void)doPinch:(UIPinchGestureRecognizer *)gesture
{
  scale = gesture.scale;
  [self transformImageView];
  if (gesture.state == UIGestureRecognizerStateEnded) {
    previousScale = scale * previousScale;
    scale = 1;
  }
}


- (void)doRorate:(UIRotationGestureRecognizer *)gesture
{
  rotation = gesture.rotation;
  [self transformImageView];
  if (gesture.state == UIGestureRecognizerStateEnded) {
    previousRotation = rotation + previousRotation;
    rotation = 0;
  }
}


@end

六、自定义手势

//
// CheckMarkRecognizer.m
// CheckPlease
//
// Created by Jierism on 16/8/4.
// Copyright © 2016年 Jierism. All rights reserved.
//

#import "CheckMarkRecognizer.h"
#import "CGPointUtils.h"
#import <UIKit/UIGestureRecognizerSubclass.h> // 一个重要目的是使手势识别器的state属性可写,子类将使用这个机制断言我们所观察的手势已成功完成

// 设置检测范围
static CGFloat const kMinimunCheckMarkAngle = 80;
static CGFloat const kMaximumCheckMarkAngle = 100;
static CGFloat const kMinimumCheckMarkLength = 10;

@implementation CheckMarkRecognizer{
  // 前两个实例变量提供之前的线段
  CGPoint lastPreviousPoint;
  CGPoint lastCurrentPoint;
  // 画出的线段长度
  CGFloat lineLengthSoFar;
}


// 用lastPreviousPoint和lastCurrentPoint组成第一条线段,跟第二条线段形成角度去完成手势
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
  [super touchesBegan:touches withEvent:event];
  UITouch *touch = [touches anyObject];
  CGPoint point = [touch locationInView:self.view];
  lastPreviousPoint = point;
  lastCurrentPoint = point;
  lineLengthSoFar = 0.0;
}

- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
  [super touchesMoved:touches withEvent:event];
  UITouch *touch = [touches anyObject];
  CGPoint previousPoint = [touch previousLocationInView:self.view];
  CGPoint currentPoint = [touch locationInView:self.view];
  CGFloat angle = angleBetweenLines(lastPreviousPoint, lastCurrentPoint, previousPoint, currentPoint);
  if (angle >= kMinimunCheckMarkAngle && angle <= kMaximumCheckMarkAngle && lineLengthSoFar > kMinimumCheckMarkLength) {
    self.state = UIGestureRecognizerStateRecognized;
  }
  lineLengthSoFar += distanceBetweenPoints(previousPoint, currentPoint);
  lastPreviousPoint = previousPoint;
  lastCurrentPoint = currentPoint;
}

@end
//
// ViewController.m
// CheckPlease
//
// Created by Jierism on 16/8/4.
// Copyright © 2016年 Jierism. All rights reserved.
//

#import "ViewController.h"
#import "CheckMarkRecognizer.h"

@interface ViewController ()

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


@end

@implementation ViewController

- (void)viewDidLoad {
  [super viewDidLoad];
  // Do any additional setup after loading the view, typically from a nib.
  CheckMarkRecognizer *check = [[CheckMarkRecognizer alloc] initWithTarget:self action:@selector(doCheck:)];
  [self.view addGestureRecognizer:check];
  self.imageView.hidden = YES;
}

- (void)didReceiveMemoryWarning {
  [super didReceiveMemoryWarning];
  // Dispose of any resources that can be recreated.
}

- (void)doCheck:(CheckMarkRecognizer *)check
{
  self.imageView.hidden = NO;
  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    self.imageView.hidden = YES;
  });
}


@end

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • iOS应用开发中对UIImage进行截取和缩放的方法详解

    iOS应用开发中对UIImage进行截取和缩放的方法详解

    这篇文章主要介绍了iOS应用开发中对UIImage进行截取和缩放的方法,分别讲解了如何截取指定区域大小的UIImage以及缩放到指定大小和等比缩放的具体操作过程,需要的朋友可以参考下
    2016-04-04
  • iOS Touch ID指纹识别技术简介

    iOS Touch ID指纹识别技术简介

    这篇文章主要为大家详细介绍了iOS Touch ID指纹识别技术,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-04-04
  • iOS开发之UIScrollView控件详解

    iOS开发之UIScrollView控件详解

    UIScrollView是一个非常重要的控件,其可以展示比设备屏幕更大区域的内容,我们可以通过手指滑动来查看内容视图的每一部分内容,也可以通过手指捏合来对内容视图进行缩放操作,我们每天开发中都不断显式或隐式地与UIScrollView打交道,下面给大家详细介绍UIScrollView控件。
    2016-09-09
  • iOS多级列表实现代码

    iOS多级列表实现代码

    这篇文章主要为大家详细介绍了iOS多级列表实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-09-09
  • iOS中valueForKeyPath的常用方法法示例

    iOS中valueForKeyPath的常用方法法示例

    这篇文章主要给大家介绍了关于iOS中valueForKeyPath的常用方法法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-07-07
  • iOS开发实现随机图片验证码封装

    iOS开发实现随机图片验证码封装

    这篇文章主要介绍了iOS开发实现随机图片验证码封装,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-08-08
  • iOS中状态栏的基本使用方法汇总

    iOS中状态栏的基本使用方法汇总

    在iOS开发过程中,经常会设置状态栏的样式,所以下面这篇文章主要给大家介绍了关于iOS中状态栏的基本使用的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2018-07-07
  • IOS实现图片轮播无限循环效果

    IOS实现图片轮播无限循环效果

    这篇文章主要为大家详细介绍了IOS实现图片轮播无限循环效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-03-03
  • iOS沙盒视频缩略图及保存本地代码

    iOS沙盒视频缩略图及保存本地代码

    这篇文章主要为大家详细介绍了iOS沙盒视频缩略图及保存本地的代码,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-06-06
  • Objective-C中类和方法的定义以及协议的使用

    Objective-C中类和方法的定义以及协议的使用

    这篇文章主要介绍了Objective-C中类和方法的定义以及协议的使用,配合Mac下的Xcode IDE进行讲解,需要的朋友可以参考下
    2016-01-01

最新评论