【问题标题】:iOS hitTest withEventiOS hitTest withEvent
【发布时间】:2013-09-27 01:16:03
【问题描述】:

我正在尝试使用 hitTest withEvent 获取对位于蒙面 UIImageView 下方的 UImageView 的引用。这是我所拥有的不起作用的:

UIView A 包含 3 个 UIImageView 作为子视图:panelOne、panelTwo 和 panelThree。 panelThree 占据了整个框架,但被掩盖成一个三角形,露出面板 1 和 2 的一部分。所以我需要检测用户何时在该矩形之外点击并将触摸发送到相应的 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);
}

bottomView 的 NSLog 总是 panelThree(最上面的面板)。据我了解,命中测试应该返回“最底部”子视图。

【问题讨论】:

    标签: ios objective-c cocoa-touch


    【解决方案1】:

    你理解错了。它将返回将自己识别为已触摸且最靠近您的手指、更靠近顶部的视图。
    如果视图在某个点上不能将自己识别为触摸,则需要覆盖

    - (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
    

    【讨论】:

    • 所以我把它倒过来了。在 pointInside 方法中,我可以检查触摸是否在该区域内,如果不在则返回 NO。这样可以识别下面的视图吗?
    • 是的,没错。如果一个视图返回 no,将询问下面的下一个视图。
    猜你喜欢
    • 1970-01-01
    • 2016-02-28
    • 2018-03-03
    • 1970-01-01
    • 1970-01-01
    • 2019-04-23
    • 1970-01-01
    • 1970-01-01
    • 2011-04-15
    相关资源
    最近更新 更多