iOS - Отключить клавиатуру при касании за пределами UITextField - PullRequest
440 голосов
/ 15 марта 2011

Мне интересно, как заставить клавиатуру исчезать, когда пользователь прикасается к внешней стороне UITextField.

Ответы [ 35 ]

735 голосов
/ 15 марта 2011

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

Код:

InDidLoad

UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];

[self.view addGestureRecognizer:tap];

В dismissKeyboard:

-(void)dismissKeyboard 
{
    [aTextField resignFirstResponder];
}

(где aTextField - текстовое поле, отвечающее за клавиатуру)

Swift 3 версия выглядит так

let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.dismissKeyboard (_:)))
self.view.addGestureRecognizer(tapGesture)

Для dismissKeyboard

func dismissKeyboard (_ sender: UITapGestureRecognizer) {
    aTextField.resignFirstResponder()
}
171 голосов
/ 24 июля 2012

Я набрал несколько ответов.

Используйте ивар, который инициализируется во время viewDidLoad:

UIGestureRecognizer *tapper;

- (void)viewDidLoad
{
    [super viewDidLoad];
    tapper = [[UITapGestureRecognizer alloc]
                initWithTarget:self action:@selector(handleSingleTap:)];
    tapper.cancelsTouchesInView = NO;
    [self.view addGestureRecognizer:tapper];
}

Отклонить то, что сейчас редактирует:

- (void)handleSingleTap:(UITapGestureRecognizer *) sender
{
    [self.view endEditing:YES];
}
100 голосов
/ 20 июня 2012

Отметьте это, это будет самый простой способ сделать это,

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
      [self.view endEditing:YES];// this will do the trick
}

Или

Эта библиотека будет обрабатывать, включая автоматическую прокрутку полосы прокрутки, пробел, чтобы скрыть клавиатуру и т. Д.

https://github.com/michaeltyson/TPKeyboardAvoiding

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

Я вижу, что у некоторых людей возникают проблемы при использовании метода UITapGestureRecognizer. Самый простой способ, которым я выполнил эту функцию, при этом оставляя неизменным поведение нажатия моей существующей кнопки, это добавление только одной строки к ответу @ Jensen2k:

[tap setCancelsTouchesInView:NO];

Это позволило моим существующим кнопкам по-прежнему работать без использования метода @Dmitry Sitnikov.

Прочтите об этом property здесь (поиск по CancelsTouchesInView): Справочник по классам UIGestureRecognizer

Я не уверен, как это будет работать с полосами прокрутки, поскольку я вижу, что у некоторых были проблемы, но, надеюсь, кто-то еще может столкнуться с тем же сценарием, что и у меня.

55 голосов
/ 04 августа 2011

Лучше сделать ваш UIView экземпляр UIControl (в конструкторе интерфейсов), а затем подключить их событие TouchUpInside к методу dismissKeyboard. Этот IBAction метод будет выглядеть так:

- (IBAction)dismissKeyboard:(id)sender {
    [aTextBox resignFirstResponder];
}
28 голосов
/ 06 января 2015

Swift версия, это работает в сочетании с другими элементами (например, UIButton или другой UITextField):

override func viewDidLoad() {
    super.viewDidLoad()

    let tapper = UITapGestureRecognizer(target: self, action:#selector(endEditing))
    tapper.cancelsTouchesInView = false
    view.addGestureRecognizer(tapper)
}
20 голосов
/ 26 января 2018

Swift 4

Настройте UIViewController с помощью этого метода расширения, например, в viewDidLoad:

override func viewDidLoad() {
    super.viewDidLoad()
    self.setupHideKeyboardOnTap()
}

и клавиатура будет закрыта даже при нажатии на NavigationBar.

import UIKit
extension UIViewController {
    /// Call this once to dismiss open keyboards by tapping anywhere in the view controller
    func setupHideKeyboardOnTap() {
        self.view.addGestureRecognizer(self.endEditingRecognizer())
        self.navigationController?.navigationBar.addGestureRecognizer(self.endEditingRecognizer())
    }

    /// Dismisses the keyboard from self.view
    private func endEditingRecognizer() -> UIGestureRecognizer {
        let tap = UITapGestureRecognizer(target: self.view, action: #selector(self.view.endEditing(_:)))
        tap.cancelsTouchesInView = false
        return tap
    }
}
17 голосов
/ 04 октября 2011

Как насчет этого: я знаю, что это старый пост. Это может помочь кому-то:)

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {  
    NSArray *subviews = [self.view subviews];
    for (id objects in subviews) {
        if ([objects isKindOfClass:[UITextField class]]) {
            UITextField *theTextField = objects;
            if ([objects isFirstResponder]) {
                [theTextField resignFirstResponder];
            }
        } 
    }
}
14 голосов
/ 10 октября 2014

Это хорошее общее решение:

Objective-C:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    [self.view endEditing:YES];    
}

Swift:

override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
    self.view.endEditing(true)
}

На основе решения @icodebuster: https://stackoverflow.com/a/18756253/417652

10 голосов
/ 05 января 2012

Я думаю, что самый простой (и лучший) способ сделать это - создать подкласс вашего глобального представления и использовать метод hitTest:withEvent для прослушивания любого прикосновения. Касания на клавиатуре не зарегистрированы, поэтому hitTest: withEvent вызывается только тогда, когда вы касаетесь / прокручиваете / проводите / зажимаете ... где-то еще, затем вызываете [self endEditing:YES].

Это лучше, чем использовать touchesBegan, потому что touchesBegan не вызывается, если вы нажмете кнопку в верхней части представления. Это лучше, чем UITapGestureRecognizer, который, например, не может распознать жест прокрутки. Это также лучше, чем использование тусклого экрана, потому что в сложном и динамичном пользовательском интерфейсе нельзя ставить тусклый экран везде. Более того, он не блокирует другие действия, вам не нужно дважды нажимать, чтобы выбрать кнопку снаружи (как в случае UIPopover).

Кроме того, это лучше, чем вызывать [textField resignFirstResponder], потому что у вас может быть много текстовых полей на экране, так что это работает для всех них.

...