3

I have a structure composed on a root layer and 2 CALayer subclass. These 2 layers contain a layer too.

Here a scheme:

ROOT LAYER 
    |
    |------- LAYER A
    |           |---------BG
    |
    |
    |--------LAYER B
                |---------BG

If I call the hitTest method on the ROOT LAYER it returns the most inner layer into the hierarchy. So if user clicks over LAYER A I get the BG of LAYER A.

//In this example hitResult will contains the BG of LAYER A or the BG of LAYER B
CALayer *hitResult = [rootLayer hitTest:point)]; 

How can I stop the responder chain and get directly LAYER A or LAYER B from a HitTest sent to ROOT LAYER ?

MatterGoal
  • 16,038
  • 19
  • 109
  • 186

2 Answers2

6

If these layers are your own CALayer subclasses then you can override hitTest: or containsPoint: to do your own logic there.

Overriding containsPoint: and returning NO in your background layers will stop them from being returned from their superlayers hitTest: implementation.

Alternatively you could override hitTest: in Layer A and Layer B and return self if they contain the point.

David Rönnqvist
  • 56,267
  • 18
  • 167
  • 205
1

Just for the record, note that if you set a null z scale, layers don't pass the hit test anymore.

// BG layer won't receive clicks
bgLayer.transform = CATransform3DMakeScale(1, 1, 0)

It can be a way to make layers inactive without subclassing, but I guess Apple is free to change this behaviour anytime, so I won't recommend it.

I drop this answer anyway for those who may wonder why sublayers don't get clicks anymore. Just get sure you pass 1 in sz in any scaling.

I have myself lost few hours with this tricky one.

Moose
  • 2,607
  • 24
  • 23