Подтвердить что ты не робот

Пересылка UIGesture в режим просмотра

Я работаю над приложением iphone (iOS 4.0 или новее) и испытываю некоторые проблемы с сенсорным управлением между несколькими видами. У меня есть структура представления, подобная этой

---> A superView 
     |
     ---> SubView - A 
     |
     ---> SubView - B (exactly on top of A, completely blocking A).

enter image description here

В основном у меня есть супервизор, а subviews sibling A и B. B имеет тот же фрейм, что и A, и, следовательно, полностью скрывают A.

Теперь мое требование таково.

  • SubView B должен получить все салфетки и нажмите (один и два) жесты.
  • SubView A должен получать все жесты пинча.

Вот как я добавил распознаватели жестов в представления

UISwipeGestureRecognizer *leftSwipe  =  [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(leftSwipe:)];
[leftSwipe setDirection:(UISwipeGestureRecognizerDirectionLeft)];
leftSwipe.delegate  =   self;
[bView addGestureRecognizer:leftSwipe];
[leftSwipe release];

UISwipeGestureRecognizer *rightSwipe  =  [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(rightSwipe:)];
[rightSwipe setDirection:(UISwipeGestureRecognizerDirectionRight)];
rightSwipe.delegate   =   self;
[bView addGestureRecognizer:rightSwipe];
[rightSwipe release];

UIPinchGestureRecognizer *pinch   =  [[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(handlePinch:)];
pinch.delegate    =   self;
[aView addGestureRecognizer:pinch];
[pinch release];

Я провел некоторое исследование, и для меня UIGestureRecognizerDelegate выглядел многообещающим, и я реализовал метод делегата

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer

Я возвратил NO для SubView B, надеясь, что основное представление получит это событие. Нет такой удачи, хотя

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
    if ([gestureRecognizer isKindOfClass:[UIPinchGestureRecognizer class]] && [gestureRecognizer view] == bView) {
        NSLog(@"pinchGesture");
        //bView.userInteractionEnabled = NO;
        return NO;
    }
    return YES;
}

Затем я отключил взаимодействие пользователя SubView B внутри обратного вызова делегата (код комментария в вышеупомянутом блоке), когда распознается жест щепотки, в надежде, что оставшаяся часть жестов будет получена SubView A. Нет такой удачи и там.

Так вот, где я сейчас стою. Я видел этот вопрос, где принятый ответ включает свойство cancelsTouchesInView. Но я считаю, что cancelsTouchesInView только отменяет конкретное событие касания, не пересылает его.

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

РЕДАКТИРОВАТЬ: ВРЕМЯ ВРЕМЕНИ

Мой так называемый subView A на самом деле является экземпляром стороннего класса View class, который отнимает все внимание, и я не контролирую никаких жестов на нем. Я хочу различную реализацию для левого и правого салфетки, и я хочу, чтобы щепотка, кран и т.д. Работали так же, как и с этим сторонним видом. Поэтому я поставил точку зрения над A (SubView B), чтобы получить левый и правый щелчки. Но теперь я хочу перенаправить другие события жестов в базовую библиотеку.

4b9b3361

Ответ 1

Если я правильно исправлю вашу проблему, вы можете просто добавить еще один, четкий вид с прямоугольником, такой же, как вы, A и B, и реализовать на нем все жесты: когда вы делаете жест жестки, управляйте subView A, проведите пальцем по экрану и коснитесь (одиночные и двойные) - управление subView B. Вы можете сделать это по-разному: с помощью указателей или просто посылая возвращенный жест методу в классе, который контролирует ваш под просмотр.

например:

UISwipeGestureRecognizer *leftSwipe  =  [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(leftSwipe:)];
[leftSwipe setDirection:(UISwipeGestureRecognizerDirectionLeft)];
leftSwipe.delegate  =   subViewAcontroller;
[clearView addGestureRecognizer:leftSwipe];
[leftSwipe release];

UISwipeGestureRecognizer *rightSwipe  =  [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(rightSwipe:)];
[rightSwipe setDirection:(UISwipeGestureRecognizerDirectionRight)];
rightSwipe.delegate   =   subViewAcontroller;
[clearView addGestureRecognizer:rightSwipe];
[rightSwipe release];

UIPinchGestureRecognizer *pinch   =  [[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(handlePinch:)];
pinch.delegate    =   subViewBcontroller;
[clearView addGestureRecognizer:pinch];
[pinch release];

или

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
    if ([gestureRecognizer isKindOfClass:[UIPinchGestureRecognizer class]]) {
        NSLog(@"pinchGesture");
        [subViewBcontroller solvePinchGesture: gestureRecognizer];
    }
//etc
    return YES;
}

Ответ 2

Жест жестокости никогда не будет принят aView, потому что вы считаете, что иерархия неверна.

---> A superView 
 |
 ---> SubView - A 
 |
 ---> SubView - B (exactly on top of A, completely blocking A).

bView будет захватывать все множественные касания, включая жест щепотки, но bView не будет обрабатывать жест щепотки, поэтому он передаст его следующему ответчику в цепочке ответчика, то есть супервидео bView или viewController для bView. Событие пинча никогда не будет передаваться его представлениям со стороны, потому что они параллельны (отношения родительский-дочерний или view-viewController).

Вы можете изменить свою иерархию представлений, как показано ниже:

---> A superView 
 |
 ---> SubView - A 
       |
       ---> SubView - B (child view of b, exactly on top of A, completely blocking A)



- (void)viewDidLoad {
    [super viewDidLoad];

    aView = [[UIView alloc] initWithFrame:self.view.bounds];
    aView.backgroundColor = [UIColor blueColor];

    bView = [[UIView alloc] initWithFrame:self.view.bounds];
    bView.backgroundColor = [UIColor redColor];

    [self.view addSubview:aView];
    [aView addSubview:bView];

    UISwipeGestureRecognizer *leftSwipe  =  [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(leftSwipe:)];
    [leftSwipe setDirection:(UISwipeGestureRecognizerDirectionLeft)];
    leftSwipe.delegate  =   self;
    [bView addGestureRecognizer:leftSwipe];

    UISwipeGestureRecognizer *rightSwipe  =  [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(rightSwipe:)];
    [rightSwipe setDirection:(UISwipeGestureRecognizerDirectionRight)];
    rightSwipe.delegate   =   self;
    [bView addGestureRecognizer:rightSwipe];

    UIPinchGestureRecognizer *pinch   =  [[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(handlePinch:)];
    pinch.delegate    =   self;
    [aView addGestureRecognizer:pinch];
}

Пожалуйста, получите более подробную информацию по ссылке: https://developer.apple.com/library/ios/#documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/EventsiPhoneOS/EventsiPhoneOS.html#//apple_ref/doc/uid/TP40009541-CH2-SW1

- > Важное замечание о событии, проходящем в цепочке ответчиков "Когда система отправляет событие касания, она сначала отправляет ее в определенное представление. Для событий касания это представление - это тот, который возвращается hitTest: withEvent:; для" встряхивания "событий-событий, событий дистанционного управления, сообщений о действиях, и сообщениями меню редактирования, это представление является первым ответчиком. Если начальный вид не обрабатывает событие, он перемещается по цепочке ответчиков по определенному пути:

  • Тестирование или первый ответчик передает запрос или сообщение его контроллеру вида, если он имеет один; если в представлении нет контроллера вида, он передает событие или сообщение в его супервизор.
  • Если диспетчер представлений или его просмотр не может обрабатывать событие или сообщение, он передает его в супервизор представления.
  • Каждый последующий супервизор в иерархии следует шаблону, описанному в первых двух шагах, если он не может обрабатывать событие или сообщение.
  • Верхний вид в иерархии представления, если он не обрабатывает событие или сообщение, передает его объекту окна для обработки.
  • Объект UIWindow, если он не обрабатывает событие или сообщение, передает его объекту приложения singleton. "

Мой ответ выше - это не единственное решение, что вам нужно сделать, это сделать салфетки и манипулировать жесты логикой в ​​той же цепочке ответчиков, чтобы событие жестов с жестким пинчем передавалось правильному ответчику. Например, вы можете опустить subview b и добавить салфетки влево/вправо для супервизора aView.

Ответ 3

Я сделал что-то подобное некоторое время назад. Я хотел сделать две разные вещи одним пальцем и двумя или несколькими пальцами. Моему решению может потребоваться некоторая настройка для вас, и я не могу гарантировать, что все будет работать точно так же в вашей среде кода. Я не нашел надлежащей документации hitTest и почему она называется несколько раз подряд. Поэтому я провел некоторое тестирование и пришел к решению, как отделить один и несколько пальцев жесты, которые очень хорошо работали для моих нужд.

У меня была эта иерархия представлений:

---> A superView 
 |
 ---> ScrollView - A - all touches
 |
 ---> ScrollView - B - only two+ finger scroll (exactly on top of A, completely blocking A).

Я реализовал переключатель в hitTest супервизора:

BOOL endDrag; // indicates scrollviewB did finish
BOOL shouldClearHitTest; // bool to help calling the method clearHitTest only once.
BOOL multiTouch; // needed for the method clearHitTest to know if a multi-touch is detected or not
NSMutableArray *events; // store all events within one eventloop/touch;


- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    if (!endDrag) {
        if (!shouldClearHitTest) { // as hitTest will be called multible times in one event-loop and i need all events, i will clean the temporaries when everything is done
            shouldClearHitTest = YES;
            [[NSRunLoop mainRunLoop] performSelector:@selector(clearHitTest) target:self argument:nil order:1 modes:[NSArray arrayWithObject:NSRunLoopCommonModes]];
        }
        [events addObject:event]; // store the events so i can access them after all hittests for one touch are evaluated

        if (event.type == UIEventTypeTouches && ([_events count] > 3 || [[event allTouches] count] > 0 || _currentEvent)) { // two or more fingers detected. at least for my view hierarchy
            multiTouch = YES;
            return scrollViewB;
        }
    }else {
        endDrag = NO;
    }
    return scrollViewA;
}

- (void)clearHitTest {
    if (shouldClearHitTest) {
        shouldClearHitTest = NO;
        [events removeAllObjects];
        if (multiTouch) {
           // Do some special stuff for multiTouch
        }
        multiTouch = NO;
    }
}

Ответ 4

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

//--->for bview gesture to detect swipe
[pinch requireGestureRecognizerToFail:leftSwipe]; && 
[pinch requireGestureRecognizerToFail:rightSwipe];

//--->for aview gesture to detect pinch
[rightSwipe requireGestureRecognizerToFail:rightSwipe]; ||
[leftSwipe requireGestureRecognizerToFail:pinch];

Ответ 5

Если bView имеет жест жесткости. Из действия жестов bView pinch, если вы назовёте действие жестов aView, затем...

UIPinchGestureRecognizer *pinchA   =  [[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(handlePinchA:)];
[aView addGestureRecognizer:pinchA];
[pinchA release];    

UIPinchGestureRecognizer *pinchB   =  [[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(handlePinchB:)];
[bView addGestureRecognizer:pinchB];
[pinchB release];


-(void)handlePinchA:(UIGestureRecognizer*)gestureRecognizer
{
NSLog(@"handlePinch on A");  
}

-(void)handlePinchB:(UIGestureRecognizer*)gestureRecognizer
{
NSLog(@"handlePinch on B");
[self handlePinchA:gestureRecognizer];  
}

aView - это библиотека thirdParty. Можете ли вы вызвать метод handlePinchA извне? NSLog gestureRecognizers печатает меня action = handlePinchA

NSLog(@"gestureRecognizers %@", [aView gestureRecognizers]);

Печать меня:

gestureRecognizers (
"<UIPinchGestureRecognizer: 0x8b3e500; state = Possible; view = <UIView 0x8b2f470>; target= <(action=handlePinchA:, target=....