UIGestureRecognizer подпрограмма распознавания subView - PullRequest
4 голосов
/ 19 мая 2011

Название сложно.Основной случай выглядит следующим образом:

UIView *superView = [[UIView alloc] initWithFrame:CGRectMake(0,0,400,400)];
UIView *subView = [[UIView alloc] initWithFrame:CGRectMake(-200,-200,400,400)];
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAction:)];
[subView addGestureRecognizer:tapGesture];
[superView addSubView:subView];

ОК, вы обнаружите, что жест касания вступит в силу при щелчке по области в (0,0,200,200), если щелкнуть точку (-150, -150) жест касания не вступит в силу.

Я не знаю, вызван ли щелчок за пределами superView причиной этой проблемы или нет.

У кого-нибудь есть идеи, как это исправить?

Ответы [ 2 ]

11 голосов
/ 02 мая 2012

Чтобы позволить подпредставлениям, находящимся вне суперпредставления, реагировать на прикосновения, переопределите hitTest:withEvent: суперпредставления.

Документация по доставке события

Сенсорные события. Объект окна использует проверку нажатия и цепочку респондента, чтобы найти представление для получения события касания. В тестировании попаданий окно вызывает hitTest: withEvent: в самом верхнем представлении иерархии представлений; этот метод рекурсивно вызывает pointInside: withEvent: для каждого представления в иерархии представлений, которое возвращает YES, продолжая вниз по иерархии, пока не найдет подпредставление, в пределах которого произошло касание. Это представление становится представлением проверки нажатия.

  1. Создание подкласса UIView.
  2. Переопределить hitTest: withEvent.
  3. Используйте этот подкласс UIView для суперпредставления.

Добавить метод ниже в подкласс:

(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    NSEnumerator *reverseE = [self.subviews reverseObjectEnumerator];
    UIView *iSubView;

    while ((iSubView = [reverseE nextObject])) {

        UIView *viewWasHit = [iSubView hitTest:[self convertPoint:point toView:iSubView] withEvent:event];
        if(viewWasHit) {
            return viewWasHit;
        }

    }
    return [super hitTest:point withEvent:event];
}

Примечание: Используется обратный перечислитель, поскольку подпредставления упорядочены сзади и вперед, и мы хотим сначала протестировать самый передний вид.

2 голосов
/ 19 июля 2011

Единственный обходной путь, который я нашел для такого случая, - это создание экземпляра вида, прозрачного для касаний, в качестве основного вида.В этом случае внутренний вид будет реагировать на прикосновения, поскольку он соответствует границам основного.В классе, который я сделал из разных примеров, найденных в сети, я могу контролировать уровень «видимости касанием» следующим образом: полностью видимый - все касания заканчиваются в представлении.только подпредставления - само представление невидимо, но подпредставления получают свои прикосновения.Полностью невидимый - я думаю, что он довольно понятен:)

Я не пытался использовать его с распознавателями жестов, но не думаю, что возникнут какие-либо проблемы, поскольку он отлично работает с обычными прикосновениями.

Код прост ...

TransparentTouchView.h

#import <UIKit/UIKit.h>

typedef enum{
    TransparencyTypeNone = 0,         //act like usual uiview
    TransparencyTypeContent,          //only content get touches
    TransparencyTypeFull              //fully transparent for touches
}TransparencyType;

@interface TransparentTouchView : UIView {
    TransparencyType      _transparencyType;
}

@property(nonatomic,assign)TransparencyType transparencyType;

@end

TransparentTouchView.m

#import "TransparentTouchView.h"


@implementation TransparentTouchView

@synthesize 
transparencyType = _transparencyType;

- (id)initWithFrame:(CGRect)frame{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
        self.backgroundColor = [UIColor clearColor];
    }
    return self;
}

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
    // UIView will be "transparent" for touch events if we return NO
    switch (_transparencyType) {
        case TransparencyTypeContent:
            for(UIView* subview in self.subviews){
                CGPoint p = [subview convertPoint:point fromView:self];
                if([subview pointInside:p withEvent:event]){
                    return YES;
                }
            }
            return NO;
            break;
        case TransparencyTypeFull:
            return NO;
        default:
            break;
    }
    return YES;
}

@end

Я считаю, что вы можете приспособить его для своих нужд.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...