触摸 响应者链
事件: 由硬件捕获到用户的一个操作
iOS的事件: 触摸时间, 晃动事件, 远程控制事件
触摸事件: 支持多点触摸, 最多支持11个点, 6s以后的设备支持压感识别
如何捕获用户的触摸事件?
1.用户能够触摸的都是UIView或UIView的子类
2.创建一个UIView的子类
3.重写UIView的几个方法
和触摸相关的方法
一次触摸包含: 一次开始, 一次结束, 多次移动
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(@"开始触摸");
随机位置
self.center = CGPointMake(arc4random() % 176 + 100, arc4random() % 468 + 100);
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(@"触摸移动");
self.transform = CGAffineTransformRotate(self.transform, M_PI_4);
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(@"结束触摸");
变大
bounds修改, center不变, 以中点扩大或缩小
center修改, bounds不变
CGRect rect = self.bounds;
rect.size.width *= 1.1;
rect.size.height *= 1.1;
self.bounds = rect;
旋转
参数1: 原本视图的变形参数
参数2: 改变的弧度
self.transform = CGAffineTransformRotate(self.transform, M_PI_4);
}
当触摸时, 出现异常情况(比如来电话), 会阻断触摸的执行, 就是调用能触摸取消这个方法
触摸取消这个方法多用于异常情况
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(@"取消触摸");
}
@end
main.m
TouchView *touchView = [[TouchView alloc] initWithFrame:CGRectMake(0, 0, 50, 50)];
touchView.center = self.view.center;
touchView.backgroundColor = [UIColor colorWithRed:0.916 green:0.713 blue:1.000 alpha:1.000];
[self.view addSubview:touchView];
[touchView release];
DragView *dragView = [[DragView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
dragView.backgroundColor = [UIColor cyanColor];
[self.view addSubview:dragView];
[dragView release];
DragView.m
#import "DragView.h"
@interface DragView () {
CGPoint startPoint;
}
@end
@implementation DragView
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
touches: 存放触摸点的集合, 集合的元素类型UITouch
NSLog(@"%@", touches);
UITouch: 触摸类, 用于存放触摸点的信息(视图, 位置, 窗口, 点击次数, 点击状态), 继承于NSObject
UITouch *touch = [touches anyObject];
点击次数
NSLog(@"%lu", touch.tapCount);
时间戳(距离系统开机的秒数)
NSLog(@"%.lf", touch.timestamp);
触摸点在某个视图上的位置
CGPoint startPonit = [touch locationInView:self.superview];
NSLog(@"%@", NSStringFromCGPoint(startPonit));
触摸状态: 开始, 移动, 停止, 结束, 取消
NSLog(@"%ld", touch.phase);
触摸的压感
NSLog(@"%.2lf", touch.maximumPossibleForce);
event: 事件
UIEvent, 事件类, 继承于NSObject, 存储事件相关信息
NSLog(@"%@", event);
事件类型
NSLog(@"%ld", event.type);
获取某个触摸点
UITouch *touch = [touches anyObject];
给定坐标系, 获取触摸点的位置
startPoint = [touch locationInView:self.superview];
NSLog(@"startPoint: %@", NSStringFromCGPoint(startPoint));
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint endPoint = [touch locationInView:self.superview];
NSLog(@"endPoint: %@",NSStringFromCGPoint(endPoint));
//随鼠标移动
CGPoint point = self.center;
point.x += endPoint.x - startPoint.x;
point.y += endPoint.y - startPoint.y;
self.center = point;
startPoint = endPoint;
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
}
@end
响应者链: 多个响应者组成
UIResponder, 响应者类
查找触摸了哪个响应者(范围从大到小)
1.UIApplication, 应用类
2.window
3.UIViewController
4.view
5.view的子视图
注: 查找的过程组装响应者链
处理触摸事件(范围从小到大)
第一个能够处理响应事件者, 叫第一响应者
RootViewController.m
#import "RootViewController.h"
#import "TouchView.h"
#import "DragView.h"
@interface RootViewController ()<UITextFieldDelegate> {
UITextField *textField;
UITextField *passwordField;
}
@end
@implementation RootViewController
- (void)viewDidLoad {
textField = [[UITextField alloc] initWithFrame:CGRectMake(100, 100, 375 - 200, 40)];
textField.borderStyle = UITextBorderStyleRoundedRect;
textField.placeholder = @" 请输入用户名";
textField.returnKeyType = UIReturnKeyNext;
textField.delegate = self;
[self.view addSubview:textField];
[textField release];
passwordField = [[UITextField alloc] initWithFrame:CGRectMake(100, 160, 375 - 200, 40)];
passwordField.borderStyle = UITextBorderStyleRoundedRect;
passwordField.placeholder = @" 请输入密码";
passwordField.returnKeyType = UIReturnKeyDone;
passwordField.delegate = self;
[self.view addSubview:passwordField];
[passwordField release];
UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
button.frame = CGRectMake(140, 220, 375 - 280, 40);
button.titleLabel.font = [UIFont systemFontOfSize:20];
button.backgroundColor = [UIColor colorWithRed:0.233 green:1.000 blue:0.059 alpha:1.000];
[button setTitle:@"按钮" forState:UIControlStateNormal];
[button setTintColor:[UIColor whiteColor]];
[self.view addSubview:button];
[button addTarget:self action:@selector(press) forControlEvents:UIControlEventTouchUpInside];
让textField成为第一响应者
[textField becomeFirstResponder];
UIView *bgView = [[UIView alloc] initWithFrame:CGRectMake(100, 300, 100, 100)];
bgView.backgroundColor = [UIColor cyanColor];
userInteractionEnabled, 是否开启用户交互, 如果设置为NO, 阻断响应者链的执行
Bug: 超出父视图范围是无法被点击的
将userInteractionEnabled默认为NO的类
1.UILabel
2.UIImageView
bgView.userInteractionEnabled = NO;
[self.view addSubview:bgView];
[bgView release];
UITextField *textField2 = [[UITextField alloc] initWithFrame:CGRectMake(10, 50, 80, 40)];
textField2.borderStyle = UITextBorderStyleRoundedRect;
[bgView addSubview:textField2];
[textField2 release];
}
- (void)press {
NSLog(@"press");
让textField注销第一响应者
[textField resignFirstResponder];
[passwordField resignFirstResponder];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - UITextFieldDelegate
- (BOOL)textFieldShouldReturn:(UITextField *)textField1 {
if (textField1 == passwordField) {
[passwordField resignFirstResponder];
} else {
[passwordField becomeFirstResponder];
}
return YES;
}
@end
2015-10-20 20:20:37