Как игнорировать события касания и передавать их другим объектам UIControl подзаголовка?
У меня есть пользовательский UIViewController, UIView которого занимает угол экрана, но большая часть его прозрачна, за исключением тех частей, которые имеют некоторые кнопки и прочее. Из-за расположения объектов на этом представлении рамка представления может закрывать некоторые кнопки под ним. Я хочу иметь возможность игнорировать любые прикосновения к этой точке зрения, если они не касаются чего-либо важного, но я, кажется, только могу пройти по фактическим событиям касания (затрагивает вещи Enned/nextResponder). Если у меня есть UIButton или что-то вроде того, которое не использует touchesEnded, как мне передать событие касания вместе с этим?
Я не могу просто вручную определить переключатель кнопок для вызова, потому что этот пользовательский ViewController может использоваться во многих разных представлениях. Мне в основном нужен способ назвать это:
[self.nextResponder touchesEnded:touches withEvent:event];
и в типах UIControl.
Ответы
Ответ 1
Вероятно, лучший способ сделать это - переопределить 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 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 buttons):
return hitView;
}
Я бы рекомендовал, чтобы первый подход был самым надежным (если можно получить ссылку на базовое представление).
Ответ 2
Быстрый ответ:
Вы можете создать подкласс 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!
Ответ 3
Я не нашел хороший способ передать события UITouch между объектами. Что обычно работает лучше, так это реализовать hitTest и вернуть нуль, если точка не в том представлении, которое вы хотите обработать:
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
Ответ 4
Это старый вопрос, и он поднимается вверху поисков. Итак, я думал, что опубликую еще одно возможное решение, которое может работать лучше для вашей ситуации. В моем случае я хотел перетащить ярлык поверх другого ярлыка, и я хотел получить ярлык ниже в hitTest. Самое простое - установить userInteractionEnabled
на NO
или 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
}
Ответ 5
Моя проблема была схожа: у меня был UIControl со сложными сенсорными респондентами, но он был смешным, когда встроен в прокрутку...
Это предотвращает прокрутку родительского элемента (или может быть изменено для предотвращения других взаимодействий), когда суб-просмотр имеет активный сенсорный жест.
Мое решение:
Создайте делегатский протокол для didBeginInteraction и didEndInteraction в представлении sub.
Вызвать делегат .didBeginInteraction от touchhesBegan
Вызов delegate.didEndInteraction from touchesEnded и touchsCancelled
В родительском контроллере реализовайте протокол didBegin и didEnd, установите делегат
Затем установите scrollView.scrollEnabled = NO в didBegin, scrollEnabled = YES в didEnd.
Надеюсь, это поможет кому-то с немного другим вариантом использования, чем заданный вопрос!