Đóng bàn phím iOS bằng cách chạm vào bất cứ đâu bằng Swift


409

Tôi đã tìm kiếm tất cả về điều này nhưng dường như tôi không thể tìm thấy nó. Tôi biết cách loại bỏ bàn phím bằng cách sử dụng Objective-Cnhưng tôi không biết làm thế nào để sử dụng bàn phím đó Swift? Có ai biết không?


9
Làm thế nào bạn làm điều đó trong Objective-C? Thông thường, việc chuyển đổi từ cú pháp này sang cú pháp khác và hiếm khi là vấn đề của các phương thức / quy ước khác nhau.
Craig Otis

5
Tôi chưa tìm hiểu về Swift, nhưng tôi có ấn tượng rằng API cũng giống như vậy
cốt lõi vào

Bạn có thể muốn kiểm tra câu trả lời này .
Ahmad F

Câu trả lời:


1299
override func viewDidLoad() {
    super.viewDidLoad()

    //Looks for single or multiple taps. 
    let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "dismissKeyboard")

    //Uncomment the line below if you want the tap not not interfere and cancel other interactions.
    //tap.cancelsTouchesInView = false 

    view.addGestureRecognizer(tap)
}

//Calls this function when the tap is recognized.
@objc func dismissKeyboard() {
    //Causes the view (or one of its embedded text fields) to resign the first responder status.
    view.endEditing(true)
}

Đây là một cách khác để thực hiện nhiệm vụ này nếu bạn sẽ sử dụng chức năng này trong nhiều UIViewControllers:

// Put this piece of code anywhere you like
extension UIViewController {
    func hideKeyboardWhenTappedAround() {
        let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(UIViewController.dismissKeyboard))
        tap.cancelsTouchesInView = false            
        view.addGestureRecognizer(tap)
    }

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

Bây giờ trong tất cả UIViewController, tất cả những gì bạn phải làm là gọi hàm này:

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

Hàm này được bao gồm dưới dạng một hàm tiêu chuẩn trong repo của tôi có chứa rất nhiều Tiện ích mở rộng Swift hữu ích như thế này, hãy kiểm tra xem: https://github.com/goktugyil/EZSwiftExtensions


19
Vì Swift 2 trong câu trả lời đầu tiên, hãy thay thế dòng này-> let tap: UITapGestureRecognizer = UITapGestureRecognizer (target: self, action: #selector (MyViewControll.dismissPal))
Sam Bellerose

2
nó phá vỡ sự khác biệt của tableviewcell trên bộ điều khiển bàn
Utku Dalmaz

11
Đây là một trong những tiện ích mở rộng hữu ích nhất mà tôi từng gặp! Cảm ơn bạn! Sự thận trọng duy nhất tôi sẽ mở rộng là điều này có thể can thiệp vào didSelectRowAtIndexPath.
Clifton Labrum

47
Chỉ cần phát hiện ra câu hỏi này và thực hiện phương pháp đó. Điều đó với "didSelectRow" của tableView / UICollectionView không gọi theo nghĩa đen đã khiến tôi phát điên. Giải pháp là: Đơn giản chỉ cần thêm phần này vào phần mở rộng của bạn : tap.cancelsTouchesInView = false. Điều đó đã giải quyết nó cho tôi ít nhất. Hy vọng điều này sẽ giúp được ai đó
Quantm

10
"Kiểm tra repo của tôi" là "Nghe bản mixtape mới" của tôi: P
Josh

118

Câu trả lời cho câu hỏi của bạn về cách loại bỏ bàn phím trong Xcode 6.1 bằng Swift bên dưới:

import UIKit

class ItemViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet var textFieldItemName: UITextField!

    @IBOutlet var textFieldQt: UITextField!

    @IBOutlet var textFieldMoreInfo: UITextField!


    override func viewDidLoad() {
        super.viewDidLoad()

        textFieldItemName.delegate = self
        textFieldQt.delegate = self
        textFieldMoreInfo.delegate = self
    }

                       ...

    /**
     * Called when 'return' key pressed. return NO to ignore.
     */
    func textFieldShouldReturn(textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        return true
    }


   /**
    * Called when the user click on the view (outside the UITextField).
    */
    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        self.view.endEditing(true)
    }

}

( Nguồn thông tin này ).


6
Tuyệt vời của mã, cảm ơn! touchesBegan chính xác là những gì tôi đang tìm kiếm :)
Lukasz Czerwinski

4
Điều này không làm việc cho tôi. Nếu tôi nhấn vào khung nhìn của trình điều khiển xem thì nó hoạt động. Nếu tôi nhấn vào một mục điều khiển trong chế độ xem, bàn phím sẽ không loại bỏ.
dùng3731622

Đây là câu trả lời tốt nhất mà tôi từng sử dụng cho đến nay! Câu trả lời này nên được đánh dấu là chính xác. Cảm ơn người đàn ông!
wagng

Đây là giải pháp tốt nhất tôi đã thấy cho đến nay. Lưu ý nhỏ: trong Swift mới hơn, chữ ký ghi đè đã thay đổi một chút. Bạn cần phải thêm _ trước chạm: override func touchesBegan (_ chạm: Set <UITouch>, sự kiện withEvent: UIEvent)
Regis St-Gelais

1
Điều này có lẽ nên được đánh dấu là chính xác. Câu trả lời được chấp nhận hiện tại làm cho mọi nút trong chế độ xem không phản hồi khi bàn phím hiển thị.
Bartek Spitza

39

Swift 4 làm việc

Tạo tiện ích mở rộng như bên dưới và gọi hideKeyboardWhenTappedAround()trong bộ điều khiển chế độ xem Cơ sở của bạn.

//
//  UIViewController+Extension.swift
//  Project Name
//
//  Created by ABC on 2/3/18.
//  Copyright © 2018 ABC. All rights reserved.
//

import UIKit

extension UIViewController {
    func hideKeyboardWhenTappedAround() {
        let tapGesture = UITapGestureRecognizer(target: self, 
                         action: #selector(hideKeyboard))
        view.addGestureRecognizer(tapGesture)
    }

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

Điều quan trọng nhất để gọi trong Bộ điều khiển Chế độ xem Cơ sở của bạn để không cần phải gọi mọi lúc trong tất cả các bộ điều khiển xem.


36

Bạn có thể gọi

resignFirstResponder()

trên bất kỳ trường hợp nào của UIResponder, chẳng hạn như UITextField. Nếu bạn gọi nó trên chế độ xem hiện đang khiến bàn phím được hiển thị thì bàn phím sẽ tắt.


5
Trong tình huống mà bạn không biết chính xác người trả lời đầu tiên, việc từ chứcFirstResponder () có thể dẫn đến một đống rắc rối. Câu trả lời của Esq bên dưới (sử dụng view.doneEditing ()) phù hợp hơn rất nhiều
shiser

1
Bất cứ khi nào tôi sử dụng resignFirstResponder trên văn bản của mình, ứng dụng sẽ gặp sự cố. Tôi đã thử mọi cách tôi có thể nghĩ ra và tìm kiếm trên web để tìm cách khắc phục. Không có gì giúp tôi. Bạn sẽ biết tại sao điều đó xảy ra?
AugustoQ

1
Như shiser đã nói đây không phải là giải pháp tốt nhất. cộng với nó không hoạt động trong mọi tình huống.
Alix

21
//Simple exercise to demonstrate, assuming the view controller has a //Textfield, Button and a Label. And that the label should display the //userinputs when button clicked. And if you want the keyboard to disappear //when clicken anywhere on the screen + upon clicking Return key in the //keyboard. Dont forget to add "UITextFieldDelegate" and 
//"self.userInput.delegate = self" as below

import UIKit

class ViewController: UIViewController,UITextFieldDelegate {

    @IBOutlet weak var userInput: UITextField!
    @IBAction func transferBtn(sender: AnyObject) {
                display.text = userInput.text

    }
    @IBOutlet weak var display: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()

//This is important for the textFieldShouldReturn function, conforming to textfieldDelegate and setting it to self
        self.userInput.delegate = self
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

//This is for the keyboard to GO AWAYY !! when user clicks anywhere on the view
    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        self.view.endEditing(true)
    }


//This is for the keyboard to GO AWAYY !! when user clicks "Return" key  on the keyboard

    func textFieldShouldReturn(textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        return true
    }

}

touchesBegan làm việc cho tôi để kết thúc chỉnh sửa textfield và textview. Cảm ơn
Sanju

Đây là những gì tôi sử dụng, đơn giản. Loại bỏ các mã không liên quan để tập trung vào giải pháp.
John Doe

19

đối với Swift 3 thì rất đơn giản

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

nếu bạn muốn ẩn bàn phím khi nhấn phím RETURN

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    textField.resignFirstResponder()
    return true
}

nhưng trong trường hợp thứ hai, bạn cũng sẽ cần chuyển đại biểu từ tất cả các textField sang ViewContoder trong Main.Storyboard


Tôi nhận được unrecognized selector sent to instancevới mã này.
Haring10

11

Swift 3: Cách dễ nhất để loại bỏ bàn phím:

  //Dismiss keyboard method
    func keyboardDismiss() {
        textField.resignFirstResponder()
    }

    //ADD Gesture Recignizer to Dismiss keyboard then view tapped
    @IBAction func viewTapped(_ sender: AnyObject) {
        keyboardDismiss()
    }

    //Dismiss keyboard using Return Key (Done) Button
    //Do not forgot to add protocol UITextFieldDelegate 
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        keyboardDismiss()

        return true
    }

1
Tôi khá chắc chắn rằng lệnh gọi view.endEditing (true) đơn giản hơn ở chỗ nó không yêu cầu bạn lưu trữ một biến hoặc giả sử bạn chỉ có một trường văn bản.
Glenn Howes

10

Câu trả lời của Dash là chính xác và được ưa thích. Một cách tiếp cận "thiêu đốt đất" hơn là gọi view.endEditing(true). Điều này gây ra viewvà tất cả các cuộc phỏng vấn của nó để resignFirstResponder. Nếu bạn không có một tham chiếu đến quan điểm mà bạn muốn loại bỏ, thì đây là một giải pháp hiệu quả nhưng khó khăn.

Lưu ý rằng cá nhân tôi nghĩ rằng bạn nên có một tham chiếu đến quan điểm mà bạn muốn từ chức trả lời đầu tiên. .endEditing(force: Bool)là một cách tiếp cận dã man; xin vui lòng không sử dụng nó.


10

swift 5 chỉ cần hai dòng là đủ. Thêm vào của bạn viewDidLoadnên làm việc.

 let tapGesture = UITapGestureRecognizer(target: view, action: #selector(UIView.endEditing))
 view.addGestureRecognizer(tapGesture)

Nếu cử chỉ nhấn của bạn chặn một số chạm khác, sau đó thêm dòng này:

tapGesture.cancelsTouchesInView = false

Giải pháp rất đơn giản và thanh lịch :), nên là câu trả lời ở đây.
Joseph Astrahan

9

Trong bảng phân cảnh:

  1. chọn TableView
  2. từ phía bên tay phải, chọn trình kiểm tra thuộc tính
  3. trong phần bàn phím - chọn chế độ loại bỏ bạn muốn

không thể tìm thấy món đồ đó, nó ở đâu và nó trông như thế nào? Tôi đang ở trong trình kiểm tra thuộc tính của textField
Ethan Parker

Bạn cần xem TableView chứ không phải TextField
zevij

9

Swift 3:

Mở rộng với Selectortham số dưới dạng để có thể thực hiện các công cụ bổ sung trong chức năng loại bỏ và cancelsTouchesInViewđể tránh biến dạng khi chạm vào các yếu tố khác của chế độ xem.

extension UIViewController {
    func hideKeyboardOnTap(_ selector: Selector) {
        let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: selector)
        tap.cancelsTouchesInView = false
        view.addGestureRecognizer(tap)
    }
}

Sử dụng:

override func viewDidLoad() {
    super.viewDidLoad()
    self.hideKeyboardOnTap(#selector(self.dismissKeyboard))
}

func dismissKeyboard() {
    view.endEditing(true)
    // do aditional stuff
}

9

Sử dụng IQPalmanager sẽ giúp bạn giải quyết dễ dàng .....

/////////////////////////////////////////////

! [cách tắt bàn phím ..] [1]

import UIKit

class ViewController: UIViewController,UITextFieldDelegate {

   @IBOutlet weak var username: UITextField!
   @IBOutlet weak var password: UITextField!

   override func viewDidLoad() {
      super.viewDidLoad() 
      username.delegate = self
      password.delegate = self
      // Do any additional setup after loading the view, typically from a nib.
   }

   override func didReceiveMemoryWarning() {
      super.didReceiveMemoryWarning()
      // Dispose of any resources that can be recreated.
   }

   func textFieldShouldReturn(textField: UITextField!) -> Bool // called when   'return' key pressed. return NO to ignore.
   {
      textField.resignFirstResponder()
      return true;
   }

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

8

Tôi tìm thấy giải pháp tốt nhất bao gồm câu trả lời được chấp nhận từ @Esqarrouth, với một số điều chỉnh:

extension UIViewController {
    func hideKeyboardWhenTappedAround() {
        let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "dismissKeyboardView")
        tap.cancelsTouchesInView = false
        view.addGestureRecognizer(tap)
    }

    func dismissKeyboardView() {
        view.endEditing(true)
    }
}

Dòng tap.cancelsTouchesInView = falsenày rất quan trọng: nó đảm bảo rằng UITapGestureRecognizerkhông ngăn các thành phần khác trên chế độ xem nhận được tương tác của người dùng.

Phương pháp dismissKeyboard()đã được thay đổi để hơi kém thanh lịch dismissKeyboardView(). Điều này là do trong cơ sở mã khá cũ của dự án của tôi, đã có nhiều lần dismissKeyboard()sử dụng (tôi tưởng tượng điều này không phổ biến), gây ra sự cố trình biên dịch.

Sau đó, như trên, hành vi này có thể được bật trong Bộ điều khiển Xem riêng lẻ:

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

7

Nếu bạn sử dụng chế độ xem cuộn, nó có thể đơn giản hơn nhiều.

Chỉ cần chọn Dismiss interactivelytrong bảng phân cảnh.


7

Trong Swift 4, thêm @objc:

Trong viewDidLoad:

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

Chức năng:

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

7

Thêm tiện ích mở rộng này vào ViewContoder của bạn:

  extension UIViewController {
// Ends editing view when touches to view 
  open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    super.touchesBegan(touches, with: event)
    self.view.endEditing(true)
  }
}

6

Để mở rộng câu trả lời của Esqarrouth , tôi luôn sử dụng cách sau để loại bỏ bàn phím, đặc biệt nếu lớp mà tôi loại bỏ bàn phím không có thuộc viewtính và / hoặc không phải là lớp con củaUIView .

UIApplication.shared.keyWindow?.endEditing(true)

Và, để thuận tiện, phần mở rộng sau đây cho UIApplcationlớp:

extension UIApplication {

    /// Dismisses the keyboard from the key window of the
    /// shared application instance.
    ///
    /// - Parameters:
    ///     - force: specify `true` to force first responder to resign.
    open class func endEditing(_ force: Bool = false) {
        shared.endEditing(force)
    }

    /// Dismisses the keyboard from the key window of this 
    /// application instance.
    ///
    /// - Parameters:
    ///     - force: specify `true` to force first responder to resign.
    open func endEditing(_ force: Bool = false) {
        keyWindow?.endEditing(force)
    }

}

5
  import UIKit

  class ItemViewController: UIViewController, UITextFieldDelegate {

  @IBOutlet weak var nameTextField: UITextField!

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

    // Called when 'return' key pressed. return NO to ignore.

    func textFieldShouldReturn(textField: UITextField) -> Bool {

            textField.resignFirstResponder()
             return true
     }

 // Called when the user click on the view (outside the UITextField).

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

5

Là một lập trình viên mới làm quen, có thể gây nhầm lẫn khi mọi người tạo ra các phản hồi có kỹ năng và không cần thiết hơn ... Bạn không phải thực hiện bất kỳ nội dung phức tạp nào được hiển thị ở trên! ...

Đây là tùy chọn đơn giản nhất ... Trong trường hợp bàn phím của bạn xuất hiện để phản hồi trường văn bản - Bên trong chức năng màn hình cảm ứng của bạn chỉ cần thêm chức năng resignFirstResponder . Như được hiển thị bên dưới - bàn phím sẽ đóng vì Phản hồi đầu tiên được phát hành (thoát khỏi chuỗi Phản hồi) ...

override func touchesBegan(_: Set<UITouch>, with: UIEvent?){
    MyTextField.resignFirstResponder()
}

5

Tôi đã sử dụng IQKeyBoardManagerSwift cho bàn phím. Nó rất dễ dàng để sử dụng. chỉ cần thêm nhóm 'IQPalManagerSwift'

Nhập IQKeyboardManagerSwift và ghi mã trên didFinishLaunchingWithOptionstrong AppDelegate.

///add this line 
IQKeyboardManager.shared.shouldResignOnTouchOutside = true
IQKeyboardManager.shared.enable = true

4

Lớp lót này sẽ từ bỏ Bàn phím khỏi tất cả (bất kỳ) UITextField trong UIView

self.view.endEditing(true)

4

Chỉ một dòng mã trong viewDidLoad()phương thức:

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

4

Trong swift bạn có thể sử dụng

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

}

3

Dành cho Swift3

Đăng ký một trình nhận dạng sự kiện trong viewDidLoad

let tap = UITapGestureRecognizer(target: self, action: #selector(hideKeyBoard))

sau đó chúng ta cần thêm cử chỉ vào dạng xem trong cùng viewDidLoad.

self.view.addGestureRecognizer(tap)

Sau đó, chúng ta cần khởi tạo phương thức đã đăng ký

func hideKeyBoard(sender: UITapGestureRecognizer? = nil){
    view.endEditing(true)
}

1
Cảm ơn câu trả lời đầy đủ và ghi chú. Đây là giải pháp duy nhất làm việc cho tôi.
zeeshan

3

Đăng như một câu trả lời mới kể từ khi chỉnh sửa câu trả lời của @ King-Wizard bị từ chối.

Biến lớp của bạn thành đại biểu của UITextField và ghi đè touchesBegan.

Swift 4

import UIKit

class ViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet var textField: UITextField!

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

    //Called when 'return' key is pressed. Return false to keep the keyboard visible.
    func textFieldShouldReturn(textField: UITextField) -> Bool {
        return true
    }

    // Called when the user clicks on the view (outside of UITextField).
    override func touchesBegan(touches: Set<UITouch>, with event: UIEvent?) {
        self.view.endEditing(true)
    }

}

2

Bạn cũng có thể thêm một trình nhận dạng cử chỉ nhấn để từ chức bàn phím. : D

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

    let recognizer = UITapGestureRecognizer(target: self, action: Selector("handleTap:"))
    backgroundView.addGestureRecognizer(recognizer)
}
    func handleTap(recognizer: UITapGestureRecognizer) {
    textField.resignFirstResponder()
    textFieldtwo.resignFirstResponder()
    textFieldthree.resignFirstResponder()

    println("tappped")
}

2

Một khả năng khác là chỉ cần thêm một nút lớn không có nội dung nằm bên dưới tất cả các chế độ xem bạn có thể cần phải chạm vào. Cung cấp cho nó một hành động có tên:

@IBAction func dismissKeyboardButton(sender: AnyObject) {
    view.endEditing(true)
}

Vấn đề với một trình nhận dạng cử chỉ là đối với tôi, rằng nó cũng bắt được tất cả các lần chạm mà tôi muốn nhận được bởi bảngViewCells.


2

Nếu bạn có các chế độ xem khác cũng sẽ nhận được liên lạc, bạn phải đặt cancelsTouchesInView = false

Như thế này:

let elsewhereTap = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))
    elsewhereTap.cancelsTouchesInView = false
    self.view.addGestureRecognizer(elsewhereTap)

2
override func viewDidLoad() {
        super.viewDidLoad()

self.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(tap)))

}

func tap(sender: UITapGestureRecognizer){
        print("tapped")
        view.endEditing(true)
}

Hãy thử nó, nó hoạt động


1

Khi có nhiều hơn một trường văn bản trong dạng xem

Thực hiện theo khuyến nghị của @ modocache để tránh gọi điệnview.endEditing() , bạn có thể theo dõi trường văn bản trở thành phản hồi đầu tiên, nhưng điều đó rất lộn xộn và dễ bị lỗi.

Một cách khác là gọi resignFirstResponder() trên tất cả các trường văn bản trong trình điều khiển khung nhìn . Đây là một ví dụ về việc tạo một bộ sưu tập của tất cả các trường văn bản (trong trường hợp của tôi là cần thiết cho mã xác thực):

@IBOutlet weak var firstName: UITextField!
@IBOutlet weak var lastName: UITextField!
@IBOutlet weak var email: UITextField!

var allTextFields: Array<UITextField>!  // Forced unwrapping so it must be initialized in viewDidLoad
override func viewDidLoad()
{
    super.viewDidLoad()
    self.allTextFields = [self.firstName, self.lastName, self.email]
}

Với bộ sưu tập có sẵn, việc lặp lại tất cả chúng là một vấn đề đơn giản:

private func dismissKeyboard()
{
    for textField in allTextFields
    {
        textField.resignFirstResponder()
    }
}

Vì vậy, bây giờ bạn có thể gọi dismissKeyboard()trong nhận dạng cử chỉ của bạn (hoặc bất cứ nơi nào phù hợp với bạn). Hạn chế là bạn phải duy trì danh sách UITextFields khi bạn thêm hoặc xóa các trường.

Bình luận hoan nghênh. Nếu có vấn đề với việc gọi các resignFirstResponder()điều khiển không phải là phản hồi đầu tiên hoặc nếu có cách dễ dàng và được bảo đảm để theo dõi phản hồi đầu tiên hiện tại, tôi rất muốn nghe về điều đó!

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.