触摸事件
一个软件 或者一个界面 对于 IOS 来说 都是触碰操作
1.创建根控制器 RootViewController 来操作
cmd+n
创建好之后 要将原有的根控制器替换
①引入头文件
②替换控制器
RootViewController *rootVC=[[RootViewController alloc]init];
// 用 rootVC 来初始化
self.window .rootViewController =rootVC;
[RootViewController release];
3.首先创建我们需要的视图类
RootViewController.m 中创建:
- (void)viewDidLoad {
[super viewDidLoad];
UIView *view = [[UIView alloc]initWithFrame:CGRectMake(60, 184, 200, 200)];
view .backgroundColor = [UIColor redColor];
[self.view addSubview:view];
[view release];
}
这样我们的类就会创建好
3.今天主要是让我们的视图类 对手指的触摸发生反应 比如移动 变色 之类的
所以我们要再建一个 TouchView
cmd+n 继承 UIView;
①在TouchView. m 中 想让一个视图对触摸做出反应
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
NSLog(@"%s",__FUNCTION__);
}
// 当触摸点在视图上移动的时候 触发
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
NSLog(@"%s",__FUNCTION__);
}
//触摸事件被意外终端的时候(比如 :电话进来)
-(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event{
NSLog(@"%s",__FUNCTION__);
}
//当触摸离开屏幕的时候触发
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
NSLog(@"%s",__FUNCTION__);
}
当我们在触摸设定好的视图后 控制台就会显示出运行的代码
② 需求:当我触摸视图的时候 背景色变化
解决:当我们触摸视图的时候 就是控制台显示的是began 所以 我们将控制背景色的代码写在 began 里面 颜色可以赋死值 也可以随机色
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
self.backgroundColor = [UIColor randomColor];
// 这里的 self 指的就是调用了这个方法的类 你又不知道是谁会用 所以用 self 最方便
// randomColor 是类目 完全体是:UIColor colorWithRed:COLORVALUE green:COLORVALUE blue:COLORVALUE alpha:1.0];
//但是太长了 所以我们用类目封起来 引用头文件 就可以用了
// 我们还想父类视图颜色变起来怎么办呢?用 superView
self.superview.backgroundColor = [UIColor randomColor];
NSLog(@"%s",__FUNCTION__);
}
随机色的类目:UIColor+Random
.h 里面
#import <UIKit/UIKit.h>
@interface UIColor (Random)
+(UIColor *)randomColor;
@end
.m 里面
#import "UIColor+Random.h"
#define COLORVALUE arc4random()%256/255.0
@implementation UIColor (Random)
+(UIColor *)randomColor{
return [UIColor colorWithRed:COLORVALUE green:COLORVALUE blue:COLORVALUE alpha:1.0];
}
@end
这里面 又有类目 又有宏 是不是感觉很厉害 都是因为程序员太懒了╮(╯▽╰)╭
注意!!:需求说的是触摸就变色 那么大王说我单击和双击 想发生不一样的改变
解决: 首先 判断 单击和双击 UITouch *touch = [touches anyObject];
获取手指,这时候得到在屏幕的手指数,获取其中的任意一个,注意存放手指的是个集合,我们没有办法指定获取其中的一个,只能随机取一个,因为里面只有一个的时候,取的肯定使我们想要的
UITouch *touch = [touches anyObject];
if (1 == touch.tapCount) {
tapCount是UITouch的一个属性,存放点击屏幕的次数
//当视图识别单击操作 就延迟执行下面方法 改变颜色 等待 是否会有双击发生
[self performSelector:@selector(changeMyselfBackgroundColor) withObject:nil afterDelay:.3];
//changeMyselfBackgroundColor 就是我们要走的方法 在下面写出来
// self.backgroundColor = [UIColor randomColor];
}else if(2==touch.tapCount){
// 当识别为双击的时候 取消之前的操作 (就是单击操作那个方法)
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(changeMyselfBackgroundColor) object:nil];
self.superview.backgroundColor = [UIColor randomColor];
self.backgroundColor = [UIColor randomColor];
}
}
-(void)changeMyselfBackgroundColor{
self.superview.backgroundColor = [UIColor randomColor];
}
这段代码的意思就是 判断摸了几次 touch.tapCount 然后 就走那个方法 这个时候要注意 你在上面的
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
//self.backgroundColor = [UIColor randomColor];
// self.superview.backgroundColor = [UIColor randomColor];
}
这段代码里 就要把里面的东西注掉 因为你触摸式从 began 开始的 但是你began 里面有方法 他就会直接走里面的方法 那你下面的判断就会不走
最后我们在 Controller .m 里面 创建 touchView 就可以运行了
RootViewController.m
TouchView *touchView = [[TouchView alloc]initWithFrame:CGRectMake(60, 184, 200, 200)];
touchView.backgroundColor = [UIColor redColor];
[self.view addSubview:touchView];
[touchView release];
③ 需求:我想拖动视图怎么办 让跟着我舞动起来
解决:那就是当我们触摸的时候触发效果呗
前提,在视图控制器中布局好视图
视图的拖拽最重要的是要切记,只要知道中心点center的移动距离和方向,就能算出整个视图的移动距离和方向
视图的拖拽是在移动函数中写的
注:我们用什么 就是创建什么 其他的可以不用管
同样 为了好看简洁我们的控制器 我们将MoveView 创建一个类
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
//实现
// 1.先获得手指对象
UITouch *touch = [touches anyObject];
// 2.获取当前位置的的手指位置 自身视图上
CGPoint currenPoint = [touch locationInView:self];
// 3.获取手指之前的位置
CGPoint previousPoint = [touch previousLocationInView:self];
// 计算移动的增量 就是让之前和之后相减
CGFloat dx = currenPoint.x - previousPoint.x;
CGFloat dy = currenPoint.y - previousPoint.y;
CGPoint center = self.center;
self.center = CGPointMake(center.x+dx, center.y+dy);
}
@end
最后我们在 Controller .m 里面 创建 touchView 就可以运行了
RootViewController.m
MoveView *moveView = [[MoveView alloc]initWithFrame:CGRectMake(60, 184, 200, 200)];
moveView.backgroundColor = [UIColor randomColor ];
[self.view addSubview:moveView];
[moveView release];
④需求:这个图片我没看清出 想放大:
解决: OK 这个就是等比缩放 不变的是中心点 我们算出放大前后的比例就可以了 同样 封装一个新的类 PinchView
在实现视图的捏合的时候要注意,这里需要用到两个手指对象,但是系统默认的是单点触摸,所以要重写init方法
PinchView.m
-(instancetype)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if (self) {
// IOS 支持多点触摸 但是默认只能单点触摸
self.multipleTouchEnabled = YES;
}return self;
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
if (1 == touches.count) {
return;
}else{
// 1.取出两个手指对象所在的集合 是一个数组
NSArray *allTouch = [touches allObjects];
//2.获取手指对象
UITouch *touch1 = [allTouch firstObject];
UITouch *touch2 = [allTouch lastObject];
//获得两个手指的当前位置
CGPoint currentPoint = [touch1 locationInView:self];
CGPoint previousPoint = [touch2 previousLocationInView:self];
// 4.计算当前两个点得手指距离
CGFloat currentDistance = [self distanceFromPoint:currentPoint toPoint:previousPoint];
// 5.获取之前两个手指的位置
CGPoint previousFirstPoint = [touch1 previousLocationInView:self];
CGPoint previousSecondPoint = [ touch2 previousLocationInView:self];
// 获取两个手指之间的距离
CGFloat previousDistance = [self distanceFromPoint:previousFirstPoint toPoint:previousSecondPoint];
// 获取缩小的前后的比例
CGFloat rate = currentDistance/previousDistance;
// 缩放视图大小,但中心点不会变 这时候选择修改 Bounds 就可以
self.bounds = CGRectMake(0, 0, self.frame.size.width*rate, self.frame.size.height*rate);
}
}
//封装计算两个点距离的方法
-(CGFloat)distanceFromPoint :(CGPoint)fromPoint toPoint:(CGPoint)toPoint{
CGFloat dx = fromPoint.x -toPoint.x;
CGFloat dy = fromPoint.y - toPoint.y;
return sqrt(dx*dx+dy*dy);
}
最后我们在 Controller .m 里面 创建 touchView 就可以运行了
RootViewController.m
PinchView *pinchView = [[PinchView alloc]initWithFrame:CGRectMake(10, 20, 300, 528)];
pinchView.backgroundColor = [UIColor randomColor];
[self.view addSubview:pinchView];
[pinchView release];
你不写最后在 controller 里面 他就找不到这个方法 我们怎么实现操作呢?
因为我们在 TouchView 里面 实现了 拖动 变色 等比缩放 所以 .m 里面的最终形态应该是这样的;
#import "TouchView.h"
#import "UIColor+Random.h"
@implementation TouchView
//如果想让一个视图 对触摸事件 做出回应
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
NSLog(@"%s",__FUNCTION__);
self.backgroundColor = [UIColor randomColor];
//父视图的属性
// 给添加类目
self.superview.backgroundColor = [UIColor randomColor];
//调用改变中心点得方法
[self changeMyselfCenter];
//UITouch 点击类
}
// 当触摸点在视图上移动的时候 触发
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [touches anyObject];
if (2 ==touch.tapCount) {
}
NSLog(@"%s",__FUNCTION__);
}
//触摸事件被意外终端的时候(比如 :电话进来)
-(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event{
NSLog(@"%s",__FUNCTION__);
}
//当触摸离开屏幕的时候触发
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
//touchs 存放手指对象
UITouch *touch = [touches anyObject];
if (1 == touch.tapCount) {
//当视图识别单击操作 就延迟执行下面方法 改变颜色 等待 是否会有双击发生
[self performSelector:@selector(changeMyselfBackgroundColor) withObject:nil afterDelay:0.3];
// self.backgroundColor = [UIColor randomColor];
}else if(2==touch.tapCount){
// 当识别为双击的时候 取消之前的操作 (就是单击操作那个方法)
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(changeMyselfBackgroundColor) object:nil];
self.superview.backgroundColor = [UIColor randomColor];
}
NSLog(@"%s",__FUNCTION__);
}
-(void)changeMyselfCenter{
self.center = CGPointMake(arc4random()%200+100, arc4random()%400+120);
}
-(void)changeMyselfBackgroundColor{
self.backgroundColor = [UIColor randomColor];
}
@end
===================响应者链===================
1.有多个响应者对象组成的链(父视图子视图)
UIResponder 响应者类,iOS中所有能响应事件(触摸、晃动、远程事件)的对象都是响应者,系统定义了一个抽象的父类UIResponder来表示响应者,其子类都是响应者。
硬件检测到触摸操作,会将信息交给UIApplication,开始检测。
UIApplication -> window -> viewController -> view ->检测所有子视图,最终确认碰触位置,完成响应者链的查询过程。
2.处理触碰事件
检测到响应者后,实现touchesBegan:withEvent:等方法,即处理事件。
如果响应者没有处理事件,事件会向下传递,如果没有响应者处理,则丢弃触摸事件。
事件处理的顺序与触摸检测查询相反,触摸的子视图 -> view -> viewController -> window -> UIApplication
3.阻断响应者链,
响应者链可以被打断,无妨完成检测查询过程,视图类的属性:userInteractionEnabled,关闭后能阻断查询过程
要实现那个视图的响应,我们就要在他的.m中重写响应方法,所以一般在需要一个响应视图的时候我们会创建一个子类,这样能够在.m中写响应方法,如我们要实现UIView的一个视图的响应,我们就要建一个UIView的子类,在子类中重写方法。在重写方法的时候我们一般通过tag值来确定访问的对象。
注:有一个方法我们没有用到 就是Cancelled 后面我们会学到
1.将我们的需求选好地方创建,比如 began move
2.封装之后记得在你想使用的里面引入头文件
3.在单击双击的时候 要将之前在 began 写的变色注掉 还要注意
4.触摸事件 就是响应者链的体现