Мне нужно реализовать функцию, которая будет вызывать некоторый код, когда я дважды нажимаю на self.view (вид UIViewCotroller
). Но проблема в том, что у меня есть другой объект пользовательского интерфейса в этом представлении, и я не хочу прикреплять какой-либо объект распознавания ко всем из них. Я нашел этот метод ниже, как сделать жест на моем представлении, и я знаю, как он работает. Прямо сейчас я столкнулся с препятствием, какой способ выбрать для создания этого распознавателя, игнорирующего subview. Любые идеи? Спасибо.
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDoubleTap:)];
[doubleTap setNumberOfTapsRequired:2];
[self.view addGestureRecognizer:doubleTap];
ios
uitapgesturerecognizer
Матросов Александр
источник
источник
Ответы:
Вы должны принять
UIGestureRecognizerDelegate
протокол внутриself
объекта и вызвать приведенный ниже метод для проверки представления. Внутри этого метода проверьте свое представлениеtouch.view
и верните соответствующий тип bool (Да / Нет). Что-то вроде этого:- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { if ([touch.view isDescendantOfView:yourSubView]) { return NO; } return YES; }
Изменить: пожалуйста, также проверьте ответ @Ian!
Swift 5
// MARK: UIGestureRecognizerDelegate methods, You need to set the delegate of the recognizer func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { if touch.view?.isDescendant(of: tableView) == true { return false } return true }
источник
-[UIGestureRecognizer requireGestureRecognizerToFail:]
но это может работать без ихif
тест не прошел, ваша реализация не вернет BOOL; для правильного стиля верните YES после блока if (используя{ }
) или вelse
ветви. Тем не менее, спасибо, я сэкономил немного времени на чтении.Другой подход состоит в том, чтобы просто сравнить, является ли представление касания представлением жестов, потому что потомки не передают условие. Хороший простой однострочник:
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { return touch.view == gestureRecognizer.view }
источник
И для варианта Swift:
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool { if touch.view.isDescendantOfView(yourSubView){ return false } return true }
Полезно знать,
isDescendantOfView
возвращаетBoolean
значение, указывающее, является ли получатель частью данного представления или идентичным этому представлению.источник
В Swift 5 и iOS 12
UIGestureRecognizerDelegate
есть метод, называемыйgestureRecognizer(_:shouldReceive:)
.gestureRecognizer(_:shouldReceive:)
имеет следующее объявление:optional func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool
Полный код ниже показывает возможную реализацию для
gestureRecognizer(_:shouldReceive:)
. С помощью этого кода нажатие на подвидViewController
представления (включаяimageView
) не запускаетprintHello(_:)
метод.import UIKit class ViewController: UIViewController, UIGestureRecognizerDelegate { override func viewDidLoad() { super.viewDidLoad() let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(printHello)) tapGestureRecognizer.delegate = self view.addGestureRecognizer(tapGestureRecognizer) let imageView = UIImageView(image: UIImage(named: "icon")!) imageView.frame = CGRect(x: 50, y: 50, width: 100, height: 100) view.addSubview(imageView) // ⚠️ Enable user interaction for imageView so that it can participate to touch events. // Otherwise, taps on imageView will be forwarded to its superview and managed by it. imageView.isUserInteractionEnabled = true } func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { // Prevent subviews of a specific view to send touch events to the view's gesture recognizers. if let touchedView = touch.view, let gestureView = gestureRecognizer.view, touchedView.isDescendant(of: gestureView), touchedView !== gestureView { return false } return true } @objc func printHello(_ sender: UITapGestureRecognizer) { print("Hello") } }
Альтернативной реализацией
gestureRecognizer(_:shouldReceive:)
может быть:func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { return gestureRecognizer.view === touch.view }
Однако обратите внимание, что этот альтернативный код не проверяет,
touch.view
является ли подпредставлениеgestureRecognizer.view
.источник
Полное быстрое решение (делегат должен быть реализован и установлен для распознавателя (ов)):
class MyViewController: UIViewController UIGestureRecognizerDelegate { override func viewDidLoad() { let doubleTapRecognizer = UITapGestureRecognizer(target: self, action: #selector(onBaseTapOnly)) doubleTapRecognizer.numberOfTapsRequired = 2 doubleTapRecognizer.delegate = self self.view.addGestureRecognizer(doubleTapRecognizer) } func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool { if touch.view.isDescendantOfView(self.view){ return false } return true } func onBaseTapOnly(sender: UITapGestureRecognizer) { if sender.state == .Ended { //react to tap } } }
источник
Вариант с использованием CGPoint, которого вы касаетесь (SWIFT 4.0)
class MyViewController: UIViewController, UIGestureRecognizerDelegate { func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { // Get the location in CGPoint let location = touch.location(in: nil) // Check if location is inside the view to avoid if viewToAvoid.frame.contains(location) { return false } return true } }
источник
Очистить быстрый путь
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { return touch.view == self.view }
источник
Обратите внимание, что API gestureRecognizer изменился на:
gestureRecognizer (_: shouldReceive :)
Обратите особое внимание на индикатор подчеркивания (пропуска) для внешней метки первого параметра.
Используя многие из приведенных выше примеров, я не получал событие. Ниже приведен пример, который работает для текущих версий Swift (3+).
public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { var shouldReceive = false if let clickedView = touch.view { if clickedView == self.view { shouldReceive = true; } } return shouldReceive }
источник
Плюс к вышеперечисленным решениям, не забудьте проверить
User Interaction Enabled
свой подвид.источник
Пришлось запретить жест на детском просмотре. Единственное, что сработало, - это разрешить и сохранить первое представление и запретить жест во всех следующих представлениях:
var gestureView: UIView? = nil func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { if (gestureView == nil || gestureView == touch.view){ gestureView = touch.view return true } return false }
источник
Swift 4:
touch.view
теперь является необязательным, поэтому на основе ответа @Antoine:func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { if let touchedView = touch.view, touchedView.isDescendant(of: deductibleBackgroundView) { return false } return true }
источник
Если вы не хотите , чтобы ваша «дважды нажмите распознавань» в конфликт с вашими кнопками и / или другими элементами управления, вы можете установить ,
self
какUIGestureRecognizerDelegate
и реализацию:func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { return !(touch.view is UIControl) }
источник