2013-09-27 5 views
1

Я пытаюсь получить ссылку на UImageView, который находится под маскированным UIImageView, используя hitTest withEvent. Вот что у меня есть, что не работает:iOS hitTest withEvent

UIView A, который содержит 3 UIImageViews в виде подзонов: panelOne, panelTwo и panelThree. panelThree занимает весь кадр, но маскируется в треугольник, отображая части панелей один и два. Поэтому мне нужно определить, когда пользователь выходит за пределы этого прямоугольника и посылает касание к соответствующему UIImageView.

Код: (CollagePanel подкласс UIImageView)

-(void)triangleInASquare 
{ 
    CGSize size = self.frame.size; 
    CollagePanel *panelOne = [[CollagePanel alloc] initWithFrame:CGRectMake(0,0, size.width/2, size.height)]; 
    panelOne.panelScale = panelOne.frame.size.width/self.frame.size.width; 
    panelOne.backgroundColor = [UIColor greenColor]; 

    CollagePanel *panelTwo = [[CollagePanel alloc] initWithFrame:CGRectMake(size.width/2,0, size.width/2, size.height)]; 
    panelTwo.panelScale = panelOne.frame.size.width/self.frame.size.width; 
    panelTwo.backgroundColor = [UIColor purpleColor]; 

    CollagePanel *panelThree = [[CollagePanel alloc] initWithFrame:CGRectMake(0,0, size.width, size.height)]; 
    panelThree.backgroundColor = [UIColor orangeColor]; 

    UIBezierPath* trianglePath = [UIBezierPath bezierPath]; 
    [trianglePath moveToPoint:CGPointMake(0, panelThree.frame.size.height)]; 
    [trianglePath addLineToPoint:CGPointMake(panelThree.frame.size.width/2,0)]; 
    [trianglePath addLineToPoint:CGPointMake(panelThree.frame.size.width, panelTwo.frame.size.height)]; 
    [trianglePath closePath]; 

    // Mask the panels's layer to triangle. 
    CAShapeLayer *triangleMaskLayer = [CAShapeLayer layer]; 
    [triangleMaskLayer setPath:trianglePath.CGPath]; 
    triangleMaskLayer.strokeColor = [[UIColor whiteColor] CGColor]; 
    panelThree.layer.mask = triangleMaskLayer; 

    //Add border 
    CAShapeLayer *borderLayer = [CAShapeLayer layer]; 
    borderLayer.strokeColor = [[UIColor whiteColor] CGColor]; 
    borderLayer.fillColor = [[UIColor clearColor] CGColor]; 
    borderLayer.lineWidth = 6; 
    [borderLayer setPath:trianglePath.CGPath]; 

    [panelThree.layer addSublayer:borderLayer]; 

    NSMutableArray *tempArray = [[NSMutableArray alloc] init]; 
    [tempArray addObject:panelOne]; 
    [tempArray addObject:panelTwo]; 
    [tempArray addObject:panelThree]; 

    [self addGestureRecognizersToPanelsInArray:tempArray]; 
    [self addPanelsFromArray:tempArray]; 
    self.panelArray = tempArray; 
} 

-(void)handleTap: (UITapGestureRecognizer*) recognizer //coming from panel.imageView 
{ 
    CGPoint tapPoint = [recognizer locationInView:self]; 
    NSLog(@"Location in self: %@", NSStringFromCGPoint(tapPoint)); 
    NSLog(@"self.subviews: %@", self.subviews); 
    UIView *bottomView = [self hitTest:tapPoint withEvent:nil]; 
    NSLog(@"Bottom View: %@", bottomView); 
} 

NSLog из bottomView всегда panelThree (самая верхняя панель). Из того, что я понимаю, тест попадания должен возвращать «нижний самый» subview.

ответ

0

вы понимаете неправильно. он вернет представление, которое распознает себя как затронутое и ближе всего к вашему пальцу, ближе к вершине.
Если представление не признает себя как прикосновение к определенной точке, необходимо перезаписать

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event 

для этой точки зрения.

Я думаю, что Ole Begemann's Shapped Button - отличный пример, как это сделать.

В вашем проекте этот метод может определить, находится ли точка в пределах путей: CGPathContainsPoint.


Ваш pointInside:withEvent: может выглядеть следующим образом:

#import "CollagePanel.h" 
#import <QuartzCore/QuartzCore.h> 

@implementation CollagePanel 
// 
// ... 
// 
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event 
{ 
    CGPoint p = [self convertPoint:point toView:[self superview]]; 
    if(self.layer.mask){ 
     if (CGPathContainsPoint([(CAShapeLayer *)self.layer.mask path], NULL, p, YES)) 
      return YES; 
    }else { 
     if(CGRectContainsPoint(self.layer.frame, p)) 
      return YES; 
    } 
    return NO; 
} 

@end 
+0

Так что я имел его в обратном направлении. В методе «Внутри» я могу проверить, находится ли касание внутри области и возвращать НЕТ, если это не так. Означает ли это, что нижеследующее представление будет признано? –

+0

да, это правильно. если представление возвращает нет, будет предложено следующее представление ниже. – vikingosegundo

+0

@JesseHiatt: см. Мое редактирование. – vikingosegundo

Смежные вопросы