UIView hitTest: withEvent: и pointInside: withEvent - PullRequest
3 голосов
/ 29 декабря 2011

Я работаю с Mixare AR SDK для iOS, и мне нужно устранить некоторые ошибки, которые возникают, одна из них - отображать информацию о POI при касании представления POI.

Prelude:

Mixare имеет наложенный UIView в пределах представлений MarkerView, представления MarkerView перемещаются по экрану для геолокации POI, и у каждого есть два подпредставления, UIImageView и UILabel.

Проблема:

Теперь, например, на экране есть 3 видимых POI, поэтому есть 3 MarkerView в качестве наложенных подпредставлений.Если вы дотронетесь до какого-либо места в оверлее, отобразится информационное представление, связанное со случайным POI, который является видимым.

Желаемый:

Я хочу, чтобы информация о связанном POI отображалась только тогда, когда пользователькоснулся MarkerView

Давайте работать.Я вижу, что MarkerView наследует от UIView и реализует hitTest: withEvent

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

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

}

Я поставил точку останова, и hitTest вызывается один раз для каждого видимого MarkerView, но с загруженным видом всегда ноль, поэтому я не могу работатьпоэтому я попытался проверить, находится ли точка попадания внутри фрейма MarkerView, реализующего pointInside: 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;
}

Но эта функция всегда возвращает NO, даже когда я касаюсь MarkerView.Когда я проверял журнал, я увидел, что значения точек 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 работает нормально, я имею в виду, что представление информации отображается правильно, если вы прикоснетесь к маркеруи ничего не делает, если коснуться любого другого места на экране.

Итак, на данный момент я не решил проблему, но применил патч, удаляющий связанный с CGTransform код в классе AugmentedViewController.m- (void) updateLocations: (NSTimer *) функция таймера

- (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 или пользовательскому интерфейсу может высказать нам свою точку зрения по этому вопросу ??

1 Ответ

1 голос
/ 30 декабря 2011

Вы должны либо попытаться выполнить хит-тест как прикрепленный:

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

Я бы посоветовал вам добавить тест на попадание в суперпредставление и сделать следующее в тесте на попадание родителя markerView s.

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

Надеюсь, это поможет

...