美文网首页
hitText底层实现

hitText底层实现

作者: FrankHuang93 | 来源:发表于2017-12-26 10:49 被阅读18次

    事件是不是系统事件,是系统事件交给代理处理(比如程序启动完成时交给代理开启一个runRoop);

    不是系统事件就交给主窗口处理(keyWindow);

    主窗口会在视图中找到最合适的视图来处理触摸事件;

    事件传递的过程-事件处理的过程(谁能处理)----

    //  04-事件的产生和传递
    #import "XMGWindow.h"
    @implementation XMGWindow
    
    
    // 事件传递的时候调用
    // 什么时候调用:当事件传递给控件的时候,就会调用控件的这个方法,去寻找最合适的view
    // 作用:寻找最合适的view
    
    // point:当前的触摸点,point这个点的坐标系就是方法调用者
    //- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
    //{
    //    // 调用系统的做法去寻找最合适的view,返回最合适的view
    //    UIView *fitView = [super hitTest:point withEvent:event];
    //    
    ////    NSLog(@"fitView--%@",fitView);
    //    return fitView;
    //}
    
    // 作用:判断当前这个点在不在方法调用者(控件)上
    //- (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];
            
            // 把当前控件上的坐标系转换成子控件上的坐标系
            CGPoint childP = [self convertPoint:point toView:childView];
            
            UIView *fitView = [childView hitTest:childP withEvent:event];
            
            
            if (fitView) { // 寻找到最合适的view
                return fitView;
            }
        }
        // 循环结束,表示没有比自己更合适的view
        return self;
    }
    
    @end
    
    //  BaseView.m
    //  04-事件的产生和传递
    #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];
            
            // 把当前控件上的坐标系转换成子控件上的坐标系
         CGPoint childP = [self convertPoint:point toView:childView];
            
           UIView *fitView = [childView hitTest:childP withEvent:event];
            
            
            if (fitView) { // 寻找到最合适的view
                return fitView;
            }
            
            
        }
        
        // 循环结束,表示没有比自己更合适的view
        return self;
        
    }
    
    @end
    

    07-hitText练习1

    当从storyboard往类里面拖线的时候发现不能拖,可以反过来从 类文件(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
    {
        // 当前坐标系上的点转换到按钮上的点
        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
    {
        
        // 当前控件上的点转换到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
    

    转自:https://www.cnblogs.com/laugh/p/6668210.html

    相关文章

      网友评论

          本文标题:hitText底层实现

          本文链接:https://www.haomeiwen.com/subject/xpydgxtx.html