레이어 히트 테스트 레이어의 하단 절반이 터치 된 경우 반환 레이어 만 반환합니다.

StackOverflow https://stackoverflow.com/questions/401040

문제

레이어 지원 뷰에 하위 레이어가 있습니다. Subrayer의 내용은 이미지 Ref로 설정되었으며 25x25 rect입니다.
TouchesBegan과 TouchesMoved 메소드가 호출되면 슈퍼 레이어에서 히트 테스트를 수행합니다. 히트 테스트 방법은 실제로 서브 레이어가 터치하면 이미지의 하단 절반이 터치 된 경우에만 반환합니다. 이미지의 상단 절반이 터치하면 대신 슈퍼 레이어를 반환합니다.

iPhone OS가 사용자 터치의 경향이 의도 한 것보다 낮다는 것을 보상합니다. 하위 레이어를 더 큰 크기 50x50으로 크기로 조정하더라도 동일한 동작을 나타냅니다.

이견있는 사람?

도움이 되었습니까?

해결책 6

고마워 케빈 ...

결국 UIViews로 코드를 다시 만들었습니다. UIView가 왜 어떤 레이어가 만지고 있는지 알지 못하는 이유를 알아내는 데 너무 많은 어려움이있었습니다. 아이디어의 배후에 대한 나의 모든 추론은 한 번에 화면에 100 개 이상의 항목을 가질 것이며, Uiviews보다 프로세서에서 레이어가 더 쉬울 것이라고 생각했습니다. 나는 지금 앱을 UP으로 실행하고 실행 중이며 100 조회는 딸꾹질을 제공하지 않습니다.

다른 사람들에 대한 나의 제안은 가능하면 히트 테스트 UIViews를 고수하는 것입니다.

다른 팁

Hittest의 문서는 다음과 같습니다.

/* 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. */

그래서 당신은 (이와 같은)해야합니다.

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

(완전성을 위해 다른 게시물의 답변 반복)

층은 단지 하단 픽셀에 터치를받는 것이 아닌 것 같습니다. 대신 스크린 레이어의 "실제"와 레이어의 내용은 다른 CGRECT에 의해 정의 된 것 같습니다. 이미지는 예상 코디네이트에 표시되는 반면 터치에 응답하는 레이어는 이미지 아래에서 오프셋됩니다. 아래에 따르면, 이미지의 기원은 (200, 200)에 있고 터치에 응답하는 레이어의 원점은 (200, 220)입니다.

아래에는 문제를 재현하는 데 사용한 테스트 코드를 게시하고 있습니다. 먼저 내 뷰 서브 클래스와 내 뷰 컨트롤러. 이 문제의 배후에 대한 모든 추론은 대단히 감사합니다.

내 견해 서브 클래스 :

#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

내 뷰 컨트롤러 :

#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

허용 된 답변은 문제를 해결하지 못하지만 Schwa의 답변은합니다.

창,보기 컨트롤러 및 뷰가 있습니다. 보기는 터치와 호출을받습니다 hitTest: 층에. 나는 같은 문제가 있었고보기의 요점이 맞다는 것을 알았지 만 hitTest: 포인트의 y 좌표는 20px 꺼져 있으며, 이는 상태 표시 줄의 높이입니다.

Schwa가 제안한대로 수퍼 레이어의 좌표계에 포인트를 매핑 함으로써이 문제는 고정되어 있습니다. "신비한"슈퍼 레이어는 수퍼 뷰의 루트 레이어입니다. 제 경우에는 창 레이어 (프레임 (0, 0, 320, 480))입니다.

아래 부분에서만 터치가 인식되는 경우, 하나의 가능성은 다른 하위 뷰 가이 하위 뷰의 상단 절반을 다루는 것입니다. 여러 하위 뷰가 있거나 하나의 이미지 만 있습니까? 여러 개의 하위 뷰가 있고 그 중 하나라도 ClearColor와 같은 배경색이있는 경우 테스트를 위해 탄탄한 배경색을 제공하십시오. 이 방법은 귀하의 하위 뷰가 다른 하위 뷰로 덮여 있는지 알 수 있습니다.

도움이되기를 바랍니다.

문제를 찾기 위해 코드를 단순화했습니다. 화면에 하나의 하위 레이어가 있고 하위 뷰가 없습니다. 위에 나열된 코드는 시뮬레이터에서 실행하는 것입니다. 화면에는 2 개의 레이어 만 있으므로 호스트 뷰의 백킹 레이어 및 내가 추가 한 하위 레이어가 있으므로 적중 테스트를 방해해서는 안됩니다.

명확하지 않은 경우, 하위 레이어의 상단 부분이 닿을 때, 히트 테스트는 대신 백킹 레이어를 반환합니다. 또한 서브 레이어 바로 아래의 지점에서 백킹 레이어를 터치하면 히트 테스트에 의해 서브 레이어가 반환됩니다.

설명하기는 어렵지만 코드를 실행하면 명확 해집니다.

감사

코드를 시도 할 때, 터치는 종종 서브 레이어의 가장자리에서 인식되지 않는다는 점을 제외하고는 거의 수정 된 동작을 얻습니다. 나는 무슨 일이 일어나고 있는지에 대해 약간 혼란스러워합니다. 터치를 등록 할 때와 같은 일을하고, 터치가 발생한 곳에서 새로운 작은 레이어를 던지고 (일부 색상의 5x5 제곱과 같은) 3 초 후에 다시 제거 할 수 있습니다. 이렇게하면 CA가 터치가 발생했다고 생각하는 곳과 커서가 실제로있는 위치를 추적 할 수 있습니다.

BTW, 파란색 컨텐츠에 대한 cgimage를 만들 필요가 없으며 레이어를 설정할 수 있습니다. backgroundColor 에게 [UIColor blueColor].CGColor.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top