項(xiàng)目中很多時(shí)候需要擴(kuò)大點(diǎn)擊(交互)區(qū)域云矫,或子試圖超出了父視圖后,無法點(diǎn)擊或交互等廊散,我們可以通過響應(yīng)者鏈
-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
1免姿、在category里添加屬性
-(void)setEnlargedMargin:(CGFloat)enlargedMargin{
[self setEnlargeEdge:UIEdgeInsetsMake(enlargedMargin, enlargedMargin, enlargedMargin, enlargedMargin)];
}
-(void)setEnlargeEdge:(UIEdgeInsets)enlargeEdge{
//拓展后的rect
CGRect rect=CGRectMake(self.bounds.origin.x-enlargeEdge.left, self.bounds.origin.y-enlargeEdge.top, self.frame.size.width+enlargeEdge.left+enlargeEdge.right, self.frame.size.height+enlargeEdge.top+enlargeEdge.bottom);
//存入
objc_setAssociatedObject(self, &key_yjn_enlarged, @[NSStringFromCGRect(rect)], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
//掙脫父試圖束縛
CGRect windowConvertRect = [self convertRect:self.bounds toView:[[[UIApplication sharedApplication] delegate] window]];
[self freeView:self.superview rect:windowConvertRect enlargeEdge:enlargeEdge];
}
-(NSArray *)enlargedRect{
NSArray *enlargedArr = objc_getAssociatedObject(self, &key_yjn_enlarged);
if (enlargedArr) {
return enlargedArr;
}else{
return @[NSStringFromCGRect(self.bounds)];
}
}
2饼酿、掙脫父試圖束縛
#pragma mark - 掙脫父試圖束縛
-(void)freeView:(UIView *)superview rect:(CGRect)rect enlargeEdge:(UIEdgeInsets)enlargeEdge{
if(superview == nil) return;
//坐標(biāo)轉(zhuǎn)換
UIWindow * window=[[[UIApplication sharedApplication] delegate] window];
CGRect selfRect = [self convertRect:self.bounds toView:window];
CGRect superViewRect = [superview convertRect:superview.bounds toView:window];
if (CGRectContainsRect(superViewRect,selfRect)) {//完全包含
return;
}else{//不完全包含
NSMutableArray *rectArr = [NSMutableArray arrayWithArray:[superview enlargedRect]];
CGRect newRect = CGRectMake(rect.origin.x - superViewRect.origin.x, rect.origin.y - superViewRect.origin.y, rect.size.width, rect.size.height);
CGRect newEnlargeRect = CGRectMake(newRect.origin.x-enlargeEdge.left, newRect.origin.y-enlargeEdge.top, newRect.size.width+enlargeEdge.left+enlargeEdge.right, newRect.size.height+enlargeEdge.top+enlargeEdge.bottom);
[rectArr addObject:NSStringFromCGRect(newEnlargeRect)];
objc_setAssociatedObject(superview, &key_yjn_enlarged, rectArr, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
[self freeView:superview.superview rect:rect enlargeEdge:enlargeEdge];
}
}
3、響應(yīng)者鏈傳遞
#pragma mark - 響應(yīng)者鏈
-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event{
for (NSString *edgeStr in [self enlargedRect]) {
CGRect rect= CGRectFromString(edgeStr);
if (CGRectContainsPoint(rect,point)) {
return YES;
}
}
return NO;
}
-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
// 1.判斷下窗口能否接收事件
if (self.userInteractionEnabled == NO || self.hidden == YES || self.alpha <= 0.01){
return nil;
}
// 2.判斷下點(diǎn)在不在窗口上
// 不在窗口上
if ([self pointInside:point withEvent:event] == NO){
return nil;
}
// 3.從后往前遍歷子控件數(shù)組
int count = (int)self.subviews.count;
for (int i = count - 1; i >= 0; i--) {
// 獲取子控件
UIView *childView = self.subviews[i];
// 坐標(biāo)系的轉(zhuǎn)換,把窗口上的點(diǎn)轉(zhuǎn)換為子控件上的點(diǎn)
// 把自己控件上的點(diǎn)轉(zhuǎn)換成子控件上的點(diǎn)
CGPoint childP = [self convertPoint:point toView:childView];
UIView *fitView = [childView hitTest:childP withEvent:event];
if (fitView) {
// 如果能找到最合適的view
return fitView;
}
}
// 4.沒有找到更合適的view胚膊,也就是沒有比自己更合適的view
return self;
}
4故俐、【注】如果要掙脫束縛,請(qǐng)想把view加到父view上紊婉,如[self.view addSubview:view];后才能添加enlargeEdge屬性药版,否則不生效。demo地址https://github.com/yinjining/hitEnlarged