We know that CALayer can’t respond directly to any response chain events, so it can’t handle click events directly. But there are two ways to capture and handle CALayer’s click events.
Method one: 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]; }}Copy the code
First use the locationInView method to get the coordinates of the click on the view. ConvertPoint: fromLayer: The convertPoint: fromLayer method passes in a CGPoint to convert the coordinate system, converting the coordinates on its parent layer to the coordinates relative to the layer itself.
- (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;
Copy the code
Once you have the coordinates of the touch points relative to the layer itself, call the containsPoint: method. ContainsPoint: The containsPoint method takes a CGPoint argument and returns YES if the point is inside the layer’s frame, NO otherwise. Thus, the CALayer click event is handled.
Method 2: 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]; }}Copy the code
HitTest: Also passes a CGPoint argument, but it returns not BOOL, but the layer itself. Returns nil if the clicked position is outside the outermost layer.
One thing to note when using hitTest:
HitTest: Returns the order of the layers in the layer tree.