Как отклонить клавиатуру при касании в любом месте за пределами UITextField (в swift)?

Я работаю над проектом, который имеет UIViewController, на контроллере представления есть UIScrollView и UITextField на scrollview. вроде этого: Я пытаюсь отключить клавиатуру и скрыть ее после ввода текста в текстовое поле и нажмите в любом месте за пределами текстового поля. Я пробовал следующий код:

override func viewDidLoad() {
    super.viewDidLoad()
    self.textField.delegate = self;
}

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    self.view.endEditing(true)
}

это работает для меня, когда я нажимаю вне scrollview, но когда я нажимаю на scrollview ничего не происходит, и клавиатура не прятаться.

есть ли способ закрыть клавиатуру при нажатии в любом месте за пределами текстового поля? спасибо

15 ответов


отредактировано для Swift 4

Edit: Добавлено @objc. Хотя это не лучший вариант для производительности, один экземпляр здесь не должен вызывать слишком много проблем, пока не будет лучшего решения.

отредактировано для исправления при необходимости взаимодействия с элементами за GestureRecognizer.

Edit: спасибо @Rao за указание на это. Добавлено tap.cancelsTouchesInView = false.

это должно помочь вам иметь несколько UITextView или UITextField

создайте расширение контроллера вида. Это сработало намного плавнее для меня и с меньшими хлопотами, чем попытка использовать .resignFirstResponder()

extension UIViewController
{
    func hideKeyboard()
    {
        let tap: UITapGestureRecognizer = UITapGestureRecognizer(
            target: self,
            action: #selector(UIViewController.dismissKeyboard))

        tap.cancelsTouchesInView = false
        view.addGestureRecognizer(tap)
    }

    @objc func dismissKeyboard()
    {
        view.endEditing(true)
    }
}

вызов self.hideKeyboard() в viewDidLoad


попробуйте это, он протестирован и работает:

Для Swift 3.0 / 4.0

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    self.view.endEditing(true)
}

Для Старшего Swift

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent) {
    self.view.endEditing(true)
}

в этом случае одним из вариантов является UITapGesture. Я попытался создать пример кода на всякий случай. Вот так,

class ViewController: UIViewController {

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

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        let tapGesture = UITapGestureRecognizer(target: self, action: "tap:")
        view.addGestureRecognizer(tapGesture)
    }

    func tap(gesture: UITapGestureRecognizer) {
        textField.resignFirstResponder()
    }
}

рабочее решение для Swift 3, которое работает с ScrollView

class ViewController: UIViewController {

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

    override func viewDidLoad() {
        super.viewDidLoad()

        // The next line is the crucial part
        // The action is where Swift 3 varies from previous versions
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.tap(gesture:)))
        self.view.addGestureRecognizer(tapGesture)
    }

    func tap(gesture: UITapGestureRecognizer) {
        textField.resignFirstResponder()
    }
}

другое вопрос это говорит об этой проблеме, на которую я ссылался и использовал. Принято отвечать больше не работает в Swift 3. Текущий выбранный ответ должен быть ответом ниже.


swift 3

override func viewDidLoad() {
    super.viewDidLoad()
    self.view.addGestureRecognizer(UITapGestureRecognizer(target: self.view, action: #selector(UIView.endEditing(_:))))
}

подробности

xCode 8.2.1, Swift 3

задание

установите UITapGestureRecognizer для просмотра UIViewController, который закроет клавиатуру и сделает эту функцию свойством Bool UIView.

сложная реализация, но использование находится в одной строке

класс TapGestureRecognizer

import UIKit

class TapGestureRecognizer: UITapGestureRecognizer {

    let identifier: String

    private override init(target: Any?, action: Selector?) {
        self.identifier = ""
        super.init(target: target, action: action)
    }

    init(target: Any?, action: Selector?, identifier: String) {
        self.identifier = identifier
        super.init(target: target, action: action)
    }

    static func == (left: TapGestureRecognizer, right: TapGestureRecognizer) -> Bool {
        return left.identifier == right.identifier
    }
}

расширение UIView

import UIKit

extension UIView {

    private var disableKeybordWhenTappedGestureRecognizerIdentifier:String {
        return "disableKeybordWhenTapped"
    }

    private var disableKeybordWhenTappedGestureRecognizer: TapGestureRecognizer? {

        let hideKeyboardGesture = TapGestureRecognizer(target: self, action: #selector(UIView.hideKeyboard), identifier: disableKeybordWhenTappedGestureRecognizerIdentifier)

        if let gestureRecognizers = self.gestureRecognizers {
            for gestureRecognizer in gestureRecognizers {
                if let tapGestureRecognizer = gestureRecognizer as? TapGestureRecognizer, tapGestureRecognizer == hideKeyboardGesture, tapGestureRecognizer == hideKeyboardGesture {
                    return tapGestureRecognizer
                }
            }
        }
        return nil
    }

    @objc private func hideKeyboard() {
        endEditing(true)
    }

    var disableKeybordWhenTapped: Bool {

        set {
            let hideKeyboardGesture = TapGestureRecognizer(target: self, action: #selector(UIView.hideKeyboard), identifier: disableKeybordWhenTappedGestureRecognizerIdentifier)

            if let disableKeybordWhenTappedGestureRecognizer = self.disableKeybordWhenTappedGestureRecognizer {
                removeGestureRecognizer(disableKeybordWhenTappedGestureRecognizer)
                if gestureRecognizers?.count == 0 {
                    gestureRecognizers = nil
                }
            }

            if newValue {
                addGestureRecognizer(hideKeyboardGesture)
            }
        }

        get {
            return disableKeybordWhenTappedGestureRecognizer == nil ? false : true
        }
    }
}

использование

view.disableKeybordWhenTapped = true

полный Образец

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        let textField = UITextField(frame: CGRect(x: 50, y: 50, width: 200, height: 30))
        textField.borderStyle = .roundedRect
        textField.placeholder = "Enter text"
        view.addSubview(textField)

        view.disableKeybordWhenTapped = true
    }
}

зацени.

override func viewDidLoad() {
    var tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.handleTap))
    self.view.userInteractionEnabled = true
    self.view.addGestureRecognizer(tapGesture)
}

тогда ваш обработчик крана.

  func handleTap(sender: UITapGestureRecognizer) {
    self.view.endEditing(true)
}

это работает при касании вне области ввода для любого количества входных элементов.

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        self.view.endEditing(true)
    }

Для Swift 3

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    self.view.endEditing(true)
}

у меня была такая же проблема, и я наконец решил его !

установите TapGestureRecognizer в раскадровке, а затем розетку в ViewController

@IBOutlet var tapGesture: UITapGestureRecognizer!

затем установите IBAction в своем ViewController

@IBAction func DismissKeyboard(sender: UITapGestureRecognizer)
{
 self.view.endEditing(true)
} 

добавьте эти строки в метод viewDidLoad

override func viewDidLoad()
{
    super.viewDidLoad()
    self.view.addGestureRecognizer(tapGesture)
}

и

надеюсь, что поможет !


каждое касание отличается от текстовое поле закрыть клавиатуру или использовать resignfirstresponder

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
 UITouch *touch = [touches anyObject];
 if(![touch.view isMemberOfClass:[UITextField class]]) {
     [touch.view endEditing:YES];
 }
}

func findAndResignFirstResponder(_ stView: UIView) -> Bool {

    if stView.isFirstResponder {
        stView.resignFirstResponder()
        return true
    }
    for subView: UIView in stView.subviews {
        if findAndResignFirstResponder(subView) {
            return true
        }
    }
    return false
}

Я создал этот метод в Obj-C, который скрывает клавиатуру независимо от того, где пользователь в настоящее время набирает:

//call this method
+ (void)hideKeyboard {
    //grab the main window of the application
    UIWindow *window = [UIApplication sharedApplication].keyWindow;
    //call our recursive method below
    [self resignResponderForView:window];
}

//our recursive method
+ (void)resignResponderForView:(UIView *)view {
    //resign responder from this view
    //If it has the keyboard, then it will hide the keyboard
    [view resignFirstResponder];
    //if it has no subviews, then return back up the stack
    if (view.subviews.count == 0)
        return;
    //go through all of its subviews
    for (UIView *subview in view.subviews) {
        //recursively call the method on those subviews
        [self resignResponderForView:subview];
    }
}

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


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

super.touchingBegins(touches, withEvent: event)
 }

введите распознаватель жестов крана и установите и действие для него.

использовать код:

nameofyourtextfield.resignfirstresponder()