简体   繁体   English

iOS:CAShapeLayer,CALayer遮罩,hitTest:WithEvents,hitTest:

[英]iOS: CAShapeLayer, CALayer mask, hitTest:WithEvents, hitTest:

Thanks in advance: I have a view hierarchy like this: 在此先感谢:我有一个这样的视图层次结构:

A UIView within this I set: CALayer * layer = (CALayer*) self.layer 我在其中设置的UIViewCALayer * layer = (CALayer*) self.layer

And within this class I have a CAShapeLayer , which is set as the mask of the CALayer . 在这个类中,我有一个CAShapeLayer ,它被设置为CALayer的掩码。

It animates fine, no problem. 它动画效果很好,没问题。

I have a UIViewController that init the above UIView by: 我有一个UIViewController通过以下方式初始化上面的UIView

myView = [myAnimationView alloc] initWithFrame:(CGRect){{0, 0}, 320, 450}]; [self.view addSubview myView];

So what I have is: a UIView class and the above UIViewController class. 所以我所拥有的是:一个UIView类和上面的UIViewController类。 Nothing else. 没有其他的。

As the CAShapeLayer animates (it is only a basic ca animation, scaling from a small circle to a larger one), I hope to be able to get the touch point within UIViewController that inits this UIView 随着CAShapeLayer动画化(这只是一个基本的ca动画,从一个小圆圈缩放到一个较大的圆圈),我希望能够在初始化该UIView UIViewController中获得接触点

Should I use hitTest:WithEvents: here? 我应该在这里使用hitTest:WithEvents:吗? I have tried it, but it get called three times. 我已经尝试过了,但是却被调用了三遍。 The returned points are correct, but I was hoping to find a way to know whether or not an animated view is being touched from the container view. 返回的点是正确的,但是我希望找到一种方法来知道是否从容器视图中触摸了动画视图。 Other words, I would like to know if the subView /subLayer is being touched. 换句话说,我想知道subView / subLayer是否被触摸。

In summary, here is my view hierarchy: 总而言之,这是我的视图层次结构:

UIViewController initializes the UIView class and adds it as subView. UIViewController初始化UIView类,并将其添加为subView。 Within this UIView class its layer is set to be CALayer by CALayer * layer = (CALayer *) self.layer and the CAShapeLayer is set to be the mask of the CALayer and animation is set on the shape layer's path. 在此UIView类中,通过CALayer * layer = (CALayer *) self.layer将其图层设置为CALayer ,并将CAShapeLayer设置为CALayer的蒙版,并在形状图层的路径上设置动画。

And I would like to to able to get the layer touched within UIViewController 我希望能够在UIViewController接触到该层

Is it possible to get the touch point from a layer that is being animated by CAShapeLayer within a view whose layer is set to be CALayer from a UIViewController that adds it as its subview? 是否可以从将视图设置为CALayer的视图中,将由CAShapeLayer动画化的层中的接触点从UIViewController添加到其子视图中? Please cite with examples. 请举一些例子。

Thanks very much in advance. 首先十分感谢。 Regards. 问候。

I think CALayer isn't designed to receive/handle touch events (which is one big difference to UIView ). 我认为CALayer并非旨在接收/处理触摸事件(这与UIView有很大的不同)。 I tested for a (long press) touch within a CAShapeLayer.path from the ViewController with something like 我测试了ViewController在CAShapeLayer.path的(长按)触摸CAShapeLayer.path类似

- (void)handleLongPress:(UILongPressGestureRecognizer *)recognizer {
    CGPoint currentPoint = [recognizer locationInView:self.overlayView];
    bool didSelect = [self selectPathContainingPoint:currentPoint];
    if (didSelect) {
        [self updateViews];
    }
}

- (BOOL)selectPathContainingPoint:(CGPoint)point {
    CALayer * layer = (CALayer *) self.layer;
    CAShapeLayer *mask = (CAShapeLayer *)layer.mask;
    return CGPathContainsPoint(mask.path, nil, point);
}

There's one caveat however: my path isn't animated. 但是有一个警告:我的路径没有动画。 In the docs for CAShapeLayer it also doesn't say anything if the CAShapeLayer.path property updates during the animation. 在CAShapeLayer的文档中,如果CAShapeLayer.path属性在动画过程中进行了更新,它也不会说什么。

Try something like this: 尝试这样的事情:

- (void)setup
{
    _maskLayer = [CAShapeLayer layer];
    _maskLayer.fillColor = [UIColor whiteColor].CGColor;
    _maskLayer.path = somePath;

    _theLayer.frame = CGRectMake(0, 0, size.width, size.height);

    // Apply a mask
    _maskLayer.frame = _theLayer.frame;
    _theLayer.mask = _maskLayer;
}

- (IBAction)tapOnView:(UITapGestureRecognizer *)sender
{
    CGPoint point = [sender locationInView:theView];
    CALayer *subLayer = [_theLayer.presentationLayer hitTest:point].modelLayer;

    if (subLayer != _theLayer && subLayer != nil) {
        // Do something with the sublayer which the user touched
    }
}

You will have to setup your TapGestureRecognizer, I did this using Interface Builder but you can do it in code if you want. 您将必须设置TapGestureRecognizer,我使用Interface Builder进行了此设置,但是您可以根据需要在代码中进行设置。 Be sure that your layers have proper bounds setup, and you also need to set the bounds on your mask. 确保您的图层具有正确的边界设置,并且还需要在蒙版上设置边界。

Notice that I am getting the presentationLayer and the converting it back to the real layer. 注意,我正在获取presentationLayer,并将其转换回真实图层。 This will cause it to work with animations. 这将使其与动画一起使用。

I hope this works for you. 希望这对您有用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM