Next, I learned that to close the virtual keyboard when clicked anywhere on the screen, we must implement the touchesBegan method together with the name of the variables, which bind with the existing view UITextFields.
If we have about 10 text fields, I learned that I have to repeat this command 10 times:
[MyFristTextField resignFristResponder];
[MySecondTextField resignFristResponder];
...
[MyTenTextField resignFristResponder];
Is not there any easier way to do this, for example, call UITextFields all at once?
Keep a reference to the current UITextField in a property. Then send resignFirstResponder to that UITextField when you want the keyboard to dismiss.
You do not need to implement 10 times.
What you can do is just use:
[self.view endEditing:YES];
At the method that you are calling from the tap Gesturrecgnizer.
For example:
self.tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(closeAllKeyBourds)];
[self.view addGestureRecognizer:self.tap];
Your code should look something like:
-(void)textFieldDidBeginEditing:(UITextField *)textField
{
self.tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(closeAllKeyBourds)];
[self.view addGestureRecognizer:self.tap];
}
{
[self.view endEditing:YES];
[self.view removeGestureRecognizer:self.tap];
self.tap = nil;
}
Tip:
If you are using 10 TextField, you better place then on a scroll view, so you can lift the scroll view up when using a lower text Field.
Hope this helps!
Edit
You have to keep an instance variable, or a property of the TapGestureRecognizer, so you can refer to it when the tap occurred.
So you keep a property at your #inerface, it should look like so:
//At your interface:
#interface LogInpageViewController : UIViewController
//Keep a property
#property (nonatomic,strong) UITapGestureRecognizer *tap;
Related
In Instagram in the header view we could see there is the profile image and the username right , so I am thinking how is this possible because the username is a UILabel how when it's clicked on it sent you the user homepage . Any idea ?
You can add a UITapGestureRecognizer to the label to make it clickable.
UITapGestureRecognizer* gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tappedOnLabel:)];
[label setUserInteractionEnabled:YES];
[label addGestureRecognizer:gesture];
-(void)tappedOnLabel:(UIGestureRecognizer*)gestureRecognizer
{
// Perform your action
}
Yes it can, check "User Interaction Enabled" in the Attribute Inspector, and add an Action method with it. Make sure you connect the action method to the label
EDIT-
I am showing this in code as i cant post screenshots.
Create a Label #property(nonatomic, weak) IBOutlet UILabel *myLabel;
Connect the Label in Storyboard.
Create a method, that you want to do when user Taps the label.
-(void)showHello{
NSLog(#"Hello World");
}
Now declare a
UITapGestureRecognizer *tap;
I used tapGesture as I want the action to run when I TAP the label.Declare this Gesture as an Instance Variable
in viewDidLoad alloc and init the gesture and add it to the Label
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.myLabel.userInteractionEnabled = YES;
tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(showHello)];
[self.myLabel addGestureRecognizer:tap];
}
Yup that should do it
Is it possible to dismiss the keyboard when you have MULTIPLE UITextFields ? If so how ?
As a side note, do I have to dismiss the keyboard for Each and Every field or can it be done globally ? Oh and it would be super cool if I don't have to touch the DONE button, I'd ideally like a solution that where the user touches anything BUT the field in question and the keyboard automagically disappears...
Oh and if you'd be so kind step by step instructions.
I should have added that I have a method already to resign the keyboard....
However, it only runs when my form is submitted! (see method below)
My question is how to the keyboard to hide/dismiss without having to jump thru so many damned hoops! You'd figure after 6 years, a mature operating system would have a way to GLOBALLY hide the keyboard....NOT!
Ok, enough whining....
- (void)hideKeyboard {
[self.dancePlace resignFirstResponder];
[self.danceGate resignFirstResponder];
[self.danceTerminal resignFirstResponder];
[self.danceText resignFirstResponder];
[self.danceDate resignFirstResponder];
[self.danceStyle resignFirstResponder];
[self.danceTimeOut resignFirstResponder];
}
And this is called when my button is submitted....
- (IBAction)addListingPressed:(id)sender {
// NSLog(#"BUTTON PRESSED");
[self hideKeyboard];
[self valuesAdded];
}
My question, assuming anyone can answer this...and I suspect not, is there a way to globally hide the keyboard if the following conditions are MET: 1.) the user taps OUT of any one of the existing fields, 2.) presses anywhere else on the screen. 3.) Is no more than a line or two in the existing viewcontroller.m file. 4.) I don't have to add a confusing button on the viewcontroller. (any time I have to add outlets, the damned thing is crashing on me...and then nastiness happens, and really...remember I am JUST a beginner, and its very confusing to read that I have to place this here and that there...oy. Simple folks, simple. I'm not looking for elegant solution, just so that it works.
I have a super class that all my view controllers inherit from. In that class I have this code.
MySuperViewController.h
#import <UIKit/UIKit.h>
#interface MySuperViewController : UIViewController
#property(strong, nonatomic) UITapGestureRecognizer *backgroundTapGestureRecognizer;
#end
MySuperViewController.m
- (void)viewDidLoad{
//add a tap gesture recognizer to capture all tap events
//this will include tap events when a user clicks off of a textfield
self.backgroundTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(onBackgroundTap:)];
self.backgroundTapGestureRecognizer.numberOfTapsRequired = 1;
self.backgroundTapGestureRecognizer.cancelsTouchesInView = NO;
[self.view addGestureRecognizer:self.backgroundTapGestureRecognizer];
}
- (void)onBackgroundTap:(id)sender{
//when the tap gesture recognizer gets an event, it calls endEditing on the view controller's view
//this should dismiss the keyboard
[[self view] endEditing:YES];
}
I have the UITapGestureRecognizer as a public property, so I can override it if I need to.
subclass
MyViewController.h
#import <UIKit/UIKit.h>
#import "MySuperViewController.h"
#interface MyViewController : MySuperViewController<UIGestureRecognizerDelegate>
#end
MyViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
//You don't always want the keyboard to be dismissed, so you tie into the gesture recognizer's delegate method
//By doing this, you can stop the endEditing call from being made
[self.backgroundTapGestureRecognizer setDelegate:self];
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
//touch.view is the view that recieved the touch
//if this view is another textfield or maybe a button, you can return NO and the endEditing call won't be made
if (touch.view == self.myViewThatShouldNotBeBlocked) {
return NO;
}
//if you want the gesture recognizer to accept the event, return yest
return YES;
}
I uploaded an example project to github.
https://github.com/JeffRegan/KeyboardBeGone
RDVKeyboardAvoiding is a scroll view with a tap gesture recognizer, designed for multiple textViews/textFields. It keeps track of the active view and removes a lot of boilerplate code.
tap anywhere outside the textField .. it will hide it..
[self.view endEditing:YES];
There are couple of other ways to do it.
[myEditField resignFirstResponder];
[myEditField endEditing];
[parentView endEditing];
If you dont wont to do so many things and simply want to dismiss keyboard than give iboutlet to each of your text filed to following method..
-(IBAction)hidekeyboard:(id)sender
{
[sender resignFirstResponder];
}
Yes, you only have to dismiss it for the one that is currently being edited.
In order to know which one is being edited, you can check the -(BOOL)isFirstResponder property, which will return YES if it is the first responder (the one being edited) or NO if it is not. Once you know which one is the first responder you can call -(void)resignFirstResponder on that one to get rid of the keyboard.
For example, if you have a method called -(void)aMethod that you want to dismiss the current view controller and you have an array of textViews called textArray, you could do a little loop such as:
-(void)aMethod {
for (UITextField *text in self.textArray) {
if ([text isFirstResponder]) [text resignFirstResponder];
return;
}
}
This way, you can have a variable number of textFields and it will still work.
If you only have one or two textFields and you do not want to create an Array object, you could do (assuming the fields are named text1 and text2:
-(void)aMethod {
if ([text1 isFirstResponder]) [text1 resignFirstResponder];
else if([text2 isFirstResponder]) [text2 resignFirstResponder];
}
Also, to make things easier for the future you could create a category method for UIView (which is what I do) to get the current first responder if it exists as a subview of that view:
#implementation UIView (GetFirstResponder)
- (UIView *)getFirstResponder {
if ([self isFirstResponder]) return self;
else {
for (UIView *subview in self.subviews) {
UIView *firstResponder = [subview getFirstResponder];
if (firstResponder) return firstResponder;
}
}
return nil;
}
You can put this method on the top of any file that you want to call it from, or create a separate file for it and import it.
Once you have this method, you can call:
- (void)aMethod {
UIView *view = [self.view getFirstResponder];
if (view) [view resignFirstResponder];
}
[superview endEditing:YES]; // superview can be the view controller's view property.
I have a simple program that does a calculation on a button press. The result is placed into a label using the following code:
//converts the float to 2 descimal places then converts it to a string
NSString *stringRectResult=[[NSString alloc]
initWithFormat:#"%1.2f",floatCalcResult];
//displays the string result in the label
resultLabel.text=stringRectResult;
It works perfectly, however, I added in code to hide the decimal keyboard when the user touches off the keyboard. That works, but when I added this code the button to update the label no longer worked. Can anyone help? The code to hide the keyboard is below. The app works when I comment it out but does not when it is active
In viewDidLoad:
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc]
initWithTarget:self action:#selector(tap:)];
[self.view addGestureRecognizer:tapRecognizer];
Tap selector...
-(void)tap:(UIGestureRecognizer *)gr
{
[self.view endEditing:YES];
}
Thanks for any and all help.
The problem is that by intercepting all of the user's taps (in order to hide the keyboard), you're preventing any other user interface elements from being tapped. I would urge you to rethink your design; it's not usually necessary to have an explicit facility to hide the keyboard.
If you do want to keep this design, you can implement the gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer: method in your class:
- (void) viewDidLoad
{
// ...
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc]
initWithTarget:self action:#selector(tap:)];
tapRecognizer.delegate = self;
[self.view addGestureRecognizer:tapRecognizer];
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
Two things to keep in mind:
You need to mark your view controller as conforming to the UIGestureRecognizerDelegate protocol.
If you later add a second gesture recognizer to the view, you'll need to add a check inside the second method to treat the second recognizer differently.
I created a form and the keypad (Numeric only) appears when entering data like your age.
I want the keyboard to disappear when the user taps the background and I want to add a "Done" button in the empty slot under the 7 (next to the zero). (im using the Number Pad keyboard)
I found this example but I have a few questions.
In
-(void)viewDidLoad
{
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(dismissKeyboard)]; [self.view addGestureRecognizer:tap];
}
-(void)dismissKeyboard
{
[aTextField resignFirstResponder];
[aTextField1 resignFirstResponder];
[aTextField2 resignFirstResponder];
[aTextField3 resignFirstResponder];
}
If I have more than 1 text field in my form.
Will I need to write every textfield in the dismissKeyboard method?
Easy way to do this is to use the method provided in UIView
- (BOOL) endEditing:(BOOL)force;
This method looks at the current view and its subview hierarchy for the text field that is currently the first responder. If it finds one, it asks that text field to resign as first responder. If the force parameter is set to YES, the text field is never even asked; it is forced to resign.
So just do this:
-(void)dismissKeyboard {
[self.view endEditing:YES];
}
and it will support any more text fields you add on your page (under that UIView of course)
You should only send dismissKeyboard to that textField that you are currently editing.
In your code you have got memory leak. Better use this one:
-(void)viewDidLoad
{
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(dismissKeyboard)];
[self.view addGestureRecognizer:tap];
[tap release];
}
To check if UITextField is currently in edit mode you can check its property:
A Boolean value indicating whether the text field is currently in edit mode. (read-only)
#property(nonatomic, readonly, getter=isEditing) BOOL editing
For example, you have 3 text fields then dismissKeyboard will look something like this:
-(void)dismissKeyboard
{
UITextField *activeTextField = nil;
if ([textField1 isEditing]) activeTextField = textField1;
else if ([textField2 isEditing]) activeTextField = textField2;
else if ([textField3 isEditing]) activeTextField = textField3;
if (activeTextField) [activeTextField resignFirstResponder];
}
I use the same functionality in many of my apps. Rather than using the GestureRecognizer, I set my view up as a UIControl, rather than a UIView. You can still do the things you'd do with a UIView, but you can also assign IBActions to be performed when interacting with the view.
Here's how to do it:
In Interface Builder, select your view. Then, assign its class to UIControl. (It's probably set up as UIView currently.
In your ViewController for that view, write an IBAction method to detect backgroundTaps. Mine looks like this:
- (IBAction)backgroundTap:(id)sender
{
if ([textField1 isEditing]) {
[textField1 resignFirstResponder];
} else if ([textField2 isEditing]) {
[textField2 resignFirstResponder];
}
}
Finally, in Interface Builder, connect the IBAction you created to the UIControl.
Read this article, it may help you
Writing iOS 4 Code to Hide the iPhone Keyboard (Xcode 4)
Here i give common text field object. and asign reference to it in "textFieldShouldBeginEditing" method. that will common for all text field..
In this case, you need to dismiss one text field that will hide keyboard..
declare textfield object in .h file.
#interface RootViewController : UIViewController
{
IBOutlet UITextField* txt_common;
}
IN .m file
- (void)viewDidLoad {
[super viewDidLoad];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(dismissKeyboard)];
[self.view addGestureRecognizer:tap];
[tap release];
}
-(void)dismissKeyboard
{
NSLog(#"hi");
[txt_common resignFirstResponder];
}
#pragma mark TextField methods
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
NSLog(#"hi++++++++++++++++++");
txt_common=textField;
return YES;
}
I know this is really basic stuff but i need to understand whether my understanding of this is correct.
So what i want to do is this. I want an view with a label on which when double tapped flips and loads another view. On the second view i want a UIPickerView and above i have a button saying back. Both views will be of same size as an UIPickerView which is 320px x 216px.
What i am thinking of to do is create two UIViewclasses named labelView and pickerView. I would then create a viewController which on loadView loads labelView then when user double taps the labelView i get an event in labelView class which is sent to my viewController that then can unload loadView and load the pickerView.
Does this sound as the best way to do this ? Is there a simpler way ? I am also unsure how i route the event from the labelView class to the viewControllerclass.
I dont exactly know the most efficient way to do it(as i am also now to this language),but it is for sure that i have solved ur problem. I made a simple program for that.Three classes involved here in my eg are BaseViewController (which will show two views),LabelView and PickerView (according to ur requirement).
In LabelView.h
#protocol LabelViewDelegate
-(void)didTapTwiceLabelView;
#end
#interface LabelView : UIView {
id <LabelViewDelegate> delegate;
}
#property(nonatomic,retain)id <LabelViewDelegate> delegate;
-(void)didTouch;
#end
In LabelView.m
#synthesize delegate;
-(id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self)
{
UILabel* labl = [[UILabel alloc] initWithFrame:CGRectMake(10, 5, frame.size.width-20,20)];
labl.text = #"Some Text";
[self addSubview:labl];
[labl release]; labl = nil;
self.backgroundColor = [UIColor grayColor];
UITapGestureRecognizer* ges = [[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(didTouch)] autorelease];
ges.numberOfTapsRequired = 2;
[self addGestureRecognizer:ges];
}
return self;
}
-(void)didTouch
{
[delegate didTapTwiceLabelView];
}
//=============================================================
In Pickerview.h
#protocol PickerViewDelegate
-(void)didTapBackButton;
#end
#interface PickerView : UIView <UIPickerViewDelegate,UIPickerViewDataSource>{
id <PickerViewDelegate> delegate;
}
#property(nonatomic,retain)id <PickerViewDelegate> delegate;
#end
In Pickerview.m
#implementation PickerView
#synthesize delegate;
-(id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self)
{
UIPickerView* picker = [[UIPickerView alloc] initWithFrame:CGRectMake(0, 30, 320, 216)];
picker.delegate = self;
picker.dataSource = self;
[self addSubview:picker];
[picker release]; picker = nil;
self.frame = CGRectMake(frame.origin.x, frame.origin.y, 320, 250);
UIButton* btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[btn setFrame:CGRectMake(10, 1, 50, 27)];
[btn setTitle:#"Back" forState:UIControlStateNormal];
[btn addTarget:self action:#selector(backButton) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:btn];
}
return self;
}
-(void)backButton
{
[delegate didTapBackButton];
}
//====================================================================
in BaseViewController.h
#import "LabelView.h"
#import "PickerView.h"
#interface VarticalLabel : UIViewController<UITextFieldDelegate,PickerViewDelegate,LabelViewDelegate> {
PickerView* myPickerView;
LabelView* myLabelView;
}
#end
In BaseViewController.m
-(void)viewDidLoad
{
[super viewDidLoad];
myPickerView= [[PickerView alloc] initWithFrame:CGRectMake(0, 50, 320, 250)];
[self.view addSubview:myPickerView];
myPickerView.delegate = self;
myLabelView= [[LabelView alloc] initWithFrame:CGRectMake(0, 50, 320, 250)];
[self.view addSubview:myLabelView];
myLabelView.delegate = self;
myPickerView.hidden = YES;
}
#pragma mark PickerViewDelgate
-(void)didTapBackButton
{
myPickerView.hidden = YES;
myLabelView.hidden = NO;
}
#pragma mark LabelViewDelegate
-(void)didTapTwiceLabelView
{
myPickerView.hidden = NO;
myLabelView.hidden = YES;
}
To get events from a button to the view controller, just hook up the button's event, e.g. touch up inside, to a method in the view controller, using interface builder. (Double tapping is probably more complicated though.)
When you say 'flips', do you mean it actually shows an animation of flipping over a view to show a 'reverse' side? Like in the weather app when you hit the 'i' button? I'm assuming this is what you mean.
Perhaps check TheElements sample example on the iPhone Reference Library, it has an example of flip animation.
Btw, it's not strictly necessary to unload the loadView that is being 'hidden' when you flip -- it saves you having to construct it again when you flip back -- but it may be pertinent if you have memory use concerns, and/or the system warns you about memory being low.
Also, what do you mean by "create a UIView"? Do you mean subclass UIView, or just instantiate a UIVIew and add children view objects to it? The latter is the usual strategy. Don't subclass UIView just because you want to add some things to a UIView.
If you've got one screen of information that gives way to another screen of information, you'd normally make them separate view controllers. So in your case you'd have one view controller with the label and upon receiving the input you want, you'd switch to the view controller composed of the UIPickerView and the button.
Supposing you use Interface Builder, you would probably have a top level XIB (which the normal project templates will have provided) that defines the app delegate and contains a reference to the initial view controller in a separate XIB (also supplied). In the separate XIB you'd probably want to add another view controller by reference (so, put it in, give it the class name but indicate that its description is contained in another file) and in that view controller put in the picker view and the button.
The point of loadView, as separate from the normal class init, is to facilitate naming and linking to an instance in one XIB while having the layout defined in another. View controllers are alloced and inited when something that has a reference to them is alloced and inited. But the view is only loaded when it is going to be presented, and may be unloaded and reloaded while the app is running (though not while it is showing). Generally speaking, views will be loaded when needed and unnecessary views will be unloaded upon a low memory warning. That's all automatic, even if you don't put anything in the XIBs and just create a view programmatically within loadView or as a result of viewDidLoad.
I've made that all sound more complicated than your solution, but it's actually simpler because of the amount you can do in Interface Builder, once you're past the curve of learning it. It may actually be worth jumping straight to the Xcode 4 beta, as it shakes things up quite a lot in this area and sites have reported that a gold master was seeded at one point, so is likely to become the official thing very soon.
With respect to catching the double tap, the easiest thing is a UITapGestureRecognizer (see here). You'd do something like:
// create a tap gesture recogniser, tell it to send events to this instance
// of this class, and to send them via the 'handleGesture:' message, which
// we'll implement below...
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc]
initWithTarget:self action:#selector(handleGesture:)];
// we want double taps
tapGestureRecognizer.numberOfTapsRequired = 2;
// attach the gesture recogniser to the view we want to catch taps on
[labelView addGestureRecognizer:tapGestureRecognizer];
// we have an owning reference to the recogniser but have now given it to
// the label. We don't intend to talk to it again without being prompted,
// so should relinquish ownership
[tapGestureRecognizer release];
/* ... elsewhere ... */
// the method we've nominated to receive gesture events
- (void)handleGesture:(UIGestureRecognizer *)gestureRecognizer
{
// could check 'gestureRecognizer' against tapGestureRecognizer above if
// we set the same message for multiple recognisers
// just make sure we're getting this because the gesture occurred
if(gestureRecognizer.state == UIGestureRecognizerStateRecognized)
{
// do something to present the other view
}
}
Gesture recognisers are available as of iOS 3.2 (which was for iPad only; so iOS 4.0 on iPhone and iPod Touch).