How to dismiss keyboard when an UIControl is touched? - ios

This has been asked a few times, but I don't seem to get it.
I have a view controller, with two textfields, one segmented control, a date picker and a few labels.
I want to dismiss the keyboard, when the user clicks the background or the segmented control or the date picker.
Here is my .h file:
#interface MRPatientenViewController : UIViewController
#property (nonatomic, strong) MRPatientenTableViewController *delegate;
- (IBAction)textFieldReturn:(id)sender;
#property (strong, nonatomic) IBOutlet UITextField *nachnameTextField;
#property (strong, nonatomic) IBOutlet UITextField *vornameTextField;
#property (strong, nonatomic) IBOutlet UIDatePicker *geburtsdatumPicker;
#property (strong, nonatomic) IBOutlet UISegmentedControl *genderSegmentedControl;
#end
this is my .m file:
-(IBAction)textFieldReturn:(id)sender{
[sender resignFirstResponder];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
if ([_nachnameTextField isFirstResponder] && [touch view] != _nachnameTextField) {
[_nachnameTextField resignFirstResponder];
}
else if ([_vornameTextField isFirstResponder] && [touch view] != _vornameTextField) {
[_vornameTextField resignFirstResponder];
}
[super touchesBegan:touches withEvent:event];
}
Now this dismisses the keyboard, if the background or the labels are touched.
But how do I dismiss the keyboard if the UISegmentedControl or the datepicker is touched?

You Touch code is correct but it also working fine in my code.when you click outside of text-field at that time Touch event call but its inner condition is not working good.i remove the condition and check its working fine.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[nachnameTextField resignFirstResponder];
[super touchesBegan:touches withEvent:event];
}

UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(dismissKeyboard)];
[geburtsdatumPicker addGestureRecognizer:tap];
[genderSegmentedControl addGestureRecognizer:tap];
[self.view addGestureRecognizer:tap];
Then resign keyboard inside the selector
-(void) dismissKeyboard
{
[nachnameTextField resignFirstResponder];
[vornameTextField resignFirstResponder];
}

Have you tried following line of code
[textfieldInFocus resignFirstResponder];

You can do the following:
UITapGestureRecognizer *tapGesture=[[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(tapAction)];
tapGesture.delegate=self;
[self.view addGestureRecognizer:tapGesture];
- (void)tapAction
{
[nachnameTextField resignFirstResponder];
[vornameTextField resignFirstResponder];
}
and for UISegmentedControl or UIDatePicker you probably have their own selector methods for example:
For UISegmentedControl :
- (IBAction)mainSegmentControl:(UISegmentedControl *)segment{
}
or For UIDatePicker :
- (void)changeDate:(UIDatePicker *)sender {
}
just call your method [self tapAction]; in both above methods and you are good to go...!!

This is the solution which worked for me: the MRViewController.h file:
#import <UIKit/UIKit.h>
#interface MRViewController : UIViewController <UITextFieldDelegate>
#property (strong, nonatomic) IBOutlet UITextField *textField;
#property (strong, nonatomic) IBOutlet UISegmentedControl *segmentedControl;
#end
The MRViewController.m file:
- (void)viewDidLoad
{
[super viewDidLoad];
[self hideKeyboardWhenBackgroundIsTapped];
self.textField.delegate = self;
}
-(void)hideKeyboardWhenBackgroundIsTapped{
UITapGestureRecognizer *tgr = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(hideKeyboard)];
[tgr setCancelsTouchesInView:NO];
[self.view addGestureRecognizer:tgr];
}
-(void)hideKeyboard{
[self.view endEditing:YES];
}
And in my storyboard scene, I got a UITextField and a UISegmentedControl.

Related

Translating a UIView and setting the label text

I'm starting to learn iOS gesture recognizers, going through this tutorial http://www.appcoda.com/ios-gesture-recognizers/. Have a problem translating a view with UIPanGestureRecognizer while setting the UILabels' text to the gesture's velocity.
I have been successfully translating a view with a pan gesture like this (with the help of IB):
PanViewController.h
#interface PanViewController : UIViewController
#property (weak, nonatomic) IBOutlet UIView *testView;
#property (weak, nonatomic) IBOutlet UILabel *horizontalVelocityLabel;
#property (weak, nonatomic) IBOutlet UILabel *verticalVelocityLabel;
#end
PanViewController.m
#interface PanViewController ()
- (void)moveViewWithGestureRecognizer:(UIPanGestureRecognizer *)panGestureRecognizer;
#end
#implementation PanViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(moveViewWithGestureRecognizer:)];
[self.testView addGestureRecognizer:panGestureRecognizer];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void)moveViewWithGestureRecognizer:(UIPanGestureRecognizer *)panGestureRecognizer {
CGPoint touchLocation = [panGestureRecognizer locationInView:self.view];
self.testView.center = touchLocation;
}
But when I add the following lines to this method, the view stops translating, but the UILabels get updated with the velocity:
CGPoint velocity = [panGestureRecognizer velocityInView:self.view];
self.horizontalVelocityLabel.text = [NSString stringWithFormat:#"Horizontal Velocity: %.2f points/sec", velocity.x];
self.verticalVelocityLabel.text = [NSString stringWithFormat:#"Vertical Velocity: %.2f points/sec", velocity.y];
I'd like to understand what i'm doing wrong. How can I fix it?
Thanks in advance.

UITap gesture only works on one view

I have the following code in a view controller:
#interface QuizController ()
#property (weak, nonatomic) IBOutlet UITextView *questionText;
#property (weak, nonatomic) IBOutlet UITextView *one;
#property (weak, nonatomic) IBOutlet UITextView *two;
#property (weak, nonatomic) IBOutlet UITextView *three;
#property (weak, nonatomic) IBOutlet UITextView *four;
#property(strong, nonatomic) NSMutableArray* possAnswers;
#end
#implementation QuizController
- (void)viewDidLoad {
[super viewDidLoad];
[self.manager setupGame];
self.possAnswers = [[NSMutableArray alloc] initWithObjects:#"a", #"b", #"c", #"d", nil];
}
//This listens for a tap on any of the TextViews and sets the background to Blue
- (IBAction)fourTapped:(id)sender {
NSLog(#"There's been a tap!");
[self blankBoxes];
if( [sender isKindOfClass:[UITapGestureRecognizer class]] )
{
UITapGestureRecognizer* tgr = (UITapGestureRecognizer*)sender;
UIView* view = tgr.view;
if( [view isKindOfClass:[UITextView class]]){
UITextView* tv = (UITextView*)view;
NSLog([tv text]);
[tv setBackgroundColor:[UIColor blueColor]];
}
}
}
-(void)blankBoxes
{
[_one setBackgroundColor:[UIColor whiteColor]];
[_two setBackgroundColor:[UIColor whiteColor]];
[_three setBackgroundColor:[UIColor whiteColor]];
[_four setBackgroundColor:[UIColor whiteColor]];
}
However, the only UITextView that gets highlighted is _one, no matter which view is tapped. I don't understand why this is. I'd be really grateful if anyone could point this out to me.
Gesture recognizers attach to one and only one view. That's by design. If you want a single gesture recognizer that lets you recognize taps on multiple views, you have to attach it to a common, enclosing superview, then look at the tap coordinates and figure out which view was tapped.
Normally you just create a different gesture recognizer for each view that needs to responds to taps.
Add the UIGestureRecognizer to a UIView that contains your subviews. After that use CGRectContainsPoint() to check if the tap location is in one of the subviews, then continue from there.
CGPoint *touchLocation = [gesture locationInView:self];
for(UIView *view in self.subviews){
if(CGRectContainsPoint(view.frame, touchLocation))
//Your code here
}

touchesBegan not being called

I'm using a UIPicker to populate a UITextField instead of a keyboard. This works great but I can't close the UIPicker now. I want to be able to tap anywhere on the screen and close the UIPicker. I've tried each of the touches method an none will fire.
setUserInteractionEnabled:YES.
Not sure if it makes a difference but I'm using a StoryBoard
Should I have set something up in my AppDelegate to listen for touches?
Here is my .h
#import <UIKit/UIKit.h>
#interface RNMemberTableViewController : UITableViewController<UIPickerViewDataSource, UIPickerViewDelegate, UITextFieldDelegate>
#property (weak, nonatomic) IBOutlet UIPickerView *behaviorPicker;
#property (nonatomic, weak) IBOutlet UIDatePicker *dateOfRecordPicker;
#property (nonatomic, strong) NSArray *behaviorLevels;
#property (weak, nonatomic) IBOutlet UITextField *behaviorTextField;
#end
here is some of the implementation...
- (void)viewDidLoad
{
[super viewDidLoad];
[self.view setUserInteractionEnabled:YES];
[self buildBehaviorPicker];
NSLog(#"Member View");
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(#"test");
[self.view touchesBegan:touches withEvent:event];
UITouch *touch = [touches anyObject];
int tCount = touch.tapCount;
NSLog(#"Touched %d", tCount);
}
- (void) buildBehaviorPicker
{
behaviorLevels = [[NSArray alloc] initWithObjects:#"Unsatisfactory", #"Needs Improvement", #"Satisfactory", #"Outstanding", nil];
UIPickerView *pickerView = [[UIPickerView alloc] init];
pickerView.dataSource = self;
pickerView.delegate = self;
[pickerView selectRow:2 inComponent:0 animated:NO];
self.behaviorTextField.inputView = pickerView;
}
Thanks in advance
-Bob
You can always try the following:
-(void)viewDidLoad
{
[super viewDidLoad];
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapReceived:)];
[tapGestureRecognizer setDelegate:self];
[self.view addGestureRecognizer:tapGestureRecognizer];
}
-(void)tapReceived:(UITapGestureRecognizer *)tapGestureRecognizer
{
// do something, like dismiss your view controller, picker, etc., etc.
}
Hope this helps ...
You can add a transparent button of the same size as the controller's view under the picker.
Set button.hidden = NO when the picker is shown and set button.hidden = YES when the picker is hidden.
There are ways to hide the picker. The easiest way is to set picker.hidden = YES.
If you are using UIScrollView then
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
will not be called, as touchesBegan is a method of UIView and not of UIScrollView.

UITapGestures in Middle of Animations

I'm am trying to delete an image while it is moving on the screen using UITapGestureRecognizers and UIViewAnimation. I have used the UIViewAnimationOptionAllowUserInteraction, but I still get the SIGBART error. I have been looking through the internet and couldn't find a solution.
This is my .m file
#import "AbcViewController.h"
#interface AbcViewController ()
#end
#implementation AbcViewController
//single tap gesture action /deletes person
-(void) tapped:(UITapGestureRecognizer *)recognizer{
[recognizer.view removeFromSuperview];
}
//double tap gesture action
-(void) tapped2:(UITapGestureRecognizer *)recognizer{
[recognizer.view removeFromSuperview];
}
- (void)viewDidLoad
{
[super viewDidLoad];
//this makes a zombie/person
UIImageView *zombieView =[[UIImageView alloc] initWithFrame:CGRectMake(135 , 300, 50, 75)];
UIImage *zombie=[UIImage imageNamed:#"free-vector-stick-figure-clip-art_105575_Stick_Figure_clip_art_hight.png"];
[zombieView setImage:zombie];
[self.view addSubview:zombieView];
[self.view insertSubview:zombieView belowSubview:_Railing];
[zombieView setUserInteractionEnabled:TRUE];
// double tap gesture recognizer
UITapGestureRecognizer *touch2 = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapped2:)];
[touch2 setDelegate: self];
[touch2 setNumberOfTapsRequired: 2];
[zombieView addGestureRecognizer:touch2];
//tap gesture recognizer
UITapGestureRecognizer *touch = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapped:)];
[touch setDelegate:self];
[touch setNumberOfTapsRequired: 1];
[zombieView addGestureRecognizer:touch];
//This makes the Person move down until he is behind the railing
[UIView animateWithDuration:8.5
delay:0.0
options:UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionCurveLinear
animations:^{
CGAffineTransform transform= CGAffineTransformMakeTranslation(0,-200);
zombieView.transform = transform;
}
completion:nil];
};
-(void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
This is my .h file:
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#interface AbcViewController : UIViewController <UIGestureRecognizerDelegate>
#property (strong, nonatomic) IBOutlet UIImageView *Railing;
//#property (strong, nonatomic) IBOutlet UIImageView *Person;
#property (strong, nonatomic) IBOutlet UIImageView *zombieView;
#property (strong, nonatomic) IBOutlet UIImage *zombie;
-(void) tapped:(UITapGestureRecognizer *)recognizer;
-(void) tapped2:(UITapGestureRecognizer *)recognizer;
#end
Every time I click it in mid-animation I get an error but when it's complete it works fine. I am fairly new to this so I'm sure it's simple, it always is. But, thank you for your patience and answers!
The object during the animation is not where you see it. It has already moved to its final position. Animation is an illusion: the "presentation layer" is animated, but the underlying "model layer" (the real object) stands still and has already moved when the animation starts. The model layer is the one inside a view so it is the only one that can be tapped.
Tapping an object while it is being animated is therefore a very tricky problem. I discuss it here:
http://www.apeth.com/iOSBook/ch18.html#_hit_testing_during_animation
Perhaps that discussion will give you some ideas. But no matter what, this is not going to be easy.
(Consider that perhaps you should not be using view animation for this kind of game. Sprite Kit was invented for just this sort of thing.)

How to hide the keyboard when touching screen (search bar)

The keyboard hides when I click search or when I click on cancel.
But I want also that the keyboard hides when I click somewhere on the screen.
I found several tutorials for the textfield, but we are using the search bar.
Can someone tell me how to do this?
Thanks.
Try This
in your .h file add UISearchBar
#property (strong, nonatomic) IBOutlet UISearchBar *searchBar;
in your .m file
- (void)viewDidLoad
{
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]
initWithTarget:self
action:#selector(dismissKeyboard)];
[self.view addGestureRecognizer:tap];
}
- (void) dismissKeyboard
{
// add self
[self.searchBar resignFirstResponder];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[yourTextField1 resignFirstResponder];
[yourTextField2 resignFirstResponder];
[yourTextField3 resignFirstResponder];
[yourSearchBar resignFirstResponder];
//etc
}
But probably you need to check where are you touching at since you don't want to hide the keyboard if you're touching on a text input or search box.
Try to use this one
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self.view endEditing:YES];
}
You could add a UITapGestureRecognizer to dismiss your keyboard.
- (void)viewDidLoad {
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]
initWithTarget:self
action:#selector(dismissKeyboard)];
[self.view addGestureRecognizer:tap];
}
- (void) dismissKeyboard {
[self.view endEditing:YES];
}

Resources