CALayer处理点击事件

我们知道CALayer不能直接响应任何响应链事件,所以不能直接处理点击事件。但是依然有两种方法可以帮助我们实现捕捉并且处理CALayer的点击事件。
运行效果:

运行效果

方法一:convertPoint:

@interface CALayerPointVC ()
@property (nonatomic, strong) CALayer *redLayer;
@property (nonatomic, strong) CALayer *yellowLayer;
@end

@implementation CALayerPointVC

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    self.redLayer = [CALayer layer];
    self.redLayer.frame = CGRectMake(100, 100, 100, 100);
    self.redLayer.backgroundColor = [UIColor redColor].CGColor;
    [self.view.layer addSublayer:self.redLayer];
    
    self.yellowLayer = [CALayer layer];
    self.yellowLayer.frame = CGRectMake(100, 200, 100, 100);
    self.yellowLayer.backgroundColor = [UIColor yellowColor].CGColor;
    [self.view.layer addSublayer:self.yellowLayer];
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    CGPoint point = [[touches anyObject] locationInView:self.view];
    CGPoint redPoint = [self.redLayer convertPoint:point fromLayer:self.view.layer];
    CGPoint yellowPoint = [self.yellowLayer convertPoint:point fromLayer:self.view.layer];
    if ([self.redLayer containsPoint:redPoint]) {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"point red" message:@"" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
        [alert show];
    }
    if ([self.yellowLayer containsPoint:yellowPoint]) {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"point yellow" message:@"" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
        [alert show];
    }
}

首先使用locationInView方法获取到点击在view上的坐标。convertPoint:fromLayer :方法传入一个CGPoint来转换坐标系,将在其父图层上的坐标转换为相对于图层自身的坐标,这样转换坐标系的方法还有以下几个:

- (CGPoint)convertPoint:(CGPoint)point fromLayer:(CALayer *)layer; 
- (CGPoint)convertPoint:(CGPoint)point toLayer:(CALayer *)layer; 
- (CGRect)convertRect:(CGRect)rect fromLayer:(CALayer *)layer;
- (CGRect)convertRect:(CGRect)rect toLayer:(CALayer *)layer;

得到触摸点相对于图层自身的坐标之后,调用containsPoint:方法。containsPoint:方法传入一个CGPoint类型参数,如果这个点在图层的frame内,则返回YES,否则返回NO。这样,就实现了对CALayer点击事件的处理。

方法二:hitTest:

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    CGPoint point = [[touches anyObject] locationInView:self.view];
    CALayer *layer = [self.view.layer hitTest:point];
    if (layer == self.redLayer) {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"point red" message:@"" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
        [alert show];
    }else if (layer == self.yellowLayer){
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"point yellow" message:@"" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
        [alert show];
    }
}

hitTest:同样传入一个CGPoint类型参数,但它的返回值不是BOOL类型,而是图层本身。如果点击的位置在最外层图层之外,则返回nil

使用hitTest:时有一点需要注意:

hitTest:返回的顺序严格按照图层树的图层顺序。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容