Clement Prem
Clement Prem

Reputation: 3119

IOS - Dismiss keyboard when UIPickerView is touched

I am building a converter app. In the main screen I have a text field to input numbers and below the text field a picker view will allow users to select conversion parameters, (for example kg to g).

I can hide the keyboard when user click the background by using the following method

 (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
 [self.enterInput resignFirstResponder];

but when I touch the picker view the keyboard is not hiding.

My question is how to dismiss the keyboard when a user touches the picker view.

Upvotes: 2

Views: 2859

Answers (3)

Alex Reynolds
Alex Reynolds

Reputation: 6352

I use this in my code. I climb the responder chain and reassign the responder. I put this in my method that shows the pickerView. So far no unexpected issues. Seems to work if a keyboard was showing and seems not to crash if there wasn't a keyboard showing.

    [[UIApplication sharedApplication] sendAction:@selector(resignFirstResponder) to:nil from:nil forEvent:nil];

Upvotes: 1

Clement Prem
Clement Prem

Reputation: 3119

Got a solution

1) First Create a hidden roundRect botton and change the type to custom (fit the size of the picker).

2) Create a touch up inside action

 - (IBAction)hiddenButtonToHideKeyboard:(id)sender {
    [self.enterInput resignFirstResponder];
}

3) Create a keyboard appear notification

[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(onKeyboardAppear:) name:UIKeyboardWillShowNotification object:nil];

4) Create a keyboard disappear notification

 [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(onKeyboardHide:) name:UIKeyboardWillHideNotification object:nil];

5) Make the button visible when keyboard is appeared

 -(void)onKeyboardAppear:(NSNotification *)notification
{
    hiddenButtonToHideKeyboard.hidden=NO;
}

6) Hide the button when the keyboard is disappeared

-(void)onKeyboardHide:(NSNotification *)notification
{
    hiddenButtonToHideKeyboard.hidden=YES;
}

5) done

I dont think it is a perfect solution but it works for me :)

Upvotes: 2

Josh Hudnall
Josh Hudnall

Reputation: 1031

Here you go. UIPickerViews are a fairly complex system of nested UIViews which is why you weren't getting any response from the touchesBegan:withEvent: method. What you can do is create your UIPickerView subclass as follows:

//
//  MyPickerView.h
//

#import <UIKit/UIKit.h>

// Protocol Definition that extends UIPickerViewDelegate and adds a method to indicate a touch
@protocol MyPickerViewDelegate <UIPickerViewDelegate>

// This is the method we'll call when we've received a touch. Our view controller should implement it and hide the keyboard
- (void)pickerViewDidReceiveTouch:(UIPickerView *)pickerView;

@end

@interface MyPickerView : UIPickerView

// We're redefining delegate to require conformity to the MyPickerViewDelegate protocol we just made
@property (nonatomic, weak) id <MyPickerViewDelegate>delegate;

@end


//
//  MyPickerView.m
//

#import "MyPickerView.h"

@implementation MyPickerView
@synthesize delegate = _myPickerViewDelegate; // We changed the data type of delegate as it was declared in the superclass so it's important to link it to a differently named backing variable

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    // We make sure to call the super method so all standard functionality is preserved
    UIView *hitView = [super hitTest:point withEvent:event];

    if (hitView) {
        // This will be true if the hit was inside of the picker
        [_myPickerViewDelegate pickerViewDidReceiveTouch:self];
    }

    // Return our results, again as part of preserving our superclass functionality
    return hitView;
}

@end

Then in your ViewController change it to conform to <MyPickerViewDelegate> instead of <UIPickerViewDelegate>. This is ok since MyPickerViewDelegate inherits from UIPickerViewDelegate and will pass through the standard UIPickerViewDelegate methods.

Finally implement pickerViewDidReceiveTouch: in your view controller:

- (void)pickerViewDidReceiveTouch:(UIPickerView *)pickerView {
    [enterInput resignFirstResponder];
}

Upvotes: 0

Related Questions