Domanda

I'm trying to detect touches in my view.app screenshot

My code:

- (CALayer *)layerForTouch:(UITouch *)touch {
    UIView *view = self;

    CGPoint location = [touch locationInView:view];
    location = [view convertPoint:location toView:nil];

    CALayer *hitPresentationLayer = [view.layer.presentationLayer hitTest:location];
    if (hitPresentationLayer) {
        return hitPresentationLayer.modelLayer;
    }

    return nil;
}

But I found problem. It's detecting just first layer in tree.

Every figure on screenshot - one layer. I'm drawing it's from the biggest to the smallest as tree.

È stato utile?

Soluzione

if your topmost layer covers the whole screen (or other below layers) then yes you will get the top most layer during hitTest check. you can do a containsPoint check for all your layers if you want to check it further below. Do find some sample code below

   @interface ViewController ()

@property (nonatomic, strong) CALayer *layer1;
@property (nonatomic, strong) CALayer *layer2;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    CALayer *layer = [[CALayer alloc] init];
    layer.frame = (CGRect) { 10, 10, 100, 100 };
    [self.view.layer addSublayer:layer];
    layer.backgroundColor = [UIColor redColor].CGColor;
    self.layer1 = layer;

    layer = [[CALayer alloc] init];
    layer.frame = (CGRect) { 60, 60, 100, 100 };
    [self.view.layer addSublayer:layer];
    layer.backgroundColor = [UIColor blueColor].CGColor;
    self.layer2 = layer;

}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    CGPoint touchPoint = [(UITouch*)[touches anyObject] locationInView:self.view];
    CALayer *touchedLayer = [self.view.layer.presentationLayer hitTest:touchPoint];

    CALayer *originalLayer = [touchedLayer modelLayer];

    if (originalLayer == self.layer1) { NSLog(@"layer 1 touched"); }

    if (originalLayer == self.layer2) { NSLog(@"layer 2 touched"); }

    for ( CALayer *layer in @[self.layer1, self.layer2])
    {
        CGPoint point = [layer convertPoint:touchPoint fromLayer:self.view.layer];
        NSLog(@"layer %@ containsPoint ? %@",layer, [layer containsPoint:point]? @"YES":@"NO");
        NSLog(@"original point : %@ | converted point : %@",NSStringFromCGPoint(touchPoint),NSStringFromCGPoint(point));
    }
}

@end

Or you can try using CAShapeLayers & match with the CGPath of ShapeLayer to see if its touched like the example below ..

@interface ViewController ()

@property (nonatomic, strong) CALayer *layer1;
@property (nonatomic, strong) CALayer *layer2;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    CAShapeLayer *shapeLayer = [[CAShapeLayer alloc] init];
    shapeLayer.path = [UIBezierPath bezierPathWithRect:(CGRect){ 0,0,100,10 }].CGPath;
    shapeLayer.backgroundColor = [UIColor redColor].CGColor;
    shapeLayer.frame = (CGRect){20, 20, 100, 100};
    [self.view.layer addSublayer:shapeLayer];
    self.layer1 = shapeLayer;

    shapeLayer = [[CAShapeLayer alloc] init];
    shapeLayer.path = [UIBezierPath bezierPathWithRect:(CGRect){ 0,0,10,100 }].CGPath;
    shapeLayer.backgroundColor = [[UIColor blueColor] colorWithAlphaComponent:0.6].CGColor;
    shapeLayer.frame = (CGRect){60, 60, 100, 100};
    [self.view.layer addSublayer:shapeLayer];
    self.layer2 = shapeLayer;

}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    CGPoint touchPoint = [(UITouch*)[touches anyObject] locationInView:self.view];
    CALayer *touchedLayer = [self.view.layer.presentationLayer hitTest:touchPoint];

    CALayer *originalLayer = [touchedLayer modelLayer];

    for ( CAShapeLayer *layer in @[self.layer1, self.layer2])
    {
        if (![layer isKindOfClass:[CAShapeLayer class]]) { continue; }

        CGPoint point = [layer convertPoint:touchPoint fromLayer:self.view.layer];

        if (CGPathContainsPoint(layer.path, 0, point, 0))
        {
            NSLog(@"match found");

            if (originalLayer == self.layer1) { NSLog(@"layer 1 touched"); }
            if (originalLayer == self.layer2) { NSLog(@"layer 2 touched"); }
            return;
        }

    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top