Reputation: 7102
I'm trying to give my users a way to dismiss the keyboard, whether by clicking outside the keyboard or by having a DONE button on the keyboard itself.
I have created a Done button and it works fine on iOS 6:
UIToolbar *keyboardToolbar;
keyboardToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, self.view.bounds.size.height - 44, 320, 44)];
UIBarButtonItem *flexItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
UIBarButtonItem *doneItem = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"dismiss_keyboard", nil) style:UIBarButtonItemStyleDone target:self action:@selector(dismissKeyboard)];
NSArray *items = [NSArray arrayWithObjects:flexItem,doneItem, nil];
[keyboardToolbar setItems:items animated:YES];
for (UIView *subview in [searchBar subviews])
{
if( [subview isKindOfClass:[UITextField class]] )
{
((UITextField*)subview).delegate=self;
((UITextField*)subview).inputAccessoryView = keyboardToolbar;
break;
}
}
But on iOS 7 this button is no where to be found.
I also tried using the method where the user can click anywhere but the keyboard and make it disappear:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesBegan:touches withEvent:event];
//Code to dismiss keyboard.
}
But my view contains a UISearchBar
and a UITableView
but the touchesBegan
event doesn't fire when I touch those, only when I touch the parent UIView, which is not visible because it's covered by my UISearchBar
and my UITableView
. I have to touch the tiny space in between the two to fire the event.
How can I make my touchesBegan
method apply to any object on the screen? And why is my DONE button not showing up in iOS 7?
Upvotes: 1
Views: 2222
Reputation: 5667
Use the below approach & get that Done button on your keyboard in iOS7.
Sample code is here.
Screenshot of Done button after using this approach is here.
Upvotes: 0
Reputation: 66242
Why is my DONE button not showing up in iOS 7?
Your DONE button isn't showing up because the internal structure of UISearchBar, which you aren't supposed to modify, has changed. (This is the reason you're not supposed to modify it.)
If you want to continue this non-recommended behavior and get it working, instead of checking if it's a UITextField, you can try checking if it conforms to UITextInputTraits, and iterate through subviews of subviews:
for(UIView *subView in [searchBar subviews]) {
if([subView conformsToProtocol:@protocol(UITextInputTraits)]) {
// iOS 6
[(UITextField *)subView setReturnKeyType: UIReturnKeyDone];
} else {
// iOS 7
for(UIView *subSubView in [subView subviews]) {
if([subSubView conformsToProtocol:@protocol(UITextInputTraits)]) {
[(UITextField *)subSubView setReturnKeyType: UIReturnKeyDone];
}
}
}
(This code is from this SO answer.)
However, this approach is not recommended, because it may break again in iOS 7.1. It also could be more resilient as a recursive method.
How can I make my
touchesBegan
method apply to any object on the screen?
Touch events are handled by the top view, so the UIView will only get them if the other views don't want them. The easiest approach here is to make an invisible UIButton that covers your whole screen, and if it's tapped, dismiss the keyboard and remove the button.
Upvotes: 1