layer hit test only returning layer when bottom half of layer is touched

后端 未结 8 1990
闹比i
闹比i 2021-02-10 19:14

I have a sublayer on a layer-backed view. The sublayer\'s contents are set to an Image Ref and is a 25x25 rect.
I perform a hit test on the super layer when the touchesBega

相关标签:
8条回答
  • 2021-02-10 19:41

    The documentation for hitTest says:

    /* Returns the farthest descendant of the layer containing point 'p'.
     * Siblings are searched in top-to-bottom order. 'p' is in the
     * coordinate system of the receiver's superlayer. */
    

    So you need to do (something like this):

    CGPoint thePoint = [touch locationInView:self];
    thePoint = [self.layer convertPoint:thePoint toLayer:self.layer.superlayer];
    CALayer *theLayer = [self.layer hitTest:thePoint];
    

    (Repeating answer from other post for completeness' sake)

    0 讨论(0)
  • 2021-02-10 19:41

    It seems that the layer is not just receiving touches on the bottom pixels. Instead it seems that the "actual" on screen layer and the contents of the layer are defined by different CGRects. The Image is displayed at the expected cordinates, while the layer that responds to touches is offset below the image. By below, I mean the origin of the image is at (200, 200) and the origin of the layer that responds to touches is at (200, 220).

    Below I am posting some test code I used to recreate the problem. First my view subclass and then my view controller. Any reasoning behind this problem is greatly appreciated.

    My View subclass:

    #import "myView.h"
    #import <QuartzCore/QuartzCore.h>
    
    
    @implementation myView
    
    
    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    
        CGPoint currentLocation = [[touches anyObject] locationInView:self];
    
        CALayer *currentLayer = [self.layer hitTest:currentLocation];
    
        CGPoint center = [currentLayer position];
    
        NSLog([currentLayer valueForKey:@"isRootLayer"]);
    
        if(![currentLayer valueForKey:@"isRootLayer"]) {
    
            if (center.x != 200) {
    
                [currentLayer setPosition:CGPointMake(200.0f, 200.0f)];     
    
            } else {
                [currentLayer setPosition:CGPointMake(100.0f, 100.0f)];     
    
            }
        }
    }
    
    
    - (id)initWithFrame:(CGRect)frame {
        if (self = [super initWithFrame:frame]) {
            // Initialization code
        }
        return self;
    }
    
    
    - (void)drawRect:(CGRect)rect {
        // Drawing code
    }
    
    
    - (void)dealloc {
        [super dealloc];
    }
    
    
    @end
    

    My View Controller:

    #import "layerTestViewController.h"
    #import <QuartzCore/QuartzCore.h>
    
    
    #define ELEMENT_PERIOD_SIZE 50
    #define ELEMENT_GROUP_SIZE 50
    
    @implementation layerTestViewController
    
    
    
    
    
    // Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        CALayer  *myLayer = [CALayer layer];
        CGRect layerFrame =CGRectMake(0.0f, 0.0f, ELEMENT_GROUP_SIZE, ELEMENT_PERIOD_SIZE);
        myLayer.frame = layerFrame; 
    
        [myLayer setName:[NSString stringWithString:@"test"]];
        [myLayer setValue:[NSString stringWithString:@"testkey"] forKey:@"key"];
    
        UIGraphicsBeginImageContext(layerFrame.size);
        [[UIColor blueColor] set];
        UIRectFill(layerFrame);
        UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    
        myLayer.contents = (id)[theImage CGImage];
        myLayer.position = CGPointMake(100.0f, 100.0f);
    
        [self.view.layer addSublayer:myLayer];   
    
        [self.view.layer setValue:[NSString stringWithString:@"YES"] forKey:@"isRootLayer"];
        NSLog([self.view.layer valueForKey:@"isRootLayer"]);
    
    }
    
    
    
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
        // Release anything that's not essential, such as cached data
    }
    
    
    - (void)dealloc {
        [super dealloc];
    }
    
    @end
    
    0 讨论(0)
提交回复
热议问题