Как игнорировать события касания и передают их в объекты другого подпа-х элементов графического интерфейса?


У меня есть пользовательский UIViewController, чей UIView занимает угол экрана, но большая его часть прозрачна, за исключением частей, которые имеют некоторые кнопки и прочее на нем. Из-за расположения объектов на этом виде рамка вида может закрывать некоторые кнопки под ней. Я хочу иметь возможность игнорировать любые прикосновения к этому представлению, если они не касаются ничего важного на нем, но я, похоже, могу только передавать фактические события касания (touchesEnded/nextResponder). если я есть UIButton или что-то вроде того, что не использует touchesEnded, как я могу передать событие касания вместе с этим?

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

[self.nextResponder touchesEnded:touches withEvent:event];

на типах UIControl, а также.

6 56

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 to 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
}

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

В Swift:

yourView.isUserInteractionEnabled = false

моя проблема была похожа: у меня был UIControl со сложными сенсорными ответчиками, но он действовал смешно, когда был встроен в вид прокрутки...

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

мое решение:

создайте протокол делегата для didBeginInteraction и didEndInteraction в представлении sub.

вызов делегата.didBeginInteraction от touchesBegan

вызов делегата.didEndInteraction от touchesEnded и touchesCancelled

в Родительском контроллере реализуйте протокол didBegin и didEnd, установите делегат

затем установите scrollView.scrollEnabled = нет в didBegin, scrollEnabled = да в didEnd.

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