hitText底層實現(xiàn)

事件是不是系統(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中喝噪;


image.png

image.png
//  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


image.png
//  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

轉(zhuǎn)自:https://www.cnblogs.com/laugh/p/6668210.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末酝惧,一起剝皮案震驚了整個濱河市榴鼎,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌晚唇,老刑警劉巖巫财,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異哩陕,居然都是意外死亡平项,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進店門悍及,熙熙樓的掌柜王于貴愁眉苦臉地迎上來闽瓢,“玉大人,你說我怎么就攤上這事心赶】鬯希” “怎么了?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵缨叫,是天一觀的道長椭符。 經(jīng)常有香客問我,道長弯汰,這世上最難降的妖魔是什么艰山? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮咏闪,結(jié)果婚禮上曙搬,老公的妹妹穿的比我還像新娘。我一直安慰自己鸽嫂,他們只是感情好纵装,可當我...
    茶點故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著据某,像睡著了一般橡娄。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上癣籽,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天挽唉,我揣著相機與錄音滤祖,去河邊找鬼。 笑死瓶籽,一個胖子當著我的面吹牛匠童,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播塑顺,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼汤求,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了严拒?” 一聲冷哼從身側(cè)響起扬绪,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎裤唠,沒想到半個月后挤牛,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡巧骚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年赊颠,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片劈彪。...
    茶點故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡竣蹦,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出沧奴,到底是詐尸還是另有隱情痘括,我是刑警寧澤,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布滔吠,位于F島的核電站纲菌,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏疮绷。R本人自食惡果不足惜翰舌,卻給世界環(huán)境...
    茶點故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望冬骚。 院中可真熱鬧椅贱,春花似錦、人聲如沸只冻。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽喜德。三九已至山橄,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間舍悯,已是汗流浹背航棱。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工睡雇, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人饮醇。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓入桂,卻偏偏與公主長得像,于是被迫代替她去往敵國和親驳阎。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,925評論 2 344