Запретить отключенную UIButton от распространения событий касания - PullRequest
15 голосов
/ 13 января 2010

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

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

Пока я пробовал:

[topButton setUserInteractionEnabled:YES];

и

[topButton setExclusiveTouch:YES];

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

Ответы [ 6 ]

14 голосов
/ 22 августа 2012

Я добавил следующий метод для супервизора отключенной кнопки:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    if (!self.watchButton.enabled &&
        [self.watchButton pointInside:[self convertPoint:point toView:self.watchButton]
                            withEvent:nil]) {
        return nil;
    }
    return [super hitTest:point withEvent:event];
}

Это хорошо работает с ячейками UITableView.

4 голосов
/ 16 июля 2015

Мне удалось заставить это работать так, как мне было нужно, с немного измененной версией ответа @ kolyuchiy выше. Я переопределил метод hitTest:withEvent: в своем подклассе UIButton, возвращая self, когда он отключен, и точка находится в рамке представления, так что касание используется, но обработка события кнопки не вызывается.

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    if ( !self.enabled && [self pointInside:[self convertPoint:point toView:self] withEvent:event] )
    {
        return self;
    }
    return [super hitTest:point withEvent:event];
}
3 голосов
/ 24 ноября 2016

После попытки @kolyuchiy (который требует изменения поведения UIButton вне его области действия) и @ patrick-lynch (который просто не работал для меня) решения пришли с более элегантным, который применяется к подклассу UIButton :

private static let dummyView: UIView = {
    let view = UIView(frame: .zero)
    view.userInteractionEnabled = true
    return view
}()

public override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? {
    if !enabled && pointInside(point, withEvent: event) {
        return self.dynamicType.dummyView
    }
    return super.hitTest(point, withEvent: event)
}
2 голосов
/ 05 июня 2018

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

Решение

У меня всегда есть контейнер с несколькими (или только одной) кнопками внутри. Поэтому я подключаю IBOutlet контейнера кнопок к UIViewController или UIView, с которыми я работаю:

@property (weak, nonatomic) IBOutlet UIView *buttonsContainer;

И я установил распознаватель жестов одним нажатием, как показано ниже:

[self.buttonsContainer addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:nil]];

С помощью этого обходного пути, если кнопка отключена, buttonsContainer фиксирует это событие и ничего с ним не делает.

Надеюсь, это поможет.

2 голосов
/ 03 февраля 2012

Что я сделал, так это поместил UIImageView того же размера с UIButton прямо под UIButton. Затем, даже если вы отключите UIButton, сенсорные события не распространяют UIImageView.

1 голос
/ 14 января 2010

Создайте подкласс кнопки, затем переопределите эти методы, чтобы кнопка перехватывала события, но игнорировала их, если для какого-либо свойства кнопки установлено значение NO:

touchesBegan:withEvent:
touchesCancelled:withEvent:
touchesEnded:withEvent:
touchesMoved:withEvent:

Это методы UIResponder.

Пусть они просто вызовут свой метод [super ...], если вы хотите обработать событие, иначе просто не вызывайте его и не возвращайте, если вы хотите, чтобы события были "съедены".

См. Также, если это необходимо: Наблюдение за жестами мультитач-зажима в UITableView

...