博客> 扩大响应范围(个人笔记,复制的)
扩大响应范围(个人笔记,复制的)
2019-07-18 02:27 评论:0 阅读:191 suifumin
扩大响应范围

1.首先我们需要知道点击无反应的四种可能情况 1)UI控件被隐藏 2) 透明度小于0.01 3.无法交互userInteractionEnabled = NO 4.超出父视图的范围 今天要讨论的是超出父视图的这种情况下怎么扩大点击范围, hitTest:withEvent: //这个方法使返回最佳的响应视图的 pointInside:withEvent://这个是判断当前的view是否具备响应的能力的。  248E8EC9-8752-479E-9392-748ABA0AFAFC.png

当我点击超出绿色那一部分红色区域的时候同样具有响应事件的能力。 具体做法。

  • (UIView )hitTest:(CGPoint)point withEvent:(UIEvent )event { UIView view = [super hitTest:point withEvent:event]; if (view == nil) { for (UIView subView in self.subviews) { CGPoint p = [subView convertPoint:point fromView:self]; if (CGRectContainsPoint(subView.bounds, p)) { view = subView; } } } return view; } 思路:获取点击区域的父视图的view,遍历这个父视图的所有子视图。判断这个点击区域是不是在这个子视图上,如果在就返回,不在就返回父视图。 、、----------------------------------------------------------------------------------------------------- 第二种扩大场景 比如设置一个按钮的宽和高为100,100,想要在他四种分别延伸50的距离来扩大响应区域。 这个时候就不能按照上面的而方法来处理了。   首先,创建一个UIButton的Category,起名为EnlargeTouchArea,设置一个外界可访问的方法setEnlaEdgeWithTop:right:bottom:left,在使用时也只需使用这个方法即可,传入的四个参数分别是上、右、下、左的扩展距离。

//  UIButton+EnlargeTouchArea.h

import

import

@interface UIButton (EnlargeTouchArea)

  • (void)setEnlargeEdgeWithTop:(CGFloat) top right:(CGFloat) right bottom:(CGFloat) bottom left:(CGFloat) left;

@end

        然后导入,所有Runtime的黑魔法都在这里

// UIButton+EnlargeTouchArea.m

import "UIButton+EnlargeTouchArea.h"

import

@implementation UIButton (EnlargeTouchArea)

static char topNameKey; static char rightNameKey; static char bottomNameKey; static char leftNameKey;

        objc_setAssociatedObject是一个C语言函数,这个函数被称之为“关联API”,它的作用是把top、right、bottom、left这四个从外界获取到的值与本类(self)关联起来,然后设置一个static char作为能够找到他们的Key

  • (void) setEnlargeEdgeWithTop:(CGFloat) top right:(CGFloat) right bottom:(CGFloat) bottom left:(CGFloat) left { objc_setAssociatedObject(self, &topNameKey, [NSNumber numberWithFloat:top], OBJC_ASSOCIATION_COPY_NONATOMIC); objc_setAssociatedObject(self, &rightNameKey, [NSNumber numberWithFloat:right], OBJC_ASSOCIATION_COPY_NONATOMIC); objc_setAssociatedObject(self, &bottomNameKey, [NSNumber numberWithFloat:bottom], OBJC_ASSOCIATION_COPY_NONATOMIC); objc_setAssociatedObject(self, &leftNameKey, [NSNumber numberWithFloat:left], OBJC_ASSOCIATION_COPY_NONATOMIC); }

       objc_getAssociatedObject同样也是一个关联API(c语言函数),它可以通过刚刚设置的Key找到上个方法中从外界传入的top、right、bottom、left,这个api和obj_setAssociatedObject一起使用就可以达到给已有类扩展属性的效果。最后我们通过self.bounds设置一个新的CGRect,作为扩大后的点按区域,并且返回

  • (CGRect) enlargedRect { NSNumber topEdge = objc_getAssociatedObject(self, &topNameKey); NSNumber rightEdge = objc_getAssociatedObject(self, &rightNameKey); NSNumber bottomEdge = objc_getAssociatedObject(self, &bottomNameKey); NSNumber leftEdge = objc_getAssociatedObject(self, &leftNameKey); if (topEdge && rightEdge && bottomEdge && leftEdge) { return CGRectMake(self.bounds.origin.x - leftEdge.floatValue, self.bounds.origin.y - topEdge.floatValue, self.bounds.size.width + leftEdge.floatValue + rightEdge.floatValue, self.bounds.size.height + topEdge.floatValue + bottomEdge.floatValue); } else { return self.bounds; } }        

       这个方法UIView的一个实例方法,作用是,捕获当前的UITouch事件中的触摸点,检测它是否在最上层的子视图内,如果不是的话就递归检测其父视图。这样的话,我们就只是将当前某一个触摸的point与某一个rect进行比较,并没有改变Button真实的frame,从而真正的从逻辑上达到了只是扩大点按区域的效果。

  • (UIView) hitTest:(CGPoint) point withEvent:(UIEvent) event { CGRect rect = [self enlargedRect]; if (CGRectEqualToRect(rect, self.bounds)) { return [super hitTest:point withEvent:event]; } return CGRectContainsPoint(rect, point) ? self : nil; }
收藏
0
sina weixin mail 回到顶部