Предотвращение отключения UIButton от распространения событий касания
Мое приложение имеет две перекрывающиеся UIButtons. Верхняя кнопка может быть отключена время от времени. Однако в этом случае любые входящие в него события касания передаются вниз к основному виду, которое в моем случае является другой кнопкой.
Мне нужна верхняя кнопка, перехватывающая все касания и не позволяющая им дойти до нижней кнопки, даже в отключенном состоянии (я был бы счастлив, даже если это назначенное действие вызывается в отключенном состоянии).
До сих пор я пробовал:
[topButton setUserInteractionEnabled:YES];
и
[topButton setExclusiveTouch:YES];
хотя более поздний случай, вероятно, нежелателен, так как мне все еще нужна нижняя кнопка, отвечающая на события, если это первое нажатие. В любом случае никто из них не работает.
Ответы
Ответ 1
Я добавил следующий метод для просмотра отключенной кнопки:
- (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.
Ответ 2
То, что я сделал, это размещение UIImageView того же размера с UIButton только под UIButton. Тогда даже если вы отключите UIButton, события касания не распространяют UIImageView.
Ответ 3
Мне удалось получить эту работу, как мне было нужно, с немного измененной версией @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];
}
Ответ 4
После попытки @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)
}
Ответ 5
Создайте подкласс кнопки, затем переопределите эти методы, чтобы кнопка захватывала события, но игнорировала их, если для какого-либо свойства кнопки установлено значение NO:
touchesBegan:withEvent:
touchesCancelled:withEvent:
touchesEnded:withEvent:
touchesMoved:withEvent:
Это методы UIResponder.
Попросите их просто вызвать свой метод [super...], если вы хотите обработать событие, иначе просто не вызывайте его и не возвращайте, если хотите, чтобы события "съедали".
Также см. это в случае необходимости: Наблюдение за жесткими касаниями в UITableView
Ответ 6
Я знаю, что поздно, но я читал много подобных вопросов, и ни один из ответов, которые я читал, не был полезен для меня (некоторые из них, потому что не работали, а другие, потому что мне не нравилось это решение) поэтому я нашел лучшую форму решения, и я поделился ею здесь, чтобы помочь будущим пользователям, которые прочитали этот вопрос.
Решение
У меня всегда есть контейнер с некоторыми (или только одними) кнопками внутри. Поэтому я подключаю IBOutlet
контейнера кнопок к UIViewController
или UIView
, с которым я работаю:
@property (weak, nonatomic) IBOutlet UIView *buttonsContainer;
И я установил ноль для распознавания жестов, как показано ниже:
[self.buttonsContainer addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:nil]];
При этом обходном пути, если кнопка отключена, buttonsContainer
фиксирует это событие и ничего не делает с ним.
Надеюсь, что это поможет.