UITouch на перекрывающихся UIViews - PullRequest
2 голосов
/ 26 марта 2012

У меня есть два вида, каждый из которых содержит два подпредставления.

Обнаружение попадания работает нормально, пока два вида сверху не перекрываются.Следовательно, я могу коснуться подпредставления, помеченного буквой A в левой части изображения ниже.

Однако, как только два верхних вида пересекаются, просто не может быть, чтобы представление A получало прикосновения, поскольку представление 1 находится «выше».вид 2 и «съедает» касание.

Оба вида 1 и вид 2 обнаруживают касания, так как их можно перемещать, следовательно, необходимо обнаруживать и реагировать на касания «между» подпредставлениями.

Это означает, что мои два «вид сверху» обнаружения должны сказать: «О, подожди минутку, может быть, я перекрываю какой-то другой вид и должен передать ему событие, и начинать перетаскивание / перемещение только тогда и только тогда, когда нет другихвид "ниже меня" ".

Как бы я это сделал?enter image description here

Редактировать: Спасибо jaydee3

Сначала это не сработало, что привело к бесконечной рекурсии: каждое представление откладывает своего родного брата, которое, в свою очередь, откладывает обратно на исходное представление:

- (UIView *) hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    UIView * hit =  [super hitTest:point withEvent:event] ;

    if (hit == self) {
        for (UIView * sibling in self.superview.subviews) {
            if (sibling != self) {
                CGPoint translated = [self convertPoint:point toView:sibling] ;
                UIView * other = [sibling hitTest:translated withEvent:event] ;
                if (other) {
                    return other ;
                }
            }
        }
    }

    return hit ;
}

Итак, я добавил «помеченный набор», чтобы отслеживать, какой вид уже посещен, и теперь все работает:)

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

    static NSMutableSet * markedViews = [NSMutableSet setWithCapacity:4] ;

    UIView * hit =  [super hitTest:point withEvent:event] ;

    if (hit == nil) return nil ;

    if (hit == self) {
        for (UIView * sibling in hit.superview.subviews) {
            if (sibling != hit) {
                if ([markedViews containsObject:sibling]) {
                    continue ;
                }

                [markedViews addObject:sibling] ;
                CGPoint translated = [hit convertPoint:point toView:sibling] ;
                UIView * other = [sibling hitTest:translated withEvent:event] ;
                [markedViews removeObject:sibling] ;

                if (other) {
                    return other ;
                }
            }
        }
    }

    return hit ;
}

1 Ответ

3 голосов
/ 26 марта 2012

Создайте пользовательский подкласс для своего представления (который содержит два других подпредставления) и перезапишите для него метод hitTest:. В этом методе проверьте, является ли представление hitTest одним из двух подпредставлений, иначе верните nil. Так что все прикосновения будут игнорироваться на вашем окружении. Приводя к прикосновению к представлению ниже, которое может обращаться с этим непосредственно.

// edit: (Вы получаете представление hitTest, вызывая UIView* view = [super hitTest:withEvent:];.)

// edit2: я думал о чем-то таком: :)

- (UIView *) hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    UIView * hit =  [super hitTest:point withEvent:event] ;

    if (hit == self) {
        return nil;
    }

    return hit ;
}

;)

...