Alright, I have a couple of UITextFields
and UITextViews
inside a UIScrollView
, and I\'d like to set the keyboard to disappear wheneve
In Swift:
Bit late but if anyone else is searching an answer to this problem, this is how I have gone about solving it:
1) Create a tap gesture recognizer with a target callback method to dismiss your keyboard using resignFirstResponder on all your fields.
2) Add the tap gesture to the scrollview.
Here's an example:
import UIKit
class ViewController: UIViewController {
@IBOutlet var t1: UITextField!
@IBOutlet var t2: UITextField!
@IBOutlet var t3: UITextField!
@IBOutlet var t4: UITextField!
@IBOutlet var srcScrollView: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let tapGesture: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "hideKeyboard")
// prevents the scroll view from swallowing up the touch event of child buttons
tapGesture.cancelsTouchesInView = false
srcScrollView.addGestureRecognizer(tapGesture)
}
func hideKeyboard() {
t1.resignFirstResponder()
t2.resignFirstResponder()
t3.resignFirstResponder()
t4.resignFirstResponder()
}
}
Create a extension class for hiding keyboard when touches scrollview/view anywhere
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)
}
}
And call this method in viewDidLoad like
override func viewDidLoad() {
super.viewDidLoad()
self.hideKeyboardWhenTappedAround()
}
scrollView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;
Look at keyboardDismissMode property of UIScrollView.
// will hide keyboard when your text field is about to go beyond the keyboard.
vwScrollView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;
// will hide keyboard instantly once the scroll view started scrolling by user.
vwScrollView.keyboardDismissMode = UIScrollViewKeyboardDismissOnDrag;
// If you need to hide keyboard on tap of scroll view,consider adding a tap gesture or sub class and override touchesbegan: method.
vwScrollView.keyboardDismissMode = .interactive
vwScrollView.keyboardDismissMode = .onDrag
When I added the gesture to a subclass of UIScrollView
, I was having problems with the various gestures in my view tree interfering with each other, such as being able to click on subviews, scroll the view, and have the keyboard dismiss in all cases. I came up with this solution, which can be setup from a superclass of UIScrollView
or from a UIViewController
.
The DismissKeyboardTapGesture
class uses ARC, works with any text fields under the view, and doesn't take over any clicks from subviews like buttons. Also takes advantage of iOS7 scrolling effect to dismiss keyboard.
Setting up from UISScrollView superclass:
_dismissKeyboard = [[DismissKeyboardTapGesture alloc] initWithView:self];
or from UIViewController:
_dismissKeyboard = [[DismissKeyboardTapGesture alloc] initWithView:self.view];
Here is the class:
@interface DismissKeyboardTapGesture : NSObject <UIGestureRecognizerDelegate>
@end
@implementation DismissKeyboardTapGesture
- (id)initWithView:(UIView *)view
{
self = [super init];
if (self) {
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTap:)];
singleTap.cancelsTouchesInView = NO;
singleTap.delegate = self;
[view addGestureRecognizer:singleTap];
if ([view respondsToSelector:@selector(setKeyboardDismissMode:)]) {
// Bonus effect to dismiss keyboard by scrolling
((UIScrollView *)view).keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;
}
}
return self;
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
// Don't stop any existing gestures in our view from working
if (otherGestureRecognizer.view == gestureRecognizer.view) {
return YES;
}
return NO;
}
- (void)singleTap:(UIGestureRecognizer*)gestureRecognizer
{
// Close keyboard for any text edit views that are children of the main view
[gestureRecognizer.view endEditing:YES];
}
@end
A bit late but if anyone else is searching an answer to this problem with Swift 3:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
view.endEditing(true)
}