事件是不是系統(tǒng)事件?如果是系統(tǒng)事件就交給代理處理(比如程序啟動完成時交給代理開啟一個runRoop)光绕;
如果不是系統(tǒng)事件就交給主窗口處理(keyWindow);
主窗口會在視圖中找到最合適的視圖來處理觸摸事件灰粮;
事件傳遞的過程-事件處理的過程(誰能處理)----
// 04-事件的產(chǎn)生和傳遞
#import "XMGWindow.h"
@implementation XMGWindow
// 事件傳遞的時候調(diào)用
// 什么時候調(diào)用:當事件傳遞給控件的時候抢腐,就會調(diào)用控件的這個方法,去尋找最合適的view
// 作用:尋找最合適的view
// point:當前的觸摸點,point這個點的坐標系就是方法調(diào)用者
//- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
//{
// // 調(diào)用系統(tǒng)的做法去尋找最合適的view烧给,返回最合適的view
// UIView *fitView = [super hitTest:point withEvent:event];
//
//// NSLog(@"fitView--%@",fitView);
// return fitView;
//}
// 作用:判斷當前這個點在不在方法調(diào)用者(控件)上
//- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
//{
// return YES;
//}
//- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
//{
//// NSLog(@"%s",__func__);
//}
// 點擊黃色視圖 -》 事件 -》 UIApplication -> UIWindow
// 因為所有的視圖類都是繼承BaseView
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
// 1.判斷當前控件能否接收事件
if (self.userInteractionEnabled == NO || self.hidden == YES || self.alpha <= 0.01) return nil;
// 2. 判斷點在不在當前控件
if ([self pointInside:point withEvent:event] == NO) return nil;
// 3.從后往前遍歷自己的子控件
NSInteger count = self.subviews.count;
for (NSInteger i = count - 1; i >= 0; i--) {
UIView *childView = self.subviews[i];
// 把當前控件上的坐標系轉(zhuǎn)換成子控件上的坐標系
CGPoint childP = [self convertPoint:point toView:childView];
UIView *fitView = [childView hitTest:childP withEvent:event];
if (fitView) { // 尋找到最合適的view
return fitView;
}
}
// 循環(huán)結(jié)束,表示沒有比自己更合適的view
return self;
}
@end
// BaseView.m
// 04-事件的產(chǎn)生和傳遞
#import "BaseView.h"
@implementation BaseView
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(@"%@---touchesBegan",[self class]);
}
// UIApplication -> [UIWindow hitTest:withEvent:] -> whiteView hitTest:withEvent
// 因為所有的視圖類都是繼承BaseView
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
// NSLog(@"%@--hitTest",[self class]);
// return [super hitTest:point withEvent:event];
// 1.判斷當前控件能否接收事件
if (self.userInteractionEnabled == NO || self.hidden == YES || self.alpha <= 0.01) return nil;
// 2. 判斷點在不在當前控件
if ([self pointInside:point withEvent:event] == NO) return nil;
// 3.從后往前遍歷自己的子控件
NSInteger count = self.subviews.count;
for (NSInteger i = count - 1; i >= 0; i--) {
UIView *childView = self.subviews[i];
// 把當前控件上的坐標系轉(zhuǎn)換成子控件上的坐標系
CGPoint childP = [self convertPoint:point toView:childView];
UIView *fitView = [childView hitTest:childP withEvent:event];
if (fitView) { // 尋找到最合適的view
return fitView;
}
}
// 循環(huán)結(jié)束,表示沒有比自己更合適的view
return self;
}
@end
07-hitText練習1
當從storyboard往類里面拖線的時候發(fā)現(xiàn)不能拖,可以反過來從 類文件(xxx.m)拖到storyboard中喝噪;
// YellowView.m
// 07-hitText練習1
#import "YellowView.h"
@interface YellowView ()
@property (nonatomic, weak) IBOutlet UIButton *btn;
@end
@implementation YellowView
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
// 當前坐標系上的點轉(zhuǎn)換到按鈕上的點
CGPoint btnP = [self convertPoint:point toView:self.btn];
// 判斷點在不在按鈕上
if ([self.btn pointInside:btnP withEvent:event]) {
// 點在按鈕上
return self.btn;
}else{
return [super hitTest:point withEvent:event];
}
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(@"%@",self.btn);
NSLog(@"%s",__func__);
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
// Drawing code
}
*/
@end
08-hitText練習2
// ViewController.m
// 08-hitText練習2
#import "ViewController.h"
#import "PopBtn.h"
@interface ViewController ()
@end
@implementation ViewController
- (IBAction)popChatView:(PopBtn *)sender {
// 彈出對話框
UIButton *chatView = [UIButton buttonWithType:UIButtonTypeCustom];
chatView.bounds = CGRectMake(0, 0, 200, 200);
chatView.center = CGPointMake(100, -100);
[chatView setBackgroundImage:[UIImage imageNamed:@"對話框"] forState:UIControlStateNormal];
[chatView setBackgroundImage:[UIImage imageNamed:@"小孩"] forState:UIControlStateHighlighted];
sender.chatView = chatView;
[sender addSubview:chatView];
}
- (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.
}
@end
// PopBtn.h
// 08-hitText練習2
#import <UIKit/UIKit.h>
@interface PopBtn : UIButton
@property (nonatomic, weak) UIButton *chatView;
@end
// PopBtn.m
// 08-hitText練習2
#import "PopBtn.h"
@implementation PopBtn
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
// 當前控件上的點轉(zhuǎn)換到chatView上
CGPoint chatP = [self convertPoint:point toView:self.chatView];
// 判斷下點在不在chatView上
if ([self.chatView pointInside:chatP withEvent:event]) {
return self.chatView;
}else{
return [super hitTest:point withEvent:event];
}
}
//找到合適的事件處理對象础嫡,來處理事件;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
// 獲取UITouch
UITouch *touch = [touches anyObject];
// 獲取當前的點
CGPoint curP = [touch locationInView:self];
// 獲取上一個的點
CGPoint preP = [touch previousLocationInView:self];
// 獲取偏移量
CGFloat offsetX = curP.x - preP.x;
CGFloat OffsetY = curP.y - preP.y;
// 修改控件的位置
CGPoint center = self.center;
center.x += offsetX;
center.y += OffsetY;
self.center = center;
}
@end