ios - 在 CALayer 中处理触摸

标签 ios iphone objective-c uiview calayer

我正在尝试在我的 View 中检测触摸。 app screenshot

我的代码:

- (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;
}

但是我发现了问题。它仅检测树中的第一层。

屏幕截图中的每个图形 - 一层。我把它从最大到最小画成树。

最佳答案

如果您的最顶层覆盖了整个屏幕(或其他下面的层),那么是的,您将在 hitTest 检查期间获得最顶​​层。如果您想在下面进一步检查,可以对所有图层进行 containsPoint 检查。请在下面找到一些示例代码

   @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

或者您可以尝试使用 CAShapeLayers 并与 ShapeLayer 的 CGPath 匹配,以查看它是否像下面的示例那样被触摸。

@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;
        }

    }
}

关于ios - 在 CALayer 中处理触摸,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22601798/

相关文章:

iphone - 如何在 NSArray 中获取索引?

iphone - UIDatePicker 获取 GTM 值

iphone - 使用 SDURLCache(NSURLCache 的子类)时的内存泄漏

objective-c - 为什么我有内存力问题?

ios - 将应用程序背景设置为主屏幕/跳板背景

ios - 使用 iOS 的 Google Analytics,数据不发送

ios - 如何在 iOS 中使用 CoreAnimation 为 CIFilter 设置动画?

iphone - 使用核心数据进行存储 - 在基于导航和基于窗口的应用程序中 - iPhone

objective-c - iOS 中的空闲线程方法

iphone - 是否可以追踪拨出电话和短信?