UIView hitTest:withEvent:和pointInside:withEvent

时间:2011-12-29 12:25:37

标签: objective-c cocoa-touch uiview core-graphics uievent

我正在使用适用于iOS的Mixare AR SDK,我需要解决一些发生的错误,其中一个是在点击POI视图时显示POI的信息。

前奏:

Mixare在MarkerView视图中放置了叠加UIView,MarkerView视图在屏幕上移动以对POI进行地理定位,每个都有两个子视图,一个是UIImageView和一个UILabel。

问题:

现在,例如,屏幕上有3个可见的POI,因此有3个MarkerView作为叠加子视图。如果您触摸叠加层中的任何位置,则会显示与随机POI相关联的信息视图。

所需:

我希望仅当用户点击MarkerView

时才会显示关联的POI信息

让我们一起工作吧。我看到MarkerView继承自UIView并实现了hitTest:withEvent

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {

    viewTouched = (MarkerView*)[super hitTest:point withEvent:event];
    return self;

}

我已经设置了一个断点,并且每个可见的MarkerView都会调用一次hitTest,但是loadedView总是为空,所以我无法使用它,所以我试图检查点击点是否在实现pointInside的MarkerView框架内:withEvent:通过这种方式

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
    NSLog(@"ClassName: %@", [[self class] description]);
    NSLog(@"Point Inside: %f, %f", point.x, point.y);
    NSLog(@"Frame x: %f y: %f widht:%f height:%f", self.frame.origin.x, self.frame.origin.y, self.frame.size.width, self.frame.size.height);

    if (CGRectContainsPoint(self.frame, point))
        return YES;
    else
        return NO;


    return YES;
}

但即使我触摸MarkerView,此功能也始终返回NO。当我检查日志时,我看到X和Y点值有时具有负值,并且视图的宽度和高度非常小,0.00022或类似而不是100 x 150,我在初始化时设置了MarkerView帧。

这里是我的日志摘录,您可以在其中看到类名,点和MarkerView帧值。

ClassName: MarkerView
2011-12-29 13:20:32.679 paisromanico[2996:707] Point Inside: 105.224899, 49.049023
2011-12-29 13:20:32.683 paisromanico[2996:707] Frame x: 187.568573 y: 245.735138 widht:0.021862 height:0.016427

我很遗憾这个问题,所以欢迎任何帮助。提前感谢您提供的任何帮助,我很抱歉这块砖:(

编辑:

最后我发现问题不在于hitTest:withEvent:或pointInside:withEvent,问题是CGTransform适用于MarkerView基于distande和旋转视图进行缩放,如果我评论任何相关的代码这一点,Mixare AR SDK工作正常,我的意思是,如果触摸标记,信息视图会正确显示,如果触摸屏幕中的任何其他位置则不会做任何事情。

所以,到目前为止,我还没有解决问题,但我在AugmentedViewController.m类中应用了删除CGTransform相关代码的补丁 - (void)updateLocations:(NSTimer *)timer function

- (void)updateLocations:(NSTimer *)timer {
    //update locations!

    if (!ar_coordinateViews || ar_coordinateViews.count == 0) {
        return;
    }

    int index = 0;
    NSMutableArray * radarPointValues= [[NSMutableArray alloc]initWithCapacity:[ar_coordinates count]];

    for (PoiItem *item in ar_coordinates) {

        MarkerView *viewToDraw = [ar_coordinateViews objectAtIndex:index];
        viewToDraw.tag = index;

        if ([self viewportContainsCoordinate:item]) {

            CGPoint loc = [self pointInView:ar_overlayView forCoordinate:item];
            CGFloat scaleFactor = 1.5;

            if (self.scaleViewsBasedOnDistance) {
                scaleFactor = 1.0 - self.minimumScaleFactor * (item.radialDistance / self.maximumScaleDistance);
            }

            float width = viewToDraw.bounds.size.width ;//* scaleFactor;
            float height = viewToDraw.bounds.size.height; // * scaleFactor;

            viewToDraw.frame = CGRectMake(loc.x - width / 2.0, loc.y-height / 2.0, width, height);

            /*
            CATransform3D transform = CATransform3DIdentity;

            //set the scale if it needs it.
            if (self.scaleViewsBasedOnDistance) {
                //scale the perspective transform if we have one.
                transform = CATransform3DScale(transform, scaleFactor, scaleFactor, scaleFactor);
            }

            if (self.rotateViewsBasedOnPerspective) {
                transform.m34 = 1.0 / 300.0;

                double itemAzimuth = item.azimuth;
                double centerAzimuth = self.centerCoordinate.azimuth;
                if (itemAzimuth - centerAzimuth > M_PI) centerAzimuth += 2*M_PI;
                if (itemAzimuth - centerAzimuth < -M_PI) itemAzimuth += 2*M_PI;

                double angleDifference = itemAzimuth - centerAzimuth;
                transform = CATransform3DRotate(transform, self.maximumRotationAngle * angleDifference / (VIEWPORT_HEIGHT_RADIANS / 2.0) , 0, 1, 0);
            }            

            viewToDraw.layer.transform = transform;

             */
            //if we don't have a superview, set it up.
            if (!(viewToDraw.superview)) {
                [ar_overlayView addSubview:viewToDraw];
                [ar_overlayView sendSubviewToBack:viewToDraw];
            }
        } else {
            [viewToDraw removeFromSuperview];
            viewToDraw.transform = CGAffineTransformIdentity;
        }
        [radarPointValues addObject:item];
        index++;
    }
    float radius = [[[NSUserDefaults standardUserDefaults] objectForKey:@"radius"] floatValue];
    if(radius <= 0 || radius > 100){
        radius = 5.0;
    }

    radarView.pois = radarPointValues;
    radarView.radius = radius;
    [radarView setNeedsDisplay];
    [radarPointValues release];
}

任何CoreGrapics或UI专家都可以就此问题向我们提出他的观点吗?

1 个答案:

答案 0 :(得分:1)

你应该尝试按照附件进行测试:

if ([self pointInside:point withEvent:event]) {
    // do something 
}

我建议你在superview上添加命中测试,并在markerView的父级的命中测试中执行以下操作

if ([markerView pointInside:point withEvent:event]) {
    // extract the tag and show the relevant info
}

希望这有帮助