it-swarm.com.ru

iOS - Отключить клавиатуру при касании за пределами UITextField

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

438
jonepatr

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

Код:

In viewDidLoad

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

[self.view addGestureRecognizer:tap];

В dismissKeyboard:

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

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

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

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

для dismissKeyboard

func dismissKeyboard (_ sender: UITapGestureRecognizer) {
    aTextField.resignFirstResponder()
}
733
Jensen2k

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

Используйте ivar, который инициализируется во время 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];
}
171
drewish

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

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

Или же

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

https://github.com/michaeltyson/TPKeyboardAvoiding

100
Prasad De Zoysa

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

[tap setCancelsTouchesInView:NO];

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

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

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

84
Qiao Yi

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

- (IBAction)dismissKeyboard:(id)sender {
    [aTextBox resignFirstResponder];
}
55
Dmitry Sitnikov

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

override func viewDidLoad() {
    super.viewDidLoad()

    let tapper = UITapGestureRecognizer(target: self, action:#selector(endEditing))
    tapper.cancelsTouchesInView = false
    view.addGestureRecognizer(tapper)
}
28
Rob

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
    }
}
20
FBente

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

- (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];
            }
        } 
    }
}
17
Mr H

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

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

14
eduludi

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

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

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

10
Enzo Tran

Swift 4 oneliner

view.addGestureRecognizer(UITapGestureRecognizer(target: view, action: #selector(UIView.endEditing(_:))))
7
newDeveloper

Вы можете сделать это, используя раскадровку в XCode 6 и выше:


Создать действие, чтобы скрыть клавиатуру

Добавьте это в файл заголовка класса, используемого вашим ViewController:

@interface TimeDelayViewController : UIViewController <UITextFieldDelegate>

- (IBAction)dissmissKeyboardOnTap:(id)sender;

@end

Затем добавьте это в файл реализации того же ViewController:

- (IBAction)dissmissKeyboardOnTap:(id)sender{
    [[self view]endEditing:YES];
}

Теперь это будет одно из "Полученных действий" для вашей раскадровки (т.е. ViewController):

enter image description here


Подключите действие к пользовательскому событию

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

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

enter image description here

... и измените его класс:

enter image description here

Теперь перетащите курсор из маленького кружка рядом с "полученным действием" для вашей сцены на "пустую" часть вашей сцены (фактически вы перетаскиваете "Полученное действие" в UIControl). Вам будет показан выбор событий, к которым вы можете подключить свое действие:

enter image description here

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

(ПРИМЕЧАНИЕ. Чтобы привязать действие к событию, вы также можете перетащить полученное действие непосредственно в UIControl в иерархии View Controllers. В иерархии это отображается как "Control".)

6
Chris Halcrow

Это должен быть самый простой способ скрыть клавиатуру, прикоснувшись снаружи:

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

(из Как отключить клавиатуру, когда пользователь нажимает на другую область вне текстового поля? )

6
KoreanXcodeWorker

Если представление вообще встроено в UIScrollView, тогда вы можете использовать следующее:

tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;
tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;

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

Обратите внимание, что они доступны на iOS 7.0 или выше.

5
Joe Masilotti

Если я вас правильно понял, вы хотите уйти в отставку, нажав на внешнюю сторону textfield, но у вас нет ссылки на ваше textfield.

Попробуй это;

  • Возьмите глобальный textField, давайте назовем его reftextField
  • Теперь в textFieldDidBeginEditing установите ссылочное текстовое поле в

    - (void) textFieldDidBeginEditing:(UITextField *)textField{
        reftextField = textField;
    }
    
  • Теперь вы можете с радостью использовать на любой кнопке часы (рекомендуется добавить прозрачную кнопку при начале редактирования)

    - (void)dismissKeyboard {
          [reftextField resignFirstResponder];
    }
    
  • Или для отставки готовой кнопки попробуйте это.

    //for resigning on done button    
    - (BOOL) textFieldShouldReturn:(UITextField *)textField{
        [textField resignFirstResponder];
        return YES;
    }
    
5
rptwsthi

Быстрая версия ответа @ Jensen2k:

let gestureRecognizer : UITapGestureRecognizer = UITapGestureRecognizer.init(target: self, action: "dismissKeyboard")
self.view.addGestureRecognizer(gestureRecognizer)

func dismissKeyboard() {
    aTextField.resignFirstResponder()
}

Один лайнер

self.view.addTapGesture(UITapGestureRecognizer.init(target: self, action: "endEditing:"))
3
Syed Asad Ali

Просто чтобы добавить сюда список моей версии о том, как отклонить клавиатуру при внешнем прикосновении.

viewDidLoad:

UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)];
[self.view addGestureRecognizer:singleTap];

В любом месте:

-(void)handleSingleTap:(UITapGestureRecognizer *)sender{
    [textFieldName resignFirstResponder];
    puts("Dismissed the keyboard");
}
3
John Riselvato

Здесь много хороших ответов об использовании UITapGestureRecognizer--, все из которых ломают кнопку UITextField's clear (X). Решение состоит в том, чтобы подавить распознаватель жестов через его делегат:

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    BOOL touchViewIsButton = [touch.view isKindOfClass:[UIButton class]];
    BOOL touchSuperviewIsTextField = [[touch.view superview] isKindOfClass:[UITextField class]];
    return !(touchViewIsButton && touchSuperviewIsTextField);
}

Это не самое надежное решение, но оно работает для меня.

3
skedastik

Вы можете создать категорию для UiView и переопределить метод touchesBegan следующим образом.

Это работает нормально для меня. И это централизованное решение этой проблемы.

#import "UIView+Keyboard.h"
@implementation UIView(Keyboard)

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self.window endEditing:true];
    [super touchesBegan:touches withEvent:event];
}
@end
3
Hiren

Один из самых простых и коротких способов - добавить этот код к своему viewDidLoad

[self.view addGestureRecognizer:[[UITapGestureRecognizer alloc]
                                     initWithTarget:self.view
                                     action:@selector(endEditing:)]];
2
Sudhin Davis

Я попробовал многие ответы здесь, и мне не повезло. Мой распознаватель жестов касания всегда заставлял мое UIButtons не отвечать при касании, даже если для свойства cancelsTouchesInView распознавателя жестов установлено значение NO.

Вот что в итоге решило проблему:

Ивару:

UITapGestureRecognizer *_keyboardDismissGestureRecognizer;

Когда текстовое поле начинает редактирование, установите распознаватель жестов:

- (void) textFieldDidBeginEditing:(UITextField *)textField
{
    if(_keyboardDismissGestureRecognizer == nil)
    {
        _keyboardDismissGestureRecognizer = [[[UITapGestureRecognizer alloc]
                                       initWithTarget:self
                                       action:@selector(dismissKeyboard)] autorelease];
        _keyboardDismissGestureRecognizer.cancelsTouchesInView = NO;

        [self.view addGestureRecognizer:_keyboardDismissGestureRecognizer];
    }
}

Тогда дело в том, как настроить метод dismissKeyboard:

- (void) dismissKeyboard
{
    [self performSelector:@selector(dismissKeyboardSelector) withObject:nil afterDelay:0.01];
}

- (void) dismissKeyboardSelector
{
    [self.view endEditing:YES];

    [self.view removeGestureRecognizer:_keyboardDismissGestureRecognizer];
    _keyboardDismissGestureRecognizer = nil;
}

Я полагаю, что есть что-то о том, как получить dismissKeyboardSelector из стека выполнения обработки касанием ...

2
user1021430

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

Итак, я добавил в пример Барри следующее:

- (void) textFieldDidBeginEditing:(UITextField *)textField
{
    _textBeingEdited = textField;
}
-(void) textFieldDidEndEditing:(UITextField *)textField
{
    _textBeingEdited = nil;
}

Также я изменил метод hideKeyboard следующим образом:

- (IBAction)hideKeyboard:(id)sender
{
    // Just call resignFirstResponder on all UITextFields and UITextViews in this VC
    // Why? Because it works and checking which one was last active gets messy.
    //UITextField * tf = (UITextField *) sender;
    [_textBeingEdited resignFirstResponder];
}
2
mtorre

Это работает

В этом примере aTextField является единственным UITextField .... Если есть другие или UITextViews, есть еще кое-что сделать.

// YourViewController.h
// ...
@interface YourViewController : UIViewController /* some subclass of UIViewController */ <UITextFieldDelegate> // <-- add this protocol
// ...
@end

// YourViewController.m

@interface YourViewController ()
@property (nonatomic, strong, readonly) UITapGestureRecognizer *singleTapRecognizer;
@end
// ...

@implementation
@synthesize singleTapRecognizer = _singleTapRecognizer;
// ...

- (void)viewDidLoad
{
    [super viewDidLoad];
    // your other init code here
    [self.view addGestureRecognizer:self.singleTapRecognizer];

{

- (UITapGestureRecognizer *)singleTapRecognizer
{
    if (nil == _singleTapRecognizer) {
        _singleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapToDismissKeyboard:)];
        _singleTapRecognizer.cancelsTouchesInView = NO; // absolutely required, otherwise "tap" eats events.
    }
    return _singleTapRecognizer;
}

// Something inside this VC's view was tapped (except the navbar/toolbar)
- (void)singleTapToDismissKeyboard:(UITapGestureRecognizer *)sender
{
    NSLog(@"singleTap");
    [self hideKeyboard:sender];
}

// When the "Return" key is pressed on the on-screen keyboard, hide the keyboard.
// for protocol UITextFieldDelegate
- (BOOL)textFieldShouldReturn:(UITextField*)textField
{
    NSLog(@"Return pressed");
    [self hideKeyboard:textField];
    return YES;
}

- (IBAction)hideKeyboard:(id)sender
{
    // Just call resignFirstResponder on all UITextFields and UITextViews in this VC
    // Why? Because it works and checking which one was last active gets messy.
    [aTextField resignFirstResponder];
    NSLog(@"keyboard hidden");
}
1
user246672

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

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var scrollView: UIScrollView!
    @IBOutlet weak var textField: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()

        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(ViewController.tap(_:)))
        view.addGestureRecognizer(tapGesture)
        // Do any additional setup after loading the view, typically from a nib.
    }
    func tap(gesture: UITapGestureRecognizer) {
        textField.resignFirstResponder()
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

Ваш Раскадровка Посмотрите на это как.

enter image description here

1
Ravi Dhorajiya
  • Установить текстовые поля делегата в представлении загрузил:

    override func viewDidLoad() 
    {
      super.viewDidLoad()
      self.userText.delegate = self
    }
    
  • Добавьте эту функцию:

    func textFieldShouldReturn(userText: UITextField!) -> Bool 
    {
     userText.resignFirstResponder()
     return true;
    }
    
1
seggy

Добавьте этот код в ваш файл ViewController.m:

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

UITapGestureRecognizer *singleTapGestureRecognizer = [[UITapGestureRecognizer alloc]
                                                          initWithTarget:self
                                                          action:@selector(handleSingleTap:)];
    [singleTapGestureRecognizer setNumberOfTapsRequired:1];
    [singleTapGestureRecognizer requireGestureRecognizerToFail:singleTapGestureRecognizer];

    [self.view addGestureRecognizer:singleTapGestureRecognizer];
}

- (void)handleSingleTap:(UITapGestureRecognizer *)recognizer
{
    [self.view endEditing:YES];
    [textField resignFirstResponder];
    [scrollView setContentOffset:CGPointMake(0, -40) animated:YES];

}
1
Gaurav Gilani

Вы можете использовать метод UITapGestureRecongnizer для отклонения клавиатуры, щелкнув за пределами UITextField. При использовании этого метода всякий раз, когда пользователь нажимает за пределами UITextField, клавиатура получает отклонение. Ниже приведен фрагмент кода для его использования.

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

    [self.view addGestureRecognizer:tap];


//Method
- (void) dismissk
{
    [abctextfield resignFirstResponder];
    [deftextfield resignFirstResponder];

}
1
Nirzar Gandhi
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {

    if let touch = touches.first{
     view.endEditing(true)

     }
}
1
Phani Sai

Отправьте сообщение resignFirstResponder в текстовое поле, в котором оно находится. Пожалуйста см. Этот пост для получения дополнительной информации.

1
Ke Sun

Для тех, кто борется с этим в Свифте. Это принятый ответ Jensen2k, но в Swift.

Swift 2.

    override func viewDidLoad() {
        //.....

        let viewTapGestureRec = UITapGestureRecognizer(target: self, action: #selector(handleViewTap(_:)))
        //this line is important
        viewTapGestureRec.cancelsTouchesInView = false
        self.view.addGestureRecognizer(viewTapGestureRec)

         //.....
    }

    func handleViewTap(recognizer: UIGestureRecognizer) {
        myTextField.resignFirstResponder()
    }
1
lwdthe1
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
    super.view.endEditing(true)
    super.touchesBegan(touches, withEvent: event)
}
0
Derek Dawson

В viewDidLoad Swift 4.2 Код такой

let viewTap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action:#selector(dismissKeyboard))
        view.addGestureRecognizer(viewTap)
@objc func dismissKeyboard() {
        view.endEditing(true)
    }
0
CSE 1994

просто используйте этот код в вашем файле .m, он уйдет в текстовое поле, когда пользователь нажмет за пределы текстового поля.

 -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
  [textfield resignFirstResponder];
 }
0
Amit Shelgaonkar

Так что мне просто нужно было решить эту проблему, и ни один из предыдущих ответов не работал для меня из коробки. Моя ситуация: UISearchBar, а также ряд других элементов управления на экране. Я хочу, чтобы нажатие за пределами панели поиска закрывало клавиатуру, но не распространяться на любые другие элементы управления. Когда клавиатура скрыта, я хочу, чтобы все элементы управления работали.

Что я сделал:

1) Реализовать пользовательский сенсорный обработчик в моем контроллере вида.

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?)
{
    if searchBar.isFirstResponder()
    {
        // This causes the first responder, whoever it is, to resign first responder, and hide the keyboard.
        // We also "eat" the touch here and not allow it to propagate further.
        view.endEditing(true)
    }
    else
    {
        // OK to propagate the touch
        super.touchesBegan(touches, withEvent: event)
    }
}

2) Добавлена ​​пара методов делегатов (мой для UISearchBar, но есть аналогичные для UITextField). controlContainerView в приведенном ниже коде - это UIView, в котором есть несколько кнопок. Помните, что настройка userInteractionEnabled в суперпредставлении отключает все его подпредставления.

 func searchBarTextDidBeginEditing(searchBar: UISearchBar)
 {
     controlContainerView.userInteractionEnabled = false
     someButton.userInteractionEnabled = false
 }

 func searchBarTextDidEndEditing(searchBar: UISearchBar)
 {
     searchBar.resignFirstResponder()

    // Done editing: enable the other controls again.

    controlContainerView.userInteractionEnabled = false
    someButton.userInteractionEnabled = false
}
0
Macondo2Seattle