2014-09-19 5 views
4

У меня есть вид с распознающим жестом. Подвью к этому представлению представляет собой экземпляр моего пользовательского класса, который наследуется от UIControl. У меня возникает проблема, когда подкласс UIControl иногда позволяет передавать события касания к родительскому представлению, когда это не должно.UIControl endTrackingWithTouch не называется

В подклассе UIControl я переопределен эти функции (код в Swift)

override func beginTrackingWithTouch(touch: UITouch, withEvent event: UIEvent) -> Bool 
{ 
    return true 
} 

override func continueTrackingWithTouch(touch: UITouch, withEvent event: UIEvent) -> Bool 
{ 
    // The code here moves this UIControl so its center is at the touchpoint 
    return true 
} 

override func endTrackingWithTouch(touch: UITouch,withEvent event: UIEvent) 
{ 
    // Something important happens here! 
} 

Эта система работает нормально, если пользователь приземляется в UIControl, тащит контроль вокруг в как X и Y, а затем снимает экран. В этом случае все три функции называются, и происходит «что-то важное».

Однако, если пользователь прикасается к UIControl, перетаскивает элемент управления около только в направлении X, а затем снимает экран, у нас есть проблема. Вызываются первые две функции, но когда сенсорная точка поднимается с экрана, вызывается распознаватель жестов, а endTrackingWithTouch не вызывается.

Как я всегда убеждаюсь, что endTrackingWithTouch всегда называется?

ответ

3

Я исправил это таким образом, чтобы я считал, что это взломать, но нет никакой альтернативы, поскольку работает UIGestureRecognizer.

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

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

override func beginTrackingWithTouch(touch: UITouch, withEvent event: UIEvent) -> Bool 
{ 
    pointerToSuperview.pauseGestureRecognizer() 
    return true 
} 

override func continueTrackingWithTouch(touch: UITouch, withEvent event: UIEvent) -> Bool 
{ 
    // The code here moves this UIControl so its center is at the touchpoint 
    return true 
} 

override func endTrackingWithTouch(touch: UITouch,withEvent event: UIEvent) 
{ 
    // Something important happens here! 
    pointerToSuperview.resumeGestureRecognizer() 
} 

override func cancelTrackingWithEvent(event: UIEvent?) 
{ 
    pointerToSuperview.resumeGestureRecognizer() 
} 

В классе SuperView в:

pauseGestureRecognizer() 
{ 
    tapGestureRecognizer.enabled = false 
} 

resumeGestureRecognizer() 
{ 
    tapGestureRecognizer.enabled = true 
} 

Это работает, потому что я не имею дело с мультитач (это нормально для мне не получать события касания касания при отслеживании касаний с помощью UIControl).

В идеале, контроль не должен указывать на просмотр, чтобы приостановить распознаватель жестов - распознаватель жестов не должен вмешиваться в касания элемента управления для начала! Однако даже установка запрета распознавания жестовTouchesInView на false не может предотвратить это.

+0

Хороший ответ. Иногда вместо отключения жестов вы можете использовать способ делегирования жестов: необязательный func gestureRecognizer (_ gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool – viggio24

+0

Если вы реализуете свой собственный TapGestureRecognizer и добавляете его в свой контроль, он ловит краны перед тем, как это произойдет. Таким образом, вам не нужно ничего знать о других распознавателях в иерархии представлений. Подробности ниже... –

1

Когда UIControl перемещается во время отслеживания касаний, он может отменить отслеживание. Попробуйте переопределить cancelTrackingWithEvent и посмотреть, так ли это. Если вы видите отмену, вам придется отслеживать ваши штрихи в неподвижном представлении где-то в родительской иерархии этого элемента управления.

+0

Это оказалось проблемой! Это ужасно странно, что он только запускает отмену при перетаскивании по горизонтали, но мне просто нужно было обойти это, сделав полный экран UIControl с подвью UIView, который перемещается (вместо самого UIControl). – user1021430

+0

На самом деле, я беру это обратно. Событие отслеживания не было отменено, потому что я менял рамку UIControl. Это было потому, что всякий раз, когда я тащил по горизонтали, мне просто приходилось тянуть короткие расстояния. Это инициировало распознаватель жестов, поскольку оно было интерпретировано как крана, и оно отменило событие отслеживания. – user1021430

1

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

На самом деле я закончил изменение главного окна UIControl в главном окне, чтобы избежать конфликтов (потому что это было всплывающее окно).

2

Есть способ исправить это, что прекрасно самодостаточно: создать экземпляр собственного TapGestureRecognizer и прикрепить его к настраиваемому элементу управления, например.в Objective-C,

_tapTest = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapped:)]; 
_tapTest.numberOfTapsRequired = 1; 
[self addGestureRecognizer:_tapTest]; 

, а затем реализовать обработчик tapped действий для обработки TAP:

- (void)tapped:(UITapGestureRecognizer *)recognizer {...} 

В моем случае, я обрабатывать tapped так же, как endTrackingWithTouch:withEvent:; ваш пробег может отличаться.

Таким образом, вы получаете кран, прежде чем какой-либо супервизор может его вырвать, и вам не нужно беспокоиться о иерархии вида, находящейся под вашим контролем.

Смежные вопросы