可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm working on a project that have a UIViewController, on the view controller there is a UIScrollView and a UITextField on the scrollview.
like this:
I'm trying to dismiss the keyboard and hide it after typing some text in the textfield and tap anywhere outside the textfield.
I've tried the following code:
override func viewDidLoad() {
super.viewDidLoad()
self.textField.delegate = self;
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
self.view.endEditing(true)
}
It works for me when I tap outside the scrollview, but when I tap on the scrollview nothing happens and the keyboard doesn't hide.
Is there any way to dismiss the keyboard when tapping anywhere outside the textfield?
thanks
回答1:
Edited for Swift 4
Edit: Added @objc
. While this isn't the best option for performance, one instance of it here shouldn't cause too many problems until there is a better solution.
Edited to fix when needing to interact with items behind GestureRecognizer.
Edit: Thanks @Rao for pointing this out. Added tap.cancelsTouchesInView = false
.
This should help you with having multiple UITextView
or UITextField
Create an extension of the view controller. This has worked much smoother for me and with less hassle than trying to use .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)
}
}
Call self.hideKeyboard()
in the viewDidLoad
回答2:
Try this, it's tested and working:
For Swift 3.0 / 4.0
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true)
}
For Older Swift
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent) {
self.view.endEditing(true)
}
回答3:
In this case, there is UITapGesture as one of the choices. I tried to create sample code just in case. Like this,
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()
}
}
回答4:
Working Solution for Swift 3 that works with 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()
}
}
Another question that talks about this issue that I referenced and used. The accepted answer no longer works in Swift 3. The current selected answer should be the below answer.
回答5:
swift 3
override func viewDidLoad() {
super.viewDidLoad()
self.view.addGestureRecognizer(UITapGestureRecognizer(target: self.view, action: #selector(UIView.endEditing(_:))))
}
回答6:
Details
xCode 8.2.1, Swift 3
Task
Set UITapGestureRecognizer for view of UIViewController which will close keyboard and make this functionality as Bool property of UIView.
Complex implementation but the usage is in one line
class 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
}
}
extension 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
}
}
}
Usage
view.disableKeybordWhenTapped = true
Full Sample
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
}
}
回答7:
Check this out.
override func viewDidLoad() {
var tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.handleTap))
self.view.userInteractionEnabled = true
self.view.addGestureRecognizer(tapGesture)
}
Then your tap handler is.
func handleTap(sender: UITapGestureRecognizer) {
self.view.endEditing(true)
}
回答8:
This works when touched outside input area for any number of input items.
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
self.view.endEditing(true)
}
回答9:
For Swift 3
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true)
}
回答10:
I had the same problem and i finally solved it !
Set a TapGestureRecognizer in your Storyboard and then an Outlet in your ViewController
@IBOutlet var tapGesture: UITapGestureRecognizer!
Then set an IBAction in your ViewController
@IBAction func DismissKeyboard(sender: UITapGestureRecognizer)
{
self.view.endEditing(true)
}
add these lines to your viewDidLoad method
override func viewDidLoad()
{
super.viewDidLoad()
self.view.addGestureRecognizer(tapGesture)
}
and its should work
Hope that will help !
回答11:
Every touch different of text field dismiss the keyboard or use resignfirstresponder
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
if(![touch.view isMemberOfClass:[UITextField class]]) {
[touch.view endEditing:YES];
}
}
回答12:
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
}
回答13:
I created this method in Obj-C that hides a keyboard no matter where the user is currently typing:
//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];
}
}
I hope that that is translate-able into Swift and makes sense. It can be called anywhere in the application and will hide the keyboard no matter what VC you're on or anything.
回答14:
Go to Keyboard Type and Select Default or whatever you need the TextField for. Then override a method call it whatever you want i usually call it touchingBegins. Below is what you forgot to add
super.touchingBegins(touches, withEvent: event)
}
回答15:
Introduce a tap gesture recogniser and set and action for it.
Use the code:
nameofyourtextfield.resignfirstresponder()