Как игнорировать события касания и передают их в объекты другого подпа-х элементов графического интерфейса?
У меня есть пользовательский UIViewController, чей UIView занимает угол экрана, но большая его часть прозрачна, за исключением частей, которые имеют некоторые кнопки и прочее на нем. Из-за расположения объектов на этом виде рамка вида может закрывать некоторые кнопки под ней. Я хочу иметь возможность игнорировать любые прикосновения к этому представлению, если они не касаются ничего важного на нем, но я, похоже, могу только передавать фактические события касания (touchesEnded/nextResponder). если я есть UIButton или что-то вроде того, что не использует touchesEnded, как я могу передать событие касания вместе с этим?
Я не могу просто вручную определить селектор кнопок для вызова, потому что этот пользовательский ViewController может использоваться на многих разных представлениях. Мне в основном нужен способ назвать это:
[self.nextResponder touchesEnded:touches withEvent:event];
на типах UIControl, а также.
6 ответов:
вероятно, лучший способ сделать это, чтобы переопределить
hitTest:withEvent:
в представлении, которое вы хотите игнорировать прикосновения. В зависимости от сложности иерархии представлений существует несколько простых способов сделать это.Если у вас есть ссылка на просмотр под видом игнорировать:
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { UIView *hitView = [super hitTest:point withEvent:event]; // If the hitView is THIS view, return the view that you want to receive the touch instead: if (hitView == self) { return otherView; } // Else return the hitView (as it could be one of this view's buttons): return hitView; }
Если у вас нет ссылки на вид:
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { UIView *hitView = [super hitTest:point withEvent:event]; // If the hitView is THIS view, return nil and allow hitTest:withEvent: to // continue traversing the hierarchy to find the underlying view. if (hitView == self) { return nil; } // Else return the hitView (as it could be one of this view's buttons): return hitView; }
Я бы рекомендовал первый подход как наиболее надежный (если можно получить ссылку на основной вид).
быстрым ответом:
вы можете создать подкласс UIView, IgnoreTouchView. В раскадровке установите его на вид(ы) VC, который вы хотите пройти через прикосновения:
class IgnoreTouchView : UIView { override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { let hitView = super.hitTest(point, with: event) if hitView == self { return nil } return hitView } }
обратите внимание, что вы должны установить UserInteractionEnabled в true для рассматриваемого UIView!
Я не нашел хорошего способа передачи событий UITouch между объектами. Что обычно работает лучше, так это реализовать hitTest и вернуть nil, если точка не находится в представлении, которое вы хотите обработать:
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
Это старый вопрос, и он появляется в верхней части поиска. Итак, я подумал, что опубликую еще одно возможное решение, которое может работать лучше для вашей ситуации. В моем случае я хотел перетащить ярлык поверх другого ярлыка, и я хотел получить ярлык ниже в hitTest. Самое простое, что нужно сделать, это установить
userInteractionEnabled
toNO
илиfalse
, затем сделайте свой hitTest, а затем снова установите его, если вам нужно снова переместить его. Вот пример кода в Swift:override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) { let touch = touches.first let location = touch?.locationInView(self.view) self.label1.userInteractionEnabled = false let view = self.view.hitTest(location!, withEvent: nil) as? UILabel print(view?.text) self.label1.userInteractionEnabled = true }
вы также можете отключить взаимодействие с пользователем, чтобы события касания игнорировались и передавались родителю.
В Swift:
yourView.isUserInteractionEnabled = false
моя проблема была похожа: у меня был UIControl со сложными сенсорными ответчиками, но он действовал смешно, когда был встроен в вид прокрутки...
Это предотвращает родительскую прокрутку (или может быть изменено для предотвращения других взаимодействий), когда sub view имеет активный сенсорный жест.
мое решение:
создайте протокол делегата для didBeginInteraction и didEndInteraction в представлении sub.
вызов делегата.didBeginInteraction от touchesBegan
вызов делегата.didEndInteraction от touchesEnded и touchesCancelled
в Родительском контроллере реализуйте протокол didBegin и didEnd, установите делегат
затем установите scrollView.scrollEnabled = нет в didBegin, scrollEnabled = да в didEnd.
надеюсь, что это поможет кому-то с немного другим случаем использования, чем поставленный вопрос!