iOS hitTest与PointInside方法

来源:互联网 发布:怎样提高淘宝店排名 编辑:程序博客网 时间:2024/05/22 10:44
作用:寻找最适合的View    参数:当前手指所在的点.产生的事件    返回值:返回谁, 谁就是最适合的View.    什么时候用调用:只要一个事件,传递给一个控件时, 就会调用这个控件的hitTest方法    -(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event    作用:判断point在不在方法调用者上    point:必须是方法调用者的坐标系    什么时候调用:hitTest方法底层会调用这个方法,判断点在不在控件上.    -(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event{        return YES;    }    hitTest底层实现:        1.判断当前能不能接收事件          if(self.userInteractionEnabled == NO || self.hidden == YES || self.alpha <= 0.01)           return  nil;        2.判断触摸点在不在当前的控件上         if(![self pointInside:point withEvent:event]) return nil;        3.从后往前遍历自己的子控件        int count = (int)self.subviews.count;        for (int i = count - 1; i >= 0;i-- ) {        UIView *childV = self.subviews[i];        把当前坐标系上的点转换成子控件坐标系上的点.        CGPoint childP = [self convertPoint:point toView:childV];        判断自己的子控件是不是最适合的View        UIView *fitView = [childV hitTest:childP withEvent:event];        如果子控件是最适拿的View,直接返回            if (fitView) {                return  fitView;            }        }        4.自己就是最适合的View            return self.

hitTest使用场景一:

业务逻辑:        底部一个按钮, 按钮的上面有一个View,遮挡在按钮的上面.        点击View时, View接收事件,当发现点击的点在按钮的位置时, 让底部的按钮处理事件.    实现思路:        实现View的touchBegain方法,先坚听UIView的点击.        并去实现UIView的HitTest方法, 在hitTest方法当中通过把当前点转换成按钮所在的坐标系            CGPoint btnP = [self convertPoint:point toView:self.btn];        转换过后查看当前点在不在按钮上,如果在按钮上,就直接返回按钮.        如果有在按钮上,保持系统默认做法.    实现代码:        -(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];            }        }

hitTest使用场景二:

业务逻辑:         按钮可以随着手指拖动而拖动.拖动过程当中,按钮当中的子控件也跟着拖动.        让超过按钮的子控件也能够响应事件,一般情况下,当一个控件超过他的父控件的时候,是不能够接收事件的.         现在要做的事情就让超过父控件的按钮也能够响应事件.    实现思路:        先办到让按钮能够跟随着手指移动而移动.        实现按钮的touchesMoved方法,在touchesMoved方法当中,获得当前手指所在的点.以前上一个点.        分别计算X轴的偏移量以及Y轴的偏移量.        然后修改当前按钮的transform让按钮办到能够跟随着手指移动而移动.        第二步, 实现按钮的hitTest方法.        在该方法当中去判断当前的点在不在按钮的子控件上.        如果在按钮的子控件上.就返回按钮的子控件如果不在的话, 就保持系统的默认做法.    实现代码:        第一步,让按钮能够跟随着手指移动而移动        -(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{            获取当前的手指            UITouch *touch = [touches anyObject];            获取当前手指所在的点            CGPoint curP = [touch locationInView:self];            获取当前手指的上一个点            CGPoint preP = [touch previousLocationInView:self];            计算X轴的偏移量            CGFloat offsetX = curP.x - preP.x;            计算Y轴的偏移量            CGFloat offsetY = curP.y - preP.y;             修改按钮的形变,让按钮能够移动.               self.transform = CGAffineTransformTranslate(self.transform, offsetX, offsetY);            }        第二步,实现hitTest方法,判断手指当前所在的点在不在按钮的子控件上.        -(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{            把当前所在的点转换成按钮子控件上面的点            CGPoint chatP =  [self convertPoint:point toView:self.chatBtn];            判断转换后的点在不在按钮的控件上.            if ([self.chatBtn pointInside:chatP withEvent:event]) {如果在                直接返回,也就意味着,当前最适合的View,就是这个按钮                return self.chatBtn;            }else{如果不在,那么就保持系统原有做法.              return  [super hitTest:point withEvent:event];            }        }
原创粉丝点击