How to move view up when iOS keyboard appears?
Solution 1
The following animation will move your view (viewForLogin in this case) 200 pixels above when the user starts typing. The view will animate back to original position when the textfield ends editing. Do not forget to set the delegates for the textfields.
Swift 3
func textFieldDidBeginEditing(_ textField: UITextField) {
UIView.animate(withDuration: 0.3, animations: {
self.view.frame = CGRect(x:self.view.frame.origin.x, y:self.view.frame.origin.y - 200, width:self.view.frame.size.width, height:self.view.frame.size.height);
})
}
func textFieldDidEndEditing(_ textField: UITextField) {
UIView.animate(withDuration: 0.3, animations: {
self.viewSupport.frame = CGRect(x:self.viewSupport.frame.origin.x, y:self.viewSupport.frame.origin.y + 200, width:self.viewSupport.frame.size.width, height:self.viewSupport.frame.size.height);
})
}
Objective-C
-(void)textFieldDidBeginEditing:(UITextField *)textField
{
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:.3];
[UIView setAnimationBeginsFromCurrentState:TRUE];
self.view.frame = CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y -200., self.view.frame.size.width, self.view.frame.size.height);
[UIView commitAnimations];
}
-(void)textFieldDidEndEditing:(UITextField *)textField
{
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:.3];
[UIView setAnimationBeginsFromCurrentState:TRUE];
self.view.frame = CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y +200., self.view.frame.size.width, self.view.frame.size.height);
[UIView commitAnimations];
}
Solution 2
SWIFT lovers Here you go. I have used this code with UIView, though. You should be able to make those adjustments for scrollview.
func addKeyboardNotifications() {
NotificationCenter.default.addObserver(self,
selector: #selector(keyboardWillShow(notification:)),
name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self,
selector: #selector(keyboardWillHide(notification:)),
name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
let duration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double
// if using constraints
// bottomViewBottomSpaceConstraint.constant = keyboardSize.height
self.view.frame.origin.y -= keyboardSize.height
UIView.animate(withDuration: duration) {
self.view.layoutIfNeeded()
}
}
}
func keyboardWillHide(notification: NSNotification) {
let duration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double
//if using constraint
// bottomViewBottomSpaceConstraint.constant = 0
self.view.frame.origin.y = 0
UIView.animate(withDuration: duration) {
self.view.layoutIfNeeded()
}
}
Don't forget to remove notifications at right place.
func removeKeyboardNotifications() {
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
Solution 3
#define DEVICE_HEIGHT [[UIScreen mainScreen] bounds].size.height
-(void)viewDidLoad {
[super viewDidLoad];
// register for keyboard notifications
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:self.view.window];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:self.view.window];
}
-(void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
// unregister for keyboard notifications while not visible.
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIKeyboardWillShowNotification
object:self.view.window];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:UIKeyboardWillHideNotification
object:self.view.window];
}
-(void)keyboardWillShow:(NSNotification *)noti
{
NSDictionary* userInfo = [noti userInfo];
CGRect keyboardRect = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey]
CGRectValue];
keyboardRect = [self.view convertRect:keyboardRect fromView:nil];
CGRect viewFrame = self.view.frame;
viewFrame.size.height = DEVICE_HEIGHT - CGRectGetHeight(keyboardRect);
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.1];
[UIView setAnimationBeginsFromCurrentState:YES];
self.view.frame = viewFrame;
CGPoint bottomOffset = CGPointMake(0, self.scrollView.contentSize.height
- self.view.bounds.size.height);
[self.scrollView setContentOffset:bottomOffset animated:NO];
[UIView commitAnimations];
}
-(void)keyboardWillHide:(NSNotification *)noti
{
NSDictionary* userInfo = [noti userInfo];
CGRect keyboardRect = [[userInfo
objectForKey:UIKeyboardFrameEndUserInfoKey]CGRectValue];
keyboardRect = [self.view convertRect:keyboardRect fromView:nil];
CGRect viewFrame = self.view.frame;
viewFrame.size.height = DEVICE_HEIGHT;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.1];
[UIView setAnimationBeginsFromCurrentState:YES];
self.view.frame = viewFrame;
[UIView commitAnimations];
}
user1904273
Updated on June 04, 2022Comments
-
user1904273 almost 2 years
For a login screen with just three textfields and submit button, I want the view to move up when the keyboard appears just enough so that while the field is not hidden, it also does not move up out of view.
The amount of movement needed is such that the submit button is a fixed distance above the keyboard. While it is possible by moving the fields high up on the page to leave room for the keyboard, the submit button is still hidden
I tried just adding the following:
-(void) viewWillAppear:(BOOL)Animated { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; } - (void)viewWillDisappear:(BOOL)animated { [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil]; }
This moves the view up a fixed amount but so much so that the fields are not visible for editing, i.e. they are too high up.
Another SO answer suggested:
-(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 = -200; // tweak as needed const float movementDuration = 0.3f; // tweak as needed int movement = (up ? movementDistance : -movementDistance); [UIView beginAnimations: @"animateTextField" context: nil]; [UIView setAnimationBeginsFromCurrentState: YES]; [UIView setAnimationDuration: movementDuration]; self.view.frame = CGRectOffset(self.view.frame, 0, movement); [UIView commitAnimations]; }
I can't figure out how to implement this. If you just leave it as is nothing happens. I guess you are supposed to rename textfield with the name of your textfield but in that case, would you do it for each of the textfields? I cannot get it to have any effect.
Another suggestion is to use a category such as TPKeyboardAvoiding however this requires a scrollview that I do not need in this case.
Is there no straightforward solution in 2015 for this issue?
-
user1904273 over 8 yearsI guess I am unclear on view. Do I need to change "textField" above to something specific or is that generic? if I need to change viewForLogin what is this? Do I need to specify it in a property or put the textfields in a container?
-
Fawad Masud over 8 yearsviewForLogin is any view that contains your textfields. It can be self.view or any subview of self.view. Just set the delegates of all the three textfields and add the above two delegate methods. Change viewForLogin with your respective view which contains your textfields and it will work.
-
user1904273 over 8 yearsthe view controller is a uiviewcontroller and was created in storyboard. The textfields just sit in the VC. Does every view controller come with is own self.view or how do I know what the view is called?
-
user1904273 over 8 yearsI tried it using self.view including changing viewForIpad. Does not have an effect. Other than how to identify the view as in self.view or something else, do I need to put this in a scrollview? What else might I have to do as it is having no effect.
-
Fawad Masud over 8 yearsNo need of scrollview. I have edited the answer, just self.view should do the job. Check if delegate methods are called or not.
-
user1904273 over 8 yearsI put a NSLog statement in the methods above and they re not called. I am still unclear if you need to do this for every single textfield if you have a lot of them i.e. -(void)textFieldDidBeginEditing:(UITextField *)firstNameField followed by -(void)textFieldDidBeginEditing:(UITextField *)lastNameField as I have over ten fields in this screen. Either way, however, for the field named textField, method it is not getting triggered. VC does implement textfielddelegate protocol.
-
user1904273 over 8 yearsOk. Got it to work. I had missed the part about setting the delegate for each field. I guess you do have to do this for every single field. Is there a way to do the same thing for a textview?
-
Fawad Masud over 8 yearsSame you have to do for textView. Set the delegates and call the delegate methods developer.apple.com/library/ios/documentation/UIKit/Reference/…
-
Tash Pemhiwa almost 7 yearsWhat is
DEVICE_HEIGHT
here?