美文网首页
改变UIView的点击范围

改变UIView的点击范围

作者: 伶俐ll | 来源:发表于2020-08-21 11:56 被阅读0次

文章原地址:https://www.jianshu.com/p/cd7d7c30dba4

前言

UI给的图有时候很小,或者有个需求需要我们扩大button的点击区域

我们一般的操作是在button 上添加一个view 增加点击事件,但是我们还有其他更方便的方法去扩大button 的点击区域。

思考

怎样来实现这个功能呢?又有多少种方式可以实现呢?下面一一来讲。

  • 理解事件传递过程,用这个来实现扩大点击范围
  • 使用Runtime机制扩大点击范围

时间传递过程

当用户点击屏幕后:

  1. UIApplication 先响应事件。

  2. 然后传递给UIWindow。

  3. 如果window可以响应。就开始遍历window的subviews。遍历原则是:从离用户最近的那个子视图去遍历

  4. 遍历的过程中,如果第一个遍历的view1可以响应,那就遍历这个view1的subviews(依次这样不停地查找,直至查找到合适的响应事件view)。

  5. 如果view1不可以响应,那就开始对view2进行判断和子视图的遍历。依次类推view3,view4……

  6. 如果最后没有找到合适的响应view,这个消息就会被抛弃。这个就是iOS中的事件链。

如下图所示:

image

然而事件的响应链条是事件链条的逆向,根据视图层级的添加顺序从后往前的

扩大UIButton范围关键的两个方法:UIView方法

// recursively calls -pointInside:withEvent:. point is in the receiver's coordinate system
- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event;

// default returns YES if point is in bounds
- (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event;

第一种方法

继承与UIButton,重写下面的方法:

-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent*)event {
    CGRect bounds = self.bounds;
    //扩大原热区直径至26,可以暴露个接口,用来设置需要扩大的半径。
    CGFloat widthDelta = 26;
    CGFloat heightDelta = 26;
    //CGRect CGRectOffset(CGRect rect, CGFloat dx, CGFloat dy)是以rect为中心,根据dx和dy来实现缩小或扩大。正值表示缩小,负值表示扩大。
    bounds = CGRectInset(bounds, -0.5 * widthDelta, -0.5 * heightDelta);
    //如果用户点击的这个点在CGRect里面返回YES
    return CGRectContainsPoint(bounds, point);
}

第二种:重写方法 - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {

    CGRect rectRange = CGRectInset(self.bounds, -30.0, -30.0);

    if (CGRectContainsPoint(rectRange, point)) {
        return self;
    }else{
        return nil;
    }

    return self;
}

其实我们上面所做的变化其实如果仔细看点击区域还是个矩形,如果需要我们将点击区域规定在圆形范围 内,我们可以这样做:

-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
    [super hitTest:point withEvent:event];

    CGPoint center = CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2);

   //当然这个半径也可以扩大
    CGFloat raidus = self.frame.size.height >= self.frame.size.width ?self.frame.size.width/2 :self.frame.size.width/2;

   //传入中心点 实时点击点 与半径判断 点击点是否在半径区域内
    BOOL pointInRound =[self touchPointInsideCircle:center radius:raidus targetPoint:point];

    if (pointInRound) {
        return self;
    }else
    {
        return nil;
    }
}

//用来判断 圆形点击区域
- (BOOL)touchPointInsideCircle:(CGPoint)center radius:(CGFloat)radius targetPoint:(CGPoint)point {
    CGFloat dist = sqrtf((point.x - center.x) * (point.x - center.x) +
                         (point.y - center.y) * (point.y - center.y));
    return (dist <= radius);
}

相关文章

网友评论

      本文标题:改变UIView的点击范围

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