iPhone Keyboard Covers UITextField
Solution 1
The usual solution is to slide the field (and everything above it) up with an animation, and then back down when you are done. You may need to put the text field and some of the other items into another view and slide the view as a unit. (I call these things "plates" as in "tectonic plates", but that's just me). But here is the general idea if you don't need to get fancy.
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
[self animateTextField: textField up: YES];
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
[self animateTextField: textField up: NO];
}
- (void) animateTextField: (UITextField*) textField up: (BOOL) up
{
const int movementDistance = 80; // tweak as needed
const float movementDuration = 0.3f; // tweak as needed
int movement = (up ? -movementDistance : movementDistance);
[UIView beginAnimations: @"anim" context: nil];
[UIView setAnimationBeginsFromCurrentState: YES];
[UIView setAnimationDuration: movementDuration];
self.view.frame = CGRectOffset(self.view.frame, 0, movement);
[UIView commitAnimations];
}
Solution 2
This worked wonders for me sliding uitextfields
In particular it has the benefit of calculating the slide animation distance depending on the position of the text field.
Solution 3
IQKeyboardManager do this for you with NO LINE OF CODE, only need to drag and drop related source file to project. IQKeyboardManager also support Device Orientation, Automatic UIToolbar Management, keyboardDistanceFromTextField and much more than you think.
Here is the Control Flow Chart:
Step1:- Added global notifications of UITextField
, UITextView
, and UIKeyboard
in a singleton class. I called it IQKeyboardManager.
Step2:- If found UIKeyboardWillShowNotification
, UITextFieldTextDidBeginEditingNotification
or UITextViewTextDidBeginEditingNotification
notifications, then try to get topMostViewController
instance from the UIWindow.rootViewController
hierarchy. In order to properly uncover UITextField
/UITextView
on it, topMostViewController.view
's frame needs to be adjusted.
Step3:- Calculated expected move distance of topMostViewController.view
with respect to first responded UITextField
/UITextView
.
Step4:- Moved topMostViewController.view.frame
up/down according to the expected move distance.
Step5:- If found UIKeyboardWillHideNotification
, UITextFieldTextDidEndEditingNotification
or UITextViewTextDidEndEditingNotification
notification, then again try to get topMostViewController
instance from the UIWindow.rootViewController
hierarchy.
Step6:- Calculated disturbed distance of topMostViewController.view
which needs to be restored to it's original position.
Step7:- Restored topMostViewController.view.frame
down according to the disturbed distance.
Step8:- Instantiated singleton IQKeyboardManager class instance on app load, so every UITextField
/UITextView
in the app will adjust automatically according to the expected move distance.
That's all
Solution 4
To expand on Amagrammer answer, here is a sample class:
LoginViewController.h
@interface LoginViewController : UIViewController <UITextFieldDelegate> {
}
@property (nonatomic, retain) IBOutlet UITextField *emailTextField;
@property (nonatomic, retain) IBOutlet UITextField *passwordTextField;
Notice we are implementing the "UITextFieldDelegate"
LoginViewController.m
@implementation LoginViewController
@synthesize emailTextField=_emailTextField;
@synthesize passwordTextField=_passwordTextField;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
//Register to receive an update when the app goes into the backround
//It will call our "appEnteredBackground method
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(appEnteredBackground)
name:UIApplicationDidEnterBackgroundNotification
object:nil];
}
return self;
}
- (void) animateTextField: (UITextField*) textField up: (BOOL) up
{
const int movementDistance = 80; // tweak as needed
const float movementDuration = 0.3f; // tweak as needed
int movement = (up ? -movementDistance : movementDistance);
[UIView beginAnimations: @"anim" context: nil];
[UIView setAnimationBeginsFromCurrentState: YES];
[UIView setAnimationDuration: movementDuration];
self.view.frame = CGRectOffset(self.view.frame, 0, movement);
[UIView commitAnimations];
}
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
[self animateTextField: textField up: YES];
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
[self animateTextField: textField up: NO];
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
//This is called when the app goes into the background.
//We must reset the responder because animations will not be saved
- (void)appEnteredBackground{
[self.emailTextField resignFirstResponder];
[self.passwordTextField resignFirstResponder];
}
Solution 5
I have face the same issue in UITableView
textField cells. I solve this issue by implementing following method to listen the keyboard notification.
Observer for the notifications here:
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(keyboardWasShown:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(keyboardWillBeHidden:) name:UIKeyboardWillHideNotification object:nil];
Handle those notification by using below function:
(void)keyboardWasShown:(NSNotification*)aNotification
(void)keyboardWillBeHidden:(NSNotification*)aNotification
Cruinh
Thinking in code since '98. (Swift, Objective-C, Java, C++, Delphi, and more scripting languages than I can remember)
Updated on July 08, 2022Comments
-
Cruinh almost 2 years
I have an app where, in Interface Builder, I set up a
UIView
that has a text field near the bottom of the view. When I run the app and try to enter text into that field, the keyboard slides up overtop of the field so I can't see what I'm typing until I hide the keyboard again.Has anyone else run into this problem and found a good way to solve it without either making the parent view scrollable or moving the text field farther up the screen?
-
jlstrecker over 12 yearsThis is great. You don't have to pick some 'movement distance' constant for each text field -- it's calculated for you.
-
Marchy over 12 yearsBest solution by far. Phenomenal mechanism!
-
Ben Coffman about 12 yearsLove it that you didn't post a link to code, but the code itself.
-
James almost 12 yearsGreat bit of code. Didn't have to edit it for it to work or anything. Thanks~
-
conecon over 11 yearsIt is useful to cover all of screen as below: const int movementDistance = textField.frame.origin.y / 2; // tweak as needed
-
lolol over 11 yearsNo, it's not. If the user taps the first textfield it will get above the visible area.
-
xu huanze over 11 yearsthis does not work very well when user switches the keyboard from normal keyboard to an international keyboard, which has a different height.
-
Mathieu over 11 yearsI have to mention that "If your are writing an application for iOS 4 or later, you should use the block-based methods for animating your content instead." Referenced from : developer.apple.com/library/ios/#documentation/windowsviews/…
-
Khon Lieu over 11 yearsWorks great on the iPad too. I just updated PORTRAIT_KEYBOARD_HEIGHT = 264 and LANDSCAPE_KEYBOARD_HEIGHT = 352. Great link. Thanks.
-
Jared Sealey about 11 yearsIf you have multiple text fields and only want 1 to animate, add a tag in the xib file and have an if statement before the animate statements if(textField.tag == 1) [self animateTextField: textField up: YES];
-
JimmyJammed about 11 yearsThe above link just made my day! So simple to implement, works flawlessly so far!
-
john doe almost 11 yearsThis is beautiful!! You are awesome!
-
Sandy almost 11 yearsWorks great, just copy paste almost. Good explaination as well.
-
Ken W almost 11 yearsThis works perfectly (in terms of the animation values) for an iPhone 4S on iOS 6.1.3 (Retina 3.5" screen)
-
Security Hound almost 11 years@NANNAV - Please provide comments when you make suggestions to modify an answer.
-
Adil Soomro almost 11 years+1 for mentioning
UIApplicationDidEnterBackgroundNotification
, else it'll move more downward if one press Home button and come again into the app, causing it to ugly and buggy. -
miek over 10 yearsThe link is broken. Please consider including an independent solution in the future!
-
dreampowder over 10 yearsStill works perfectly with iOS 7.0.3, thanks for the simple and elegant solution.
-
Renexandro about 10 yearsThis is best the explanation out there about this topic. Other tutorials use Table Views, Scroll Views, etc. This actually works without getting into any other complexities, plain and simple. Thanks for sharing this source.
-
Hless about 10 yearsStill works on iOS 7.1 (iPad). The offset doesn't stick after rotating though, so you'd have to set it again in the 'didRotateFromInterfaceOrientation' method.
-
Mohd Iftekhar Qurashi about 10 yearsThis official solution is now wrapped in a control see here:- stackoverflow.com/a/17707094/1582217
-
Raj Pawan Gumdal almost 10 yearsIdea is good, but 'contentInset' property does not help here, coz contentInset will just provide you the padding effect: stackoverflow.com/a/10049782/260665
-
learner almost 10 yearsThe accepted answer wasn't working for me. But this one does.
-
unom over 9 yearsFound this and it discusses the same issue developer.apple.com/Library/ios/documentation/StringsTextFonts/…
-
Mohd Iftekhar Qurashi over 9 years@Raj, That may be the case which I can look on IQKeyboardManager, but still no one open any issues on the official IQKeyboardManager github repository regarding the contentInset property issue, so I assume it's working.
-
Mohd Iftekhar Qurashi almost 9 years@ZaEeMZaFaR IQKeyboardManager is also optimised for iPad. Can you please open an issue on library github repo and upload a demo project demonstrating the issue with iPad?
-
ZaEeM ZaFaR almost 9 yearsThanks for reply. I will do that if issue persists, before you comment I was thinking that IQKeyboardManager is not for universal device.
-
ZaEeM ZaFaR almost 9 yearsBy Investigating more, its working fine with iPad on simulator but not on actual iPad device. Working perfectly fine on iPhone as well (Device + Simulator). What could be the issue ?
-
Mohd Iftekhar Qurashi almost 9 yearsAs I previously said, you should raise an issue on github repo with demo project with your iOS and device version details, so we can look into the issue.
-
ZaEeM ZaFaR over 8 yearsThanks for the help, I was looking to post a POC where I found that 'split keyboard' was turned ON in iOS system preferences. And that was issue which stops the controller to listen keyboard notification. Worked like charm when I turned off the split keyboard.
-
Elvis Oliveira over 8 yearsThe accepted answer work only when you set the delegate of every UITextField. This framework works in anyone UITextField, I think this is the best solution for now.