When the view is dismissed the keyboard slides after the view.
I created a video to demonstrate the problem.
http://www.youtube.com/watch?v=ISFL5G17coU'
Does anyone know why this happens
In -(void) viewWillDisappear: make sure you call resignFirstResponder on your textfield.
- (void)viewWillDisappear:(BOOL)animated
{
[textField resignFirstResponder];
}
Related
I have a app I'm making that has 2 text fields and buttons below it. When the user starts to type, the keyboard comes up and covers the buttons. Is there a way to make the keyboard go away?
There are two ways to do so
// this one line will dismiss the keyboard from anywhere in your code
[self.view endEditing:YES];
or
with the delegate of textfield (you should declare it in your .h file first)
#interface someController : UIViewController <UITextFieldDelegate>
and the in .m
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
// next line will dismiss the keyboard
[textField resignFirstResponder];
return YES;
}
Check UITextField documentation:
To dismiss the keyboard, send the resignFirstResponder message to the text field that is currently the first responder. Doing so causes the text field object to end the current editing session (with the delegate object’s consent) and hide the keyboard.
In other words, just send resignFirstResponder to an active text field object.
I use this:
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
[self.alertView dismissWithClickedButtonIndex:self.alertView.firstOtherButtonIndex animated:YES];
return YES;
}
In the view controller after setting the text field delegate to self.
I got one UITextField on my Modal view controller.
When "Done" key is clicked, i want to dismiss the modal view.
i don't know where should i add below code to dismiss modal view.
Thanks in advance for any help.
[self.parentViewController dismissModalViewControllerAnimated:YES];
add it in UITextFieldDelegate method
-(BOOL)textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];
[self.parentViewController dismissModalViewControllerAnimated:YES];
return YES;
}
When my iPhone app starts up, the main screen has a keyboard. Currently the keyboard rises as soon as the rest of the interface is displayed and this is visually distracting.
How can I have the view display with the keyboard already up?
Since I am already faking some of the rest of the screen during startup so that the user sees what they last were doing, I thought that I could fake the keyboard as well. But if the motion is there when the real keyboard appears, I've lost the effect. The keyboard is, as far as I know, on a separate window, not just a separate view, so I can't overlay it with my own image.
Is there a way to either overlay the keyboard withy my own image as it appears, or not show the keyboard until it is all the way up, or make its animation instant?
My original answer has the keyboard animate in along with the view controller if it's an animated transition (i.e. pushing a view controller or presenting a modal controller with animated: YES). However, the keyboard still animates in if the new view controller is displayed without an animated transition, so it doesn't solve your problem.
Here's another approach that worked in my testing. Try disabling animations while you're displaying the controller + keyboard.
[UIWindow beginAnimations: nil context: NULL];
[UIWindow setAnimationsEnabled: NO];
RestoredController *controller = [[[RestoredController alloc] init] autorelease];
[self.navigationController pushViewController: controller animated: NO];
[UIWindow commitAnimations];
You'll still need to make field the first responder in viewWillAppear: or viewDidAppear:
In viewWillAppear:, ensure the view is loaded (via self.view) and set the first responder to the correct field. This will display the keyboard fully when the view is actually displayed instead of animating it in.
For example:
- (void) viewWillAppear: (BOOL) animated {
[super viewWillAppear:animated];
NSString *storedID = [[NSUserDefaults standardUserDefaults] stringForKey:#"storedID"];
if ([storedID length] > 0) {
idField.text = storedEmail;
[passwordField becomeFirstResponder];
} else {
[idField becomeFirstResponder];
}
}
Not an answer, but here is some code.
I set the font for my UITextView in viewDidLoad. The view is instantiated by the NIB and the outlet is correctly set up.
-(void)viewWillAppear:(BOOL)animated;
{
[super viewWillAppear:animated];
// Start with the text from the currently edited message
NSString *startString = self.messageManager.editingMessage.text;
// start string processing omitted
self.editingMessageEditingView.text = startString;
if([self showingMessageList]) {
[self.editingMessageEditingView resignFirstResponder];
} else {
#if DEFAULT_SCREEN==1
[[self.tools.items objectAtIndex:kPVToolBarItemDelete] setEnabled:NO];
[[self.tools.items objectAtIndex:kPVToolBarItemSendLater] setEnabled:NO];
#else
[self.editingMessageEditingView becomeFirstResponder];
#endif
}
I'm using an tableView with custom cells. When I want to display another view using the pushViewController function of the navigationController I loop through the textfields and call resignFirstResponder on them. But resignFirstResponder does only work when the textfields are being displayed so I scroll first to the top of the page. This is the code:
NSIndexPath *topIndexPath;
topIndexPath = [[NSIndexPath indexPathWithIndex:0] indexPathByAddingIndex:0];
[self.tableView scrollToRowAtIndexPath:topIndexPath atScrollPosition:UITableViewScrollPositionTop animated:NO];
[[self textFieldForRow:0] resignFirstResponder];
[[self textFieldForRow:1] resignFirstResponder];
[[self textFieldForRow:2] resignFirstResponder];
[[self textFieldForRow:3] resignFirstResponder];
This works, but after this my tableView has some weird problem with its origin. I tried to set it's superviews origin to 0, but that doesn't help.
Here is a screenshot of the problem: link
As you can see, my tableview is too large and the scrollbar is stuck in the middle of the view when reaching the bottom.
Sorry for my english, I hope that you can understand me,
Thanks in advance!
Hans
It was actually quite simple. Just put your resignFirstResponder in -viewWillDisappear
edit: this is better and less hacky, I added this to my class, and it worked:
edit 2: seems that your app will be rejected when using the previous code. Here is a updated public api version:
- (void)viewWillDisappear:(BOOL)animated
{
[self.view findAndResignFirstResponder];
}
And:
#implementation UIView (FindAndResignFirstResponder)
- (BOOL)findAndResignFirstResponder
{
if (self.isFirstResponder) {
[self resignFirstResponder];
return YES;
}
for (UIView *subView in self.subviews) {
if ([subView findAndResignFirstResponder])
return YES;
}
return NO;
}
#end
(source: Get the current first responder without using a private API)
I would fix your other problem. I imagine when you say you can't call "resignFirstResponder" when the other textFields are on screen, you mean that there is a crash?
If so, it is because of screen cells don't exist and therefore the textfields are gone as well. They are recycled (so they can be dequeued for new cells).
The easy solution is to only call resignFirstResponder only on textFields that ARE on screen.
What you are doing now seems a little hacky.
I am trying to recreate something similar to the popup keyboard used in safari.
I am able to visually reproduce it by placeing a toolbar over my view and the appropriate buttons, however i cant figure out any way to dismiss the keyboard once the user has touched the done button.
There is a couple of things you need to remember. The number #1 part developers forget to set is the delegate of the textField.
If you are using the Interface Builder, you must remember that you need to set the delegate of the textField to the file Owner.
If you are not using Interface Builder then make sure you set the delegate of the textfield to self. I also include the returnType. For Example if the textField was called gameField:
gameField.delegate = self;
gameField.returnKeyType = UIReturnKeyDone;
You must also implement the UITextFieldDelegate for your ViewController.
#interface YourViewController : UIViewController <UITextFieldDelegate>
Finally you need to use the textFieldShouldReturn method and call [textField resignFirstResponder]
-(BOOL) textFieldShouldReturn:(UITextField*) textField {
[textField resignFirstResponder];
return YES;
}
All your textFields will use this same method so you only need to have this setup once. As long as the delegate is set for the textField, the UITextFieldDelegate is implemented for the interface, you add the textFieldShouldReturn method and call the
resignFirstResponder your set.
Have you tried:
[viewReceivingKeys resignFirstResponder];
where viewReceivingKeys is the UIView that is receiving the text input?
If your building your own views in Interface Builder, set your view controller to be delegate for the text field and implement textFieldShouldReturn: from UITextFieldDelegate in your views controller.
- (BOOL)textFieldShouldReturn:(UITextField *)theTextField
{
NSLog(#"%# textFieldShouldReturn", [self class]);
[theTextField resignFirstResponder];
// do stuff with the text
NSLog(#"text = %#", [theTextField text]);
return YES;
}
UITextFieldDelegate textFieldShouldReturn: in the iphone cocoa docs
If you're talking about dismissing the keyboard from a UITextField rather than a UITextView. Your question isn't that clear? If you are then ensure your class is marked as a UITextFieldDelegate in the interface file,
#interface MyController: UIViewController <UITextFieldDelegate> {
UITextField *activeTextField;
// ...remainder of code not show ...
}
and then you should implement the two delegate methods as below,
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
activeTextField = textField;!
return YES;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
activeTextField = nil;
[textField resignFirstResponder];
return YES;
}
However if you're using a UITextView then things are a bit more complicated. The UITextViewDelegate protocol lacks the equivalent to the textFieldShouldReturn: method, presumably since we shouldn’t expect the Return key to be a signal that the user wishes to stop editing the text in a multi-line text entry dialog (after all, the user may want to insert line breaks by pressing Return).
However, there are several ways around the inability of the UITextView to resign as first responder using the keyboard. The usual method is to place a Done button in the navigation bar when the UITextView presents the pop-up keyboard. When tapped, this button asks the text view to resign as first responder, which will then dismiss the keyboard.
However, depending on how you’ve planned out your interface, you might want the UITextView to resign when the user taps outside the UITextView itself. To do this, you’d subclass UIView to accept touches, and then instruct the text view to resign when the user taps outside the view itself.
Create a new class,
#import <UIKit/UIKit.h>
#interface CustomView : UIView {
IBOutlet UITextView *textView;
}
#end
Then, in the implementation, implement the touchesEnded:withEvent: method and ask the UITextView to resign as first responder.
#import "CustomView.h"
#implementation CustomView
- (id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
// Initialization code
}
return self;
}
- (void) awakeFromNib {
self.multipleTouchEnabled = YES;
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(#"touches began count %d, %#", [touches count], touches);
[textView resignFirstResponder];
[self.nextResponder touchesEnded:touches withEvent:event];
}
#end
Once you’ve added the class, you need to save all your changes, then go into Interface Builder and click on your view. Open the Identity inspector in the Utility pabel and change the type of the view in your nib file to be your CustomView rather than the default UIView class. Then in the Connections Inspector, drag the textView outlet to the UITextView. After doing so, and once you rebuild your application, touches outside the active UI elements will now dismiss the keyboard. Note however that if the UIView you are subclassing is “behind” other UI elements, these elements will intercept the touches before they reach the UIView layer. So while this solution is elegant, it can be used in only some situations. In many cases, you’ll have to resort to the brute force method of adding a Done button to the navigation bar to dismiss the keyboard.
use a navigation controller and pop the view when done?
for example, I use code like this to slide an about box in:
[[self navigationController] presentModalViewController:modalViewController animated:YES];
and then when the button in that about box is clicked, I use this to get rid of it:
[self.navigationController dismissModalViewControllerAnimated:YES];
In my case the about box occupies the whole screen, but I don't think it would have to for this to work.
edit: I think I may have misunderstood your question. Something along the lines of my code would be if you are faking the whole keyboard view yourself. I think that resign first responder is the right way to do it if it is the normal keyboard with your toolbar added on top.