判断点击、触摸区域是否属于当前UIView

简介

UIView提供了一个pointInside:withEvent:方法,用于判断用户点击的点是否属于当前这个视图,其定义如下:

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

用法示例

比如说美工给我们提供了一张圆形的底色透明的png图片,如下所示:


�圆形透明图片.png

现在要求点击图片上圆形部分可以触发单击事件,点击图片的其它区域不做任何反应,这里有2种方案可以实现:

方案1

把图片做成UIButton,并设置UIButton的layer.cornerRadius为圆形的半径:

UIImage *image = [UIImage imageNamed:@"圆形透明图片.png"];

UIButton *btnView = [UIButton buttonWithType:UIButtonTypeCustom];
[btnView setImage:image forState:UIControlStateNormal];
btnView.frame = CGRectMake(0, 0, image.size.width, image.size.height);
// 设置UIButton为圆形,并且半径与图片半径一致
btnView.layer.cornerRadius = image.size.width / 2.0;
btnView.clipsToBounds = YES;
[btnView addTarget:self action:@selector(buttonTapped) 
              forControlEvents:UIControlEventTouchUpInside];
方案2

pointInside:withEvent:来实现
先为UIButton定义一个扩展UIButton (Circle),用于设置圆形图片半径,并重写pointInside:withEvent:方法

#import <UIKit/UIKit.h>
@interface UIButton (Circle)
// 设置图片的圆角半径
- (void)setCornerRadius:(CGFloat)cornerRadius;
@end


#import "UIButton+Circle.h"
#import "objc/runtime.h"
static char cornerRadiusKey;

@implementation UIButton (Circle)
- (void)setCornerRadius:(CGFloat)cornerRadius
{
    objc_setAssociatedObject(self, &cornerRadiusKey, [NSString stringWithFormat:@"%f", cornerRadius], OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (CGFloat)getCornerRadius
{
    NSString *str = objc_getAssociatedObject(self, &cornerRadiusKey);
    return (str && str.length) ? [str floatValue] : 0;
}
/**
 * 计算point点与center点的距离,
 * 如果 <= cornerRadius,则表示点击了图片的内容区域,视为有有效点击
 * 如果 > cornerRadius, 则表示点击了图片的空白区域,视为无效点击
 */
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
    CGPoint center = CGPointMake(self.bounds.size.width / 2.0, self.bounds.size.height / 2.0);
    CGFloat distance = sqrt(pow(point.x - center.x, 2) + pow(point.y - center.y, 2));
    return distance <= [self getCornerRadius];
}
@end

下面是使用方式,:

@implementation ViewController
- (void)viewDidLoad
{
    UIImage *image = [UIImage imageNamed:@"圆形透明图片.png"];
    UIButton *btnView = [UIButton buttonWithType:UIButtonTypeCustom];
    [btnView setImage:image forState:UIControlStateNormal];
    btnView.frame = CGRectMake(100, 100, image.size.width, image.size.height);
    // 设置半径
    [btnView setCornerRadius:image.size.width / 2.0];
    [btnView addTarget:self action:@selector(buttonTapped)
                  forControlEvents:UIControlEventTouchUpInside];
   
    [self.view addSubview:btnView];
}
- (void)buttonTapped
{
    NSLog(@"button tapped");
}
@end

运行后可以看到:

  • 当点击了图片内容区域,则会触发buttonTapped方法
  • 当点击了图片的空白区域,没有任何反应。

总结

方案1 �方案2
优点 代码简单,适用广 处理比较灵活
缺点 有些特殊情况处理不了 稍显复杂,适用于一些特殊情况
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 好奇触摸事件是如何从屏幕转移到APP内的?困惑于Cell怎么突然不能点击了?纠结于如何实现这个奇葩响应需求?亦或是...
    Lotheve阅读 58,021评论 51 603
  • 在iOS开发中经常会涉及到触摸事件。本想自己总结一下,但是遇到了这篇文章,感觉总结的已经很到位,特此转载。作者:L...
    WQ_UESTC阅读 6,133评论 4 26
  • -- iOS事件全面解析 概览 iPhone的成功很大一部分得益于它多点触摸的强大功能,乔布斯让人们认识到手机其实...
    翘楚iOS9阅读 3,003评论 0 13
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 173,349评论 25 708
  • 《小飞侠彼得潘》: 一开始还以为是狼叔的那个彼得潘,原来不是……好吧,搞错了。彼得潘也是被拍烂的一个题材,很适合小...
    老扬阅读 780评论 0 1