By philfreo


2009-07-14 17:06:07 8 Comments

With the iOS SDK:

I have a UIView with UITextFields that bring up a keyboard. I need it to be able to:

  1. Allow scrolling of the contents of the UIScrollView to see the other text fields once the keyboard is brought up

  2. Automatically "jump" (by scrolling up) or shortening

I know that I need a UIScrollView. I've tried changing the class of my UIView to a UIScrollView but I'm still unable to scroll the textboxes up or down.

Do I need both a UIView and a UIScrollView? Does one go inside the other?

What needs to be implemented in order to automatically scroll to the active text field?

Ideally as much of the setup of the components as possible will be done in Interface Builder. I'd like to only write code for what needs it.

Note: the UIView (or UIScrollView) that I'm working with is brought up by a tabbar (UITabBar), which needs to function as normal.


Edit: I am adding the scroll bar just for when the keyboard comes up. Even though it's not needed, I feel like it provides a better interface because then the user can scroll and change textboxes, for example.

I've got it working where I change the frame size of the UIScrollView when the keyboard goes up and down. I'm simply using:

-(void)textFieldDidBeginEditing:(UITextField *)textField { 
    //Keyboard becomes visible
    scrollView.frame = CGRectMake(scrollView.frame.origin.x, 
                     scrollView.frame.origin.y, 
scrollView.frame.size.width,
scrollView.frame.size.height - 215 + 50);   //resize
}

-(void)textFieldDidEndEditing:(UITextField *)textField {
   //keyboard will hide
    scrollView.frame = CGRectMake(scrollView.frame.origin.x, 
       scrollView.frame.origin.y, 
     scrollView.frame.size.width,
      scrollView.frame.size.height + 215 - 50); //resize
}

However, this doesn't automatically "move up" or center the lower text fields in the visible area, which is what I would really like.

30 comments

@Паша Матюхин 2019-07-06 21:16:30

Swift 5

in viewDidLoad or viewDidAppear add addKeyboardObservers method.

fileprivate func addKeyboardObservers(){
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)

    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
}

fileprivate func removeKeyboardObservers(){
    NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
    NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
}


@objc fileprivate func keyboardWillHide(_ notification: Notification){
    if (window == nil) {return}
    guard let duration = (notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double) else {return}

   scrollView.contentInset.bottom = .zero
}


@objc fileprivate func keyboardWillShow(_ notification: Notification){
    if (window == nil) {return}
    if UIApplication.shared.applicationState != .active { return }

    // keyboard height
    guard let height = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect)?.height else {return}
    // keyboard present animation duration
    guard let duration = (notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double) else {return}

   scrollView.contentInset.bottom = height
}

don't forget remove observers on deinit or disappear

    self.removeKeyboardObservers()

@Jay Lee 2019-07-26 04:21:05

Apple documentation on addObserver:selector:name:object: says "If your app targets iOS 9.0 and later or macOS 10.11 and later, you don't need to unregister an observer in its dealloc method."

@Satnam Sync 2015-04-30 11:21:08

For Swift Programmers :

This will do everything for you, just put these in your view controller class and implement the UITextFieldDelegate to your view controller & set the textField's delegate to self

textField.delegate = self // Setting delegate of your UITextField to self

Implement the delegate callback methods:

func textFieldDidBeginEditing(textField: UITextField) {
    animateViewMoving(true, moveValue: 100)
}

func textFieldDidEndEditing(textField: UITextField) {
    animateViewMoving(false, moveValue: 100)
}

// Lifting the view up
func animateViewMoving (up:Bool, moveValue :CGFloat){
    let movementDuration:NSTimeInterval = 0.3
    let movement:CGFloat = ( up ? -moveValue : moveValue)
    UIView.beginAnimations( "animateView", context: nil)
    UIView.setAnimationBeginsFromCurrentState(true)
    UIView.setAnimationDuration(movementDuration )
    self.view.frame = CGRectOffset(self.view.frame, 0,  movement)
    UIView.commitAnimations()
}

For Swift 4, 4.2, 5: Change

self.view.frame = CGRectOffset(self.view.frame, 0,  movement)

to

self.view.frame = self.view.frame.offsetBy(dx: 0, dy: movement)

Last note about this implementation: If you push another view controller onto the stack while the keyboard is shown, this will create an error where the view is returned back to its center frame but keyboard offset is not reset. For example, your keyboard is the first responder for nameField, but then you push a button that pushes your Help View Controller onto your stack. To fix the offset error, make sure to call nameField.resignFirstResponder() before leaving the view controller, ensuring that the textFieldDidEndEditing delegate method is called as well. I do this in the viewWillDisappear method.

@levibostian 2016-05-10 18:10:01

SwiftLint didn't like self.view.frame = CGRectOffset(self.view.frame, 0, movement) so I changed that line to self.view.frame.offsetInPlace(dx: 0, dy: movement)

@Asinox 2018-01-14 20:22:18

Swift 4 change self.view.frame = CGRectOffset(self.view.frame, 0, movement) to self.view.frame.offsetBy(dx: 0, dy: movement)

@Josh Wolff 2019-07-05 08:32:37

FYI, for this to work, you have to put. self.view.frame = self.view.frame.offsetBy(dx: 0, dy: movement)

@naresh kolindala 2019-04-05 10:00:38

Using IQKeyboardManager, The UITextField and UITextView automatically scroll when keyboard appears. Git link: https://github.com/hackiftekhar/IQKeyboardManager.

pod: pod 'IQKeyboardManager' #iOS8 and later

pod 'IQKeyboardManager', '3.3.7' #iOS7

@jayesh mardiya 2015-10-01 13:47:34

Please add these lines in text field delegate method to scroll up in iPad.

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
    activeTextfield = textField;

    CGPoint pt;
    CGRect rc = [textField bounds];
    rc = [textField convertRect:rc toView:scrlView];
    pt = rc.origin;
    pt.x = 0;
    pt.y -= 100;

    [scrlView setContentOffset:pt animated:YES];

    scrlView.contentSize = CGSizeMake(scrlView.frame.size.width, button.frame.origin.y+button.frame.size.height + 8 + 370);
}

@Sourabh Sharma 2015-05-11 13:32:32

Try this short trick.

- (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 = textField.frame.origin.y / 2; // 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];
}

@Sergiu Todirascu 2018-09-26 18:28:49

If the text field should be at the bottom of the screen, then the most magical solution is the following override on your viewcontroller:

override var inputAccessoryView: UIView? {
    return <yourTextField>
}

@gbk 2018-09-12 08:16:01

Add my 5 cent :)

I always prefer to use tableView for inputTextField or scrollView. In combination with Notifications you can easily mange such behavior. (Note, if you use static cells in tableView such behaviour will manage automatically for you.)

// MARK: - Notifications
fileprivate func registerNotificaitions() {
    NotificationCenter.default.addObserver(self, selector: #selector(AddRemoteControlViewController.keyboardWillAppear(_:)),
                                           name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(AddRemoteControlViewController.keyboardWillDisappear),
                                           name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}

fileprivate func unregisterNotifications() {
    NotificationCenter.default.removeObserver(self)
}

@objc fileprivate func keyboardWillAppear(_ notification: Notification) {
    if let keyboardHeight = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.height {
        view.layoutIfNeeded()
        UIView.animate(withDuration: 0.3, animations: {
            let heightInset = keyboardHeight - self.addDeviceButton.frame.height
            self.tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: heightInset, right: 0)
            self.view.layoutIfNeeded()
        }, completion: nil)
    }
}

@objc fileprivate func keyboardWillDisappear() {
    view.layoutIfNeeded()
    UIView.animate(withDuration: 0.3, animations: {
        self.tableView.contentInset = UIEdgeInsets.zero
        self.view.layoutIfNeeded()
    }, completion: nil)
}

@Pankaj Jangid 2018-05-24 13:29:04

We can user given code for Swift 4.1

    let keyBoardSize = 80.0

    func keyboardWillShow() {

    if view.frame.origin.y >= 0 {
    viewMovedUp = true
     }
     else if view.frame.origin.y < 0 {
    viewMovedUp = false
   }
  }

func keyboardWillHide() {
 if view.frame.origin.y >= 0 {
    viewMovedUp = true
 }
 else if view.frame.origin.y < 0 {
    viewMovedUp = false
 }

}

func textFieldDidBeginEditing(_ textField: UITextField) {
   if sender.isEqual(mailTf) {
    //move the main view, so that the keyboard does not hide it.
    if view.frame.origin.y >= 0 {
        viewMovedUp = true
    }
  }
}

func setViewMovedUp(_ movedUp: Bool) {
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(0.3)
    // if you want to slide up the view
let rect: CGRect = view.frame
if movedUp {

    rect.origin.y -= keyBoardSize
    rect.size.height += keyBoardSize
}
else {
    // revert back to the normal state.
    rect.origin.y += keyBoardSize
    rect.size.height -= keyBoardSize
 }
 view.frame = rect
 UIView.commitAnimations()
}

func viewWillAppear(_ animated: Bool)  {
super.viewWillAppear(animated)

NotificationCenter.default.addObserver(self, selector:#selector(self.keyboardWillShow), name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector:#selector(self.keyboardWillHide), name: .UIKeyboardWillHide, object: nil)
}

func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)

NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillHide, object: nil)
}

@Bruce Lee 2015-01-22 07:56:29

First of all, I recommend a better design for your page so that there is no need to scroll your view. If you have many text fields, you still don't have to use a ScrollView, it just makes things complicated. You can just add a container UIView on the top of the controller's original view, then put those text fields on that view. When the keyboard shows or disappears, just use an animation to move this container view.

@dmani ms 2018-05-17 06:01:39

Refer follwing

import UIKit
@available(tvOS, unavailable)
public class KeyboardLayoutConstraint: NSLayoutConstraint {

    private var offset : CGFloat = 0
    private var keyboardVisibleHeight : CGFloat = 0

    @available(tvOS, unavailable)
    override public func awakeFromNib() {
        super.awakeFromNib()

        offset = constant

        NotificationCenter.default.addObserver(self, selector: #selector(KeyboardLayoutConstraint.keyboardWillShowNotification(_:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(KeyboardLayoutConstraint.keyboardWillHideNotification(_:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
    }

    deinit {
        NotificationCenter.default.removeObserver(self)
    }

    // MARK: Notification

    @objc func keyboardWillShowNotification(_ notification: Notification) {
        if let userInfo = notification.userInfo {
            if let frameValue = userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue {
                let frame = frameValue.cgRectValue
                keyboardVisibleHeight = frame.size.height
            }

            self.updateConstant()
            switch (userInfo[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber, userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber) {
            case let (.some(duration), .some(curve)):

                let options = UIViewAnimationOptions(rawValue: curve.uintValue)

                UIView.animate(
                    withDuration: TimeInterval(duration.doubleValue),
                    delay: 0,
                    options: options,
                    animations: {
                        UIApplication.shared.keyWindow?.layoutIfNeeded()
                        return
                    }, completion: { finished in
                })
            default:

                break
            }

        }

    }

    @objc func keyboardWillHideNotification(_ notification: NSNotification) {
        keyboardVisibleHeight = 0
        self.updateConstant()

        if let userInfo = notification.userInfo {

            switch (userInfo[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber, userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber) {
            case let (.some(duration), .some(curve)):

                let options = UIViewAnimationOptions(rawValue: curve.uintValue)

                UIView.animate(
                    withDuration: TimeInterval(duration.doubleValue),
                    delay: 0,
                    options: options,
                    animations: {
                        UIApplication.shared.keyWindow?.layoutIfNeeded()
                        return
                    }, completion: { finished in
                })
            default:
                break
            }
        }
    }

    func updateConstant() {
        self.constant = offset + keyboardVisibleHeight
    }

}

@ZAFAR007 2018-01-26 10:48:34

Swift 4 .

You Can Easily Move Up And Down UITextField Or UIView With UIKeyBoard With Animation enter image description here

import UIKit

class ViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet var textField: UITextField!
    @IBOutlet var chatView: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChange), name: .UIKeyboardWillChangeFrame, object: nil)
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        textField.resignFirstResponder()
    }

    @objc func keyboardWillChange(notification: NSNotification) {

        let duration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double
        let curve = notification.userInfo![UIKeyboardAnimationCurveUserInfoKey] as! UInt
        let curFrame = (notification.userInfo![UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
        let targetFrame = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
        let deltaY = targetFrame.origin.y - curFrame.origin.y
        print("deltaY",deltaY)

        UIView.animateKeyframes(withDuration: duration, delay: 0.0, options: UIViewKeyframeAnimationOptions(rawValue: curve), animations: {
            self.chatView.frame.origin.y+=deltaY // Here You Can Change UIView To UITextField
        },completion: nil)
    }

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        return true
    }

}

@davidgyoung 2018-05-26 02:06:18

Nice simple solution.

@Houman 2018-08-18 17:27:05

Almost perfect. On iPhone X though you get a strange gap between keyboard and textfield.

@JIE WANG 2018-04-18 10:16:02

This question has already a lot of answers, some said to use scroll view, some said to use a third lib.

But for me the idea solution should be UITableViewController with static cells.

You separate your UI to multiple part and put them in the tableViewCells one by one, than your don't need worry about keyboard anymore, tableViewController will manage it for you automatically.

It may be a little difficult to calculate the padding, margin, cell height, but if your math is ok, it's simple.

@DK_ 2011-01-29 14:56:02

It's actually best just to use Apple's implementation, as provided in the docs. However, the code they provide is faulty. Replace the portion found in keyboardWasShown: just below the comments to the following:

NSDictionary* info = [aNotification userInfo];
CGRect keyPadFrame=[[UIApplication sharedApplication].keyWindow convertRect:[[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue] fromView:self.view];
CGSize kbSize =keyPadFrame.size;
CGRect activeRect=[self.view convertRect:activeField.frame fromView:activeField.superview];
CGRect aRect = self.view.bounds;
aRect.size.height -= (kbSize.height);

CGPoint origin =  activeRect.origin;
origin.y -= backScrollView.contentOffset.y;
if (!CGRectContainsPoint(aRect, origin)) {
    CGPoint scrollPoint = CGPointMake(0.0,CGRectGetMaxY(activeRect)-(aRect.size.height));
    [backScrollView setContentOffset:scrollPoint animated:YES];
}

The problems with Apple's code are these: (1) They always calculate if the point is within the view's frame, but it's a ScrollView, so it may already have scrolled and you need to account for that offset:

origin.y -= scrollView.contentOffset.y

(2) They shift the contentOffset by the height of the keyboard, but we want the opposite (we want to shift the contentOffset by the height that is visible on the screen, not what isn't):

activeField.frame.origin.y-(aRect.size.height)

@zakdances 2012-05-28 22:42:09

Wouldn't a better solution be to adjust the size of the scrollview to have its height match the top of the keyboard?

@8vius 2012-06-14 16:04:20

This doesn't work for me, my view scrolls down and not up it just completely hides behind my keyboard.

@DK_ 2012-07-05 10:38:35

@8vius Make sure you haven't inverted the origin of the view? Depending on what is defined as origin (0,0) it will change the logic.

@mblackwell8 2013-05-09 04:48:36

In situations where the scroll view is not filling the screen, aRect should be set to the scroll view's frame

@makaed 2014-03-17 17:22:38

@DK_ I followed Apple's implementation and changed the part you provided. However, it doesn't work for me. I can see that my hidden textField moves a very tiny bit up, but far from being visible. Any ideas where the issue might be?

@DK_ 2014-03-18 18:22:44

@Makaed I'd double check your view frames.

@makaed 2014-03-19 01:06:43

@DK_ Seems good there. I have a few text fields in a generic scroll view (didn't subclass it, just created an outlet for it). That doesn't matter right?

@htafoya 2014-04-15 17:16:48

Shouldn't you want the CGPoint origin = activeField.frame.origin + activeField.frame.size.height ?, because you want the whole textfield to be displayed and if it happens to have just some pixels visible then code won't enter the condition.

@htafoya 2014-04-15 17:20:05

Also this only works if the textfield is not at the bottom, because you are never changing the scrollview's position or size, then it won't be able to scroll through the bottom.

@Andrew 2014-04-27 09:47:12

This solution doesn't work in Landscape orientation — the text field flies off the top of the view port. iPad with iOS 7.1.

@hris.to 2014-06-25 08:56:57

This won't work if your TextField is embedded in some other views, as it's frame is based on it's superview not based on the scroll view.

@Chris Nolet 2014-07-19 01:34:46

For point 2, it might be easiest to use: [self.scrollView scrollRectToVisible:activeField.frame animated:YES];

@Endareth 2014-11-13 02:06:09

For better iOS 8 support, I'd suggest using UIKeyboardFrameEndUserInfoKey instead of UIKeyboardFrameBeginUserInfoKey when getting the keyboard size, as this will pick up things such as custom keyboard changes and toggling predictive text on/off.

@Morten Holmgaard 2015-01-23 07:32:44

@Egor: Your fix makes it work way better - but the last line must be inverse: self.scrollView.contentOffset = self.currentSVoffset;

@Egor 2015-01-23 07:38:51

@MortenHolmgaard Of course, you're right. That was a mistake while copy-pasting code from my project.

@David Cespedes 2015-03-08 01:53:49

This doesn't work because UIKeyboardWillShowNotification will not get called when tapping the next button of a UITextField or when the keyboard is visible and you select another UITextField. It will just get called when the keyboard is going to be shown.

@CularBytes 2015-09-29 07:57:05

Sept. 2015: I've implemented it with swift, it does correctly move the view up when begin editing a textview, however, when I scroll the ScrollView while the keyboard is still present, it resets to it's original, thus hiding the textview behind the keyboard again. Also, when I already scrolled down to the bottom a bit, it won't scroll up anymore when begin editing the Text view. I'll try below answer now: stackoverflow.com/a/17707278/2901207

@RPDP 2009-07-14 18:03:55

  1. You will only need a ScrollView if the contents you have now do not fit in the iPhone screen. (If you are adding the ScrollView as the superview of the components. just to make the TextField scroll up when keyboard comes up, then it's not needed.)

  2. For showing the textfields without being hidden by the keyboard, the standard way is to move up/down the view having textfields whenever the keyboard is shown.

Here is some sample code:

#define kOFFSET_FOR_KEYBOARD 80.0

-(void)keyboardWillShow {
    // Animate the current view out of the way
    if (self.view.frame.origin.y >= 0)
    {
        [self setViewMovedUp:YES];
    }
    else if (self.view.frame.origin.y < 0)
    {
        [self setViewMovedUp:NO];
    }
}

-(void)keyboardWillHide {
    if (self.view.frame.origin.y >= 0)
    {
        [self setViewMovedUp:YES];
    }
    else if (self.view.frame.origin.y < 0)
    {
        [self setViewMovedUp:NO];
    }
}

-(void)textFieldDidBeginEditing:(UITextField *)sender
{
    if ([sender isEqual:mailTf])
    {
        //move the main view, so that the keyboard does not hide it.
        if  (self.view.frame.origin.y >= 0)
        {
            [self setViewMovedUp:YES];
        }
    }
}

//method to move the view up/down whenever the keyboard is shown/dismissed
-(void)setViewMovedUp:(BOOL)movedUp
{
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.3]; // if you want to slide up the view

    CGRect rect = self.view.frame;
    if (movedUp)
    {
        // 1. move the view's origin up so that the text field that will be hidden come above the keyboard 
        // 2. increase the size of the view so that the area behind the keyboard is covered up.
        rect.origin.y -= kOFFSET_FOR_KEYBOARD;
        rect.size.height += kOFFSET_FOR_KEYBOARD;
    }
    else
    {
        // revert back to the normal state.
        rect.origin.y += kOFFSET_FOR_KEYBOARD;
        rect.size.height -= kOFFSET_FOR_KEYBOARD;
    }
    self.view.frame = rect;

    [UIView commitAnimations];
}


- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    // register for keyboard notifications
    [[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
{
    [super viewWillDisappear:animated];
    // unregister for keyboard notifications while not visible.
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                             name:UIKeyboardWillShowNotification
                                           object:nil];

    [[NSNotificationCenter defaultCenter] removeObserver:self
                                             name:UIKeyboardWillHideNotification
                                           object:nil];
}

@Cocoa Dev 2010-12-14 17:56:27

What does _textField? I copied it into my code, it says _textField is undeclared.

@patrick 2011-01-28 13:02:08

It's the field that you use to say "when the user is editing here the view should slide up" or something so... However you can remove that if, if you more fields.

@Abduliam Rehmanius 2011-06-26 04:08:46

isn't it batter to call -(void)setViewMovedUp:(BOOL)movedUp in keyBoardWillSHow and KeyBoardWillHide events!!

@Michael 2011-07-29 18:02:02

Is the benefit of this example over the next that it does not require a UIScrollView? I don't want to have to put the contents of the view in an otherwise useless UIScrollView if its not necessary.

@Amit Battan 2012-05-09 17:49:55

getting issue on UIInterfaceOrientationLandscapeRight and UIInterfaceOrientationLandscapeLeft . . . . My application work only in Landscape

@lolol 2012-10-12 06:38:10

self is undefined for me. =/

@FractalDoctor 2012-12-02 16:00:34

Not particularly useful if you're supporting rotations of the main view.

@AlexChaffee 2013-02-12 23:52:49

I like your solution but I think I can make it even simpler: don't bother with the Notification Observer stuff; instead call the right animation routines inside the appropriate delegate methods -- for UITextView they're textViewDidBeginEditing and textViewDidEndEditing.

@zzzzz 2013-03-19 07:40:55

This code works for textfields but does'nt work for uitextview.The textview is at the bottom of my screen, I want to move it up when the keyboard appears

@Jeff 2013-07-20 08:41:45

Definitely don't change Y -- must change height!

@IKKA 2013-09-07 10:20:34

if keyboard is open then i go to background and i come back to foreground then keyboard is open but frame of view is not set in old position.what is the reason?

@ZviBar 2014-03-25 12:00:30

You don't need to paste the - (void)viewWillAppear:(BOOL)animated method at all. It just spoils everything.

@Puttin 2015-04-14 08:03:28

Use NPKeyboardLayoutGuide if you are using AutoLayout.

@Ben Leggiero 2015-11-02 19:48:32

I think you meant to give that compiler-constant a different name; prefixing it with a lower-case k implies it's a key, but you're using it as a naked constant.

@Rincha 2016-01-14 15:56:08

Not working with multiple texfiels

@W.K.S 2016-06-26 11:10:56

@user1519240: That post worked for me after commenting out !CGRectContainsPoint(aRect, activeField!.frame.origin). Thanks :)

@Burak 2016-08-08 14:54:18

For anyone using a storyboard and trying to make it work but can't, just make sure that self.view has leading, top and trailing constraints. Otherwise, it probably won't work.

@avance 2016-09-21 22:23:29

To make this work, I had to comment out the textFieldDidBeginEditing section.

@Purushothaman 2016-11-11 07:05:32

my top textfield's are hidden when the keyboard is shown because,it is working not only for that particular textfield i'm giving but also for all the textfields i have . how do i fix it

@Andy Weinstein 2017-06-29 13:46:25

Didn't work for me. If it doesn't work for you, I recommend adding a scroll view in your storyboard around the pieces that you want to move (consider that carefully) and using the Apple code here: developer.apple.com/library/content/documentation/… with one modification: use UIKeyboardWillShowNotification instead of UIKeyboardDidShowNotification. That improvement will eliminate a lag you get before the scrolling starts.

@Jonny 2017-11-02 06:19:10

Bad for using hardcoded keyboard size.

@Isaac Carol Weisberg 2018-05-03 04:21:12

Poor, deviating practice

@chuckSaldana 2018-06-12 16:55:44

Not very useful if you want to allow scrolling while editing the input fields.

@cbranch 2010-11-06 05:25:02

Shiun said "As it turned out, I believe the UIScrollView actually implicitly brings the currently edited UITextField into the viewable window implicitly" This seems to be true for iOS 3.1.3, but not 3.2, 4.0, or 4.1. I had to add an explicit scrollRectToVisible in order to make the UITextField visible on iOS >= 3.2.

@Harminder Singh 2017-12-01 03:58:57

You can use this simple Git repository: https://github.com/hackiftekhar/IQKeyboardManager

This is a library that manages all the moving of fields automatically.

According to their readme, the integration is super easy:

without needing you to enter any code and no additional setup required. To use IQKeyboardManager you simply need to add source files to your project

Although,this is very good control, in some cases it causes conflict, like in the view controllers with scroll view. It sometimes changes the content size. Still, you can go for it, and try it as per your requirement maybe you could do what I missed.

@Shiun 2010-04-24 08:31:04

I was also having a lot of issue with a UIScrollView composing of multiple UITextFields, of which, one or more of them would get obscured by the keyboard when they are being edited.

Here are some things to consider if your UIScrollView is not properly scrolling.

1) Ensure that your contentSize is greater than the UIScrollView frame size. The way to understand UIScrollViews is that the UIScrollView is like a viewing window on the content defined in the contentSize. So when in order for the UIScrollview to scroll anywhere, the contentSize must be greater than the UIScrollView. Else, there is no scrolling required as everything defined in the contentSize is already visible. BTW, default contentSize = CGSizeZero.

2) Now that you understand that the UIScrollView is really a window into your "content", the way to ensure that the keyboard is not obscuring your UIScrollView's viewing "window" would be to resize the UIScrollView so that when the keyboard is present, you have the UIScrollView window sized to just the original UIScrollView frame.size.height minus the height of the keyboard. This will ensure that your window is only that small viewable area.

3) Here's the catch: When I first implemented this I figured I would have to get the CGRect of the edited textfield and call UIScrollView's scrollRecToVisible method. I implemented the UITextFieldDelegate method textFieldDidBeginEditing with the call to the scrollRecToVisible method. This actually worked with a strange side effect that the scrolling would snap the UITextField into position. For the longest time I couldn't figure out what it was. Then I commented out the textFieldDidBeginEditing Delegate method and it all work!!(???). As it turned out, I believe the UIScrollView actually implicitly brings the currently edited UITextField into the viewable window implicitly. My implementation of the UITextFieldDelegate method and subsequent call to the scrollRecToVisible was redundant and was the cause of the strange side effect.

So here are the steps to properly scroll your UITextField in a UIScrollView into place when the keyboard appears.

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.

- (void)viewDidLoad 
{
    [super viewDidLoad];

    // register for keyboard notifications
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(keyboardWillShow:) 
                                                 name:UIKeyboardWillShowNotification 
                                               object:self.view.window];
    // register for keyboard notifications
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(keyboardWillHide:) 
                                                 name:UIKeyboardWillHideNotification 
                                               object:self.view.window];
    keyboardIsShown = NO;
    //make contentSize bigger than your scrollSize (you will need to figure out for your own use case)
    CGSize scrollContentSize = CGSizeMake(320, 345);
    self.scrollView.contentSize = scrollContentSize;
}

- (void)keyboardWillHide:(NSNotification *)n
{
    NSDictionary* userInfo = [n userInfo];

    // get the size of the keyboard
    CGSize keyboardSize = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;


    // resize the scrollview
    CGRect viewFrame = self.scrollView.frame;
    // I'm also subtracting a constant kTabBarHeight because my UIScrollView was offset by the UITabBar so really only the portion of the keyboard that is leftover pass the UITabBar is obscuring my UIScrollView.
    viewFrame.size.height += (keyboardSize.height - kTabBarHeight);

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [self.scrollView setFrame:viewFrame];
    [UIView commitAnimations];

    keyboardIsShown = NO;
}

- (void)keyboardWillShow:(NSNotification *)n
{
    // This is an ivar I'm using to ensure that we do not do the frame size adjustment on the `UIScrollView` if the keyboard is already shown.  This can happen if the user, after fixing editing a `UITextField`, scrolls the resized `UIScrollView` to another `UITextField` and attempts to edit the next `UITextField`.  If we were to resize the `UIScrollView` again, it would be disastrous.  NOTE: The keyboard notification will fire even when the keyboard is already shown.
    if (keyboardIsShown) {
        return;
    }

    NSDictionary* userInfo = [n userInfo];

    // get the size of the keyboard
    CGSize keyboardSize = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;

    // resize the noteView
    CGRect viewFrame = self.scrollView.frame;
    // I'm also subtracting a constant kTabBarHeight because my UIScrollView was offset by the UITabBar so really only the portion of the keyboard that is leftover pass the UITabBar is obscuring my UIScrollView.
    viewFrame.size.height -= (keyboardSize.height - kTabBarHeight);

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [self.scrollView setFrame:viewFrame];
    [UIView commitAnimations];
    keyboardIsShown = YES;
}
  1. Register for the keyboard notifications at viewDidLoad
  2. Unregister for the keyboard nofitications at viewDidUnload
  3. Ensure that the contentSize is set and greater than your UIScrollView at viewDidLoad
  4. Shrink the UIScrollView when the keyboard is present
  5. Revert back the UIScrollView when the keyboard goes away.
  6. Use an ivar to detect if the keyboard is already shown on the screen since the keyboard notifications are sent each time a UITextField is tabbed even if the keyboard is already present to avoid shrinking the UIScrollView when it's already shrunk

One thing to note is that the UIKeyboardWillShowNotification will fire even when the keyboard is already on the screen when you tab on another UITextField. I took care of this by using an ivar to avoid resizing the UIScrollView when the keyboard is already on the screen. Inadvertently resizing the UIScrollView when the keyboard is already there would be disastrous!

Hope this code saves some of you a lot of headache.

@Martin Wickman 2011-04-20 21:26:32

Great, but two problems: 1. UIKeyboardBoundsUserInfoKey is deprecated. 2. keyboardSize is in "screen coordinates", so your viewFrame calculations will fail if the frame is rotated or scaled.

@sottenad 2011-07-30 20:51:54

@Martin Wickman - Use CGSize keyboardSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; instead of the deprecated UIKeyboardBoundsUserInfoKey

@gyozo kudor 2011-08-02 08:13:13

Great answer but what should I do if I want to resize the view only if some of the controls are active. Let's say I have a textfield at the top of the view and one on the bottom, and I only want to resize the view for the textfield at the bottom.

@Philip Regan 2012-04-17 02:39:52

This does not work as writ for iOS 5. Either there is something missing in the implementation description or the code, or something from the comments makes it work, but I could not get it to work properly in iOS 5. In fact, Apple's own docs have not been updated since iOS 3.

@user517491 2012-04-19 13:07:08

HI, I did the same, but the text view only moves up when user starts typing? Is it the expected behavior or I am missing something?

@user517491 2012-04-19 13:14:30

@Shiun HI, I did the same, but the text view only moves up when user starts typing? Is it the expected behavior or I am missing something?

@newton_guima 2012-05-02 23:33:40

@Shiun you should also remove yourself as the observer in the dealloc method.. people often confuse the viewDidUnload as the opposite of the viewDidLoad... the viewDidUnload is only called when there is a memory warning.. so it might never be called, the dealloc, instead, will be called at some point for sure.

@j7nn7k 2012-05-24 08:09:54

[[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size should be [[userInfo objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size . Great solution though!

@Tim Büthe 2012-06-21 20:45:27

Like @djaqeel says, it would be great if the crolling whould happen as soon as the fields gets the focus, not when start typing. Secondly, scrolling back to the top or even the original position when the keyboard is hidden would be great.

@Craig B 2012-10-31 19:45:22

Ok a couple more things here. From that userInfo dictionary you can get the animation duration and curve with the following keys: UIKeyboardAnimationDurationUserInfoKey and UIKeyboardAnimationCurveUserInfoKey. You should definitely use these instead of hard-coding!!!

@AlexChaffee 2013-02-12 23:51:39

I like your solution but I think I can make it even simpler: don't bother with the Notification Observer stuff; instead call the right animation routines inside the appropriate delegate methods -- for UITextView they're textViewDidBeginEditing and textViewDidEndEditing.

@Mxyk 2013-03-05 19:32:05

@glenc What do you mean? How would I do that (could you supply sample code)? Because this works for me as well except for when the iPad is in landscape.

@Dan Loewenherz 2014-01-03 16:05:51

This is the correct answer. The other answer that's currently marked as correct has the keyboard size pinned to 80, which can very well change in iOS from version to version. This answer handles that situation appropriately.

@tounaobun 2015-02-06 07:01:37

keyboardIsShown property is required or your UIScrollview's contentInset bottom will grow larger when you click keyboard's globe key(change input).

@David Cespedes 2015-03-08 04:23:55

This is not true for me "The keyboard notification will fire even when the keyboard is already shown." am I doing something wrong? I'm working with Xcode 6.1.1 on iOS 7 and 8. Autolayout disabled

@Hemang 2015-03-26 06:37:24

@DavidCespedes, which notification is firing? If its already visible then keyboardWillHide: should call.

@David Cespedes 2015-03-27 17:24:41

@hagile they say in the answer that "The keyboard notification will fire even when the keyboard is already shown." That's not true. It will only fire when it's going to be shown, but if it's already on the screen, it won't and shouldn't fire that keyboardWillShow again, as it is already shown. It is working like this since iOS 6 I think. Before it used to fire the notification no matter the keyboard was already shown.

@CyberMoai 2017-05-06 01:40:04

Very important: use UIKeyboardFrameEndUserInfoKey instead of UIKeyboardFrameBeginUserInfoKey. Makes a difference when rotating the view.

@Badr 2017-08-01 01:08:10

I know this is too late but I wanted to share with the future visitors especially my way of doing it. Many good methods were shared but I didn't like how the UI becomes totally bad. There's a simple method which involves two parts:-

  1. Add the TextField and, whatever you want it to be floating above the keyboard while editing, to a view so they become children of the view. And then it will be easy to maintain the look and not to affect the UI badly.
  2. Use the great tool CGAffineTransform(TranslationX: x, TranslationY: y) to move the created view above the keyboard.

I know it seems very simple but it is really effective and neat. enter image description here

@Jaydeep Vyas 2017-07-07 09:05:51

Simple Solution For Scrollview with TextFields is below, No need any Constraints or active textfield etc...

 override func viewWillAppear(_ animated: Bool){
        super.viewWillAppear(animated)
        registerForKeyboardNotifications();


    }
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        deregisterFromKeyboardNotifications();
    }
    //MARK:- KEYBOARD DELEGATE METHODS
        func registerForKeyboardNotifications(){
            //Adding notifies on keyboard appearing
            NotificationCenter.default.addObserver(self, selector: #selector(keyboardWasShown(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
            NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillBeHidden(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
        }
        func deregisterFromKeyboardNotifications(){
            //Removing notifies on keyboard appearing
            NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil)
            NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)
        }
        func keyboardWasShown(notification: NSNotification){

            var info = notification.userInfo!
            let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
            var contentInset:UIEdgeInsets = self.scrRegister.contentInset
            contentInset.bottom = (keyboardSize?.height)!
            scrRegister.contentInset = contentInset


        }
        func keyboardWillBeHidden(notification: NSNotification)
        {
            var contentInset:UIEdgeInsets = self.scrRegister.contentInset
            contentInset.bottom = 0
            scrRegister.contentInset = contentInset

        }

@Martin Ullrich 2013-03-01 19:41:24

There are already a lot of answers, but still none of the solutions above had all the fancy positioning stuff required for a "perfect" bug-free, backwards compatible and flicker-free animation. (bug when animating frame/bounds and contentOffset together, different interface orientations, iPad split keyboard, ...)
Let me share my solution:
(assuming you have set up UIKeyboardWill(Show|Hide)Notification)

// Called when UIKeyboardWillShowNotification is sent
- (void)keyboardWillShow:(NSNotification*)notification
{
    // if we have no view or are not visible in any window, we don't care
    if (!self.isViewLoaded || !self.view.window) {
        return;
    }

    NSDictionary *userInfo = [notification userInfo];

    CGRect keyboardFrameInWindow;
    [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardFrameInWindow];

    // the keyboard frame is specified in window-level coordinates. this calculates the frame as if it were a subview of our view, making it a sibling of the scroll view
    CGRect keyboardFrameInView = [self.view convertRect:keyboardFrameInWindow fromView:nil];

    CGRect scrollViewKeyboardIntersection = CGRectIntersection(_scrollView.frame, keyboardFrameInView);
    UIEdgeInsets newContentInsets = UIEdgeInsetsMake(0, 0, scrollViewKeyboardIntersection.size.height, 0);

    // this is an old animation method, but the only one that retains compaitiblity between parameters (duration, curve) and the values contained in the userInfo-Dictionary.
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
    [UIView setAnimationCurve:[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];

    _scrollView.contentInset = newContentInsets;
    _scrollView.scrollIndicatorInsets = newContentInsets;

    /*
     * Depending on visual layout, _focusedControl should either be the input field (UITextField,..) or another element
     * that should be visible, e.g. a purchase button below an amount text field
     * it makes sense to set _focusedControl in delegates like -textFieldShouldBeginEditing: if you have multiple input fields
     */
    if (_focusedControl) {
        CGRect controlFrameInScrollView = [_scrollView convertRect:_focusedControl.bounds fromView:_focusedControl]; // if the control is a deep in the hierarchy below the scroll view, this will calculate the frame as if it were a direct subview
        controlFrameInScrollView = CGRectInset(controlFrameInScrollView, 0, -10); // replace 10 with any nice visual offset between control and keyboard or control and top of the scroll view.

        CGFloat controlVisualOffsetToTopOfScrollview = controlFrameInScrollView.origin.y - _scrollView.contentOffset.y;
        CGFloat controlVisualBottom = controlVisualOffsetToTopOfScrollview + controlFrameInScrollView.size.height;

        // this is the visible part of the scroll view that is not hidden by the keyboard
        CGFloat scrollViewVisibleHeight = _scrollView.frame.size.height - scrollViewKeyboardIntersection.size.height;

        if (controlVisualBottom > scrollViewVisibleHeight) { // check if the keyboard will hide the control in question
            // scroll up until the control is in place
            CGPoint newContentOffset = _scrollView.contentOffset;
            newContentOffset.y += (controlVisualBottom - scrollViewVisibleHeight);

            // make sure we don't set an impossible offset caused by the "nice visual offset"
            // if a control is at the bottom of the scroll view, it will end up just above the keyboard to eliminate scrolling inconsistencies
            newContentOffset.y = MIN(newContentOffset.y, _scrollView.contentSize.height - scrollViewVisibleHeight);

            [_scrollView setContentOffset:newContentOffset animated:NO]; // animated:NO because we have created our own animation context around this code
        } else if (controlFrameInScrollView.origin.y < _scrollView.contentOffset.y) {
            // if the control is not fully visible, make it so (useful if the user taps on a partially visible input field
            CGPoint newContentOffset = _scrollView.contentOffset;
            newContentOffset.y = controlFrameInScrollView.origin.y;

            [_scrollView setContentOffset:newContentOffset animated:NO]; // animated:NO because we have created our own animation context around this code
        }
    }

    [UIView commitAnimations];
}


// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillHide:(NSNotification*)notification
{
    // if we have no view or are not visible in any window, we don't care
    if (!self.isViewLoaded || !self.view.window) {
        return;
    }

    NSDictionary *userInfo = notification.userInfo;

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:[[userInfo valueForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
    [UIView setAnimationCurve:[[userInfo valueForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];

    // undo all that keyboardWillShow-magic
    // the scroll view will adjust its contentOffset apropriately
    _scrollView.contentInset = UIEdgeInsetsZero;
    _scrollView.scrollIndicatorInsets = UIEdgeInsetsZero;

    [UIView commitAnimations];
}

@Lucien 2013-06-06 12:40:11

Great improvements of @Shiun answer. But after keyboard is gone, the view do not back in the 1st position. It's still a great work :)

@xaphod 2017-06-02 20:41:06

Thanks, this is the best solution for me in 2017. Note that you don't need to track the focusedControl yourself, you can determine that with UIApplication.shared.sendAction(...). Here's the Swift 3 version of your answer (minus willHide portion), with the sendAction implemented: gist.github.com/xaphod/7aab1302004f6e933593a11ad8f5a72d

@Martin Ullrich 2017-06-25 16:33:43

@xaphod in my case I needed to focus more controls - e.g. a button below an input field. but yeah that code is now 4 years old and may benefit from improvements.

@xy uber.com 2019-01-26 17:42:09

This is probably the proper solution. Keyboard notification carries animation data, the text field delegations do not know about animation duration, it would just be a guess work.

@James Rochabrun 2017-03-27 21:22:40

For Swift Developer, using Swift 3, here is the repo https://github.com/jamesrochabrun/KeyboardWillShow

import UIKit

class ViewController: UIViewController {

    //1 Create a view that will hold your TEXTFIELD
    let textField: UITextField = {
        let tf = UITextField()
        tf.translatesAutoresizingMaskIntoConstraints = false
        tf.layer.borderColor = UIColor.darkGray.cgColor
        tf.layer.borderWidth = 3.0
        return tf
    }()
    //2 global variable that will hold the bottom constraint on changes
    var textfieldBottomAnchor: NSLayoutConstraint?

    override func viewDidLoad() {
        super.viewDidLoad()
        //3 add the view to your controller
        view.addSubview(textField)
        textField.heightAnchor.constraint(equalToConstant: 80).isActive = true
        textField.widthAnchor.constraint(equalToConstant: view.frame.width).isActive = true
        textField.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
        textfieldBottomAnchor = textField.bottomAnchor.constraint(equalTo: view.bottomAnchor)
        textfieldBottomAnchor?.isActive = true

        setUpKeyBoardObservers()
    }
    //4 Use NSnotificationCenter to monitor the keyboard updates
    func setUpKeyBoardObservers() {
        NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
    }

    //5 toggle the bottom layout global variable based on the keyboard's height
    func handleKeyboardWillShow(notification: NSNotification) {

        let keyboardFrame = notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? CGRect
        if let keyboardFrame = keyboardFrame {
            textfieldBottomAnchor?.constant = -keyboardFrame.height
        }
        let keyboardDuration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? Double
        if let keyboardDuration = keyboardDuration {
            UIView.animate(withDuration: keyboardDuration, animations: {
                self.view.layoutIfNeeded()
            })
        }
    }

    func handleKeyboardWillHide(notification: NSNotification) {

        textfieldBottomAnchor?.constant = 0
        let keyboardDuration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? Double
        if let keyboardDuration = keyboardDuration {
            UIView.animate(withDuration: keyboardDuration, animations: {
                self.view.layoutIfNeeded()
            })
        }
    }
    //6 remove the observers
    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)

        NotificationCenter.default.removeObserver(self)
    }
}

@Kakshil Shah 2017-03-06 08:28:23

Just add this to you pod file -> pod 'IQKeyboardManager'

Thats it, handles all of keyboard, and scrollviews and everything!

You dont need to code anything, could not find a better solution!

It has an extension, which handles textfields display, screen shifting, next and previous arrows if there are multiple text fields.

It also has a custom done button, which can be removed.

Link -> https://github.com/hackiftekhar/IQKeyboardManager

@Shruti Thombre 2018-10-10 05:35:56

I have used the same pod...and its really help me a lot..Thanks

@abhimuralidharan 2017-02-27 08:24:10

Swift 3.0 version of Apples keyboard management code is here: FloatingTF used in the code below is a Material design based textfield in iOS.

import UIKit
class SignupViewController: UIViewController, UITextFieldDelegate {

    //MARK: - IBOutlet:
@IBOutlet weak var emailTF: FloatingTF!
@IBOutlet weak var passwordTF: FloatingTF!
@IBOutlet weak var dobTF: FloatingTF!

@IBOutlet weak var scrollView: UIScrollView!

//MARK: - Variable:
var activeTextField: UITextField!

//MARK: - ViewController Lifecycle:
override func viewDidLoad() {
    super.viewDidLoad()        
    emailTF.delegate = self
    passwordTF.delegate = self
    dobTF.delegate = self 
}
override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    registerKeyboardNotifications()
}
override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)

   deRegisterKeyboardNotifications()
}

//MARK: - Keyboard notification observer Methods
fileprivate func registerKeyboardNotifications() {
    NotificationCenter.default.addObserver(self, selector: #selector(SignupViewController.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(SignupViewController.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
fileprivate func deRegisterKeyboardNotifications() {
    NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillShow, object: self.view.window)
    NotificationCenter.default.removeObserver(self, name: .UIKeyboardDidHide, object: self.view.window)
}
func keyboardWillShow(notification: NSNotification) {

    let info: NSDictionary = notification.userInfo! as NSDictionary
    let value: NSValue = info.value(forKey: UIKeyboardFrameBeginUserInfoKey) as! NSValue
    let keyboardSize: CGSize = value.cgRectValue.size
    let contentInsets: UIEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize.height, 0.0)
    scrollView.contentInset = contentInsets
    scrollView.scrollIndicatorInsets = contentInsets

    // If active text field is hidden by keyboard, scroll it so it's visible
    // Your app might not need or want this behavior.
    var aRect: CGRect = self.view.frame
    aRect.size.height -= keyboardSize.height
    let activeTextFieldRect: CGRect? = activeTextField?.frame
    let activeTextFieldOrigin: CGPoint? = activeTextFieldRect?.origin
    if (!aRect.contains(activeTextFieldOrigin!)) {
        scrollView.scrollRectToVisible(activeTextFieldRect!, animated:true)
    }    }

func keyboardWillHide(notification: NSNotification) {
    let contentInsets: UIEdgeInsets = .zero
    scrollView.contentInset = contentInsets
    scrollView.scrollIndicatorInsets = contentInsets
}

//MARK: - UITextField Delegate Methods
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    if textField == emailTF {
        passwordTF.becomeFirstResponder()
    }
    else if textField == passwordTF {
        dobTF.becomeFirstResponder()
    }
    else {
        self.view.endEditing(true)
    }
    return true
}

func textFieldDidBeginEditing(_ textField: UITextField) {
    activeTextField = textField
    scrollView.isScrollEnabled = true
}

func textFieldDidEndEditing(_ textField: UITextField) {
    activeTextField = nil
    scrollView.isScrollEnabled = false
}
}

@Emre Gürses 2017-02-17 13:36:28

i am late a little bit. You should add scrollView on your viewController.

You must be implement below 2 method.

TextField delegate method.

    - (void)textFieldDidBeginEditing:(UIView *)textField {
    [self scrollViewForTextField:reEnterPINTextField];
}

And then call the below methon in delegate method.

 - (void)scrollViewForTextField:(UIView *)textField {
    NSInteger keyboardHeight = KEYBOARD_HEIGHT;

    if ([textField UITextField.class]) {
        keyboardHeight += ((UITextField *)textField).keyboardControl.activeField.inputAccessoryView.frame.size.height;
    } 

    CGRect screenFrame = [UIScreen mainScreen].bounds;
    CGRect aRect = (CGRect){0, 0, screenFrame.size.width, screenFrame.size.height - ([UIApplication sharedApplication].statusBarHidden ? 0 : [UIApplication sharedApplication].statusBarFrame.size.height)};
    aRect.size.height -= keyboardHeight;
    CGPoint relativeOrigin = [UIView getOriginRelativeToScreenBounds:textField];
    CGPoint bottomPointOfTextField = CGPointMake(relativeOrigin.x, relativeOrigin.y + textField.frame.size.height);

    if (!CGRectContainsPoint(aRect, bottomPointOfTextField) ) {
        CGPoint scrollPoint = CGPointMake(0.0, bottomPointOfTextField.y -aRect.size.height);
        [contentSlidingView setContentOffset:scrollPoint animated:YES];
    }
}

@HariKarthick 2016-11-18 07:44:29

Try this it's working perfectly:

if Firstnametxt.text == "" || Passwordtxt.text == "" || emailtxt.text == ""
    {
        if Firstnametxt.text == ""
        {
            Firstnametxt!.shake(10, withDelta: 5, speed: 0.05, shakeDirection: ShakeDirection.Horizontal)
            Firstnametxt.becomeFirstResponder()
        }
        else if Passwordtxt.text == ""
        {
            Passwordtxt!.shake(10, withDelta: 5, speed: 0.05, shakeDirection: ShakeDirection.Horizontal)
            Passwordtxt.becomeFirstResponder()
        }
        else if emailtxt.text == ""

        {

            emailtxt!.shake(10, withDelta: 5, speed: 0.05, shakeDirection: ShakeDirection.Horizontal)
            emailtxt.becomeFirstResponder()
        }

    }
    else
    {
        let isValidEmail:Bool = self.isValidEmail(emailtxt.text!)
        if isValidEmail == true
        {
                        }
        else
        {
            emailtxt!.shake(10, withDelta: 5, speed: 0.05, shakeDirection: ShakeDirection.Horizontal)
            emailtxt.becomeFirstResponder()

        }

    }

@EJoshuaS 2017-01-10 04:53:45

It's better to include some context/explanation with code as this makes the answer more useful for the OP and for future readers.

@seggy 2016-09-07 05:41:38

Set Scrollview in view

  - (void)textFieldDidBeginEditing:(UITextField *)textField
    {
     CGPoint point;
    if(textField == txtEmail){
      // -90 is for my you can change as per your postion
      point = CGPointMake(0, textField.frame.origin.y - 90);
    }
    else if (textField == txtContact){
      point = CGPointMake(0, textField.frame.origin.y - 90);
    }
      [scrollV setContentOffset:point animated:YES];
    }

@Robert Juz 2016-11-02 15:47:46

i had an issue with reseting to default main view while changing the text field or editing it's content (for example phone textfield and adding '-' sign, and view goes back covering textfields) i finnaly overcome this by using auto layout and changing constraints constant, not frame size or position in notification delegates functions, like this:

P.S. I'm not using scrollview just simple move view up, but it should work similar

func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
    if !keyboardIsShown{
        self.infoViewTopConstraint.constant -= keyboardSize.height
        self.infoViewBottomConstraint.constant += keyboardSize.height
        self.view.setNeedsLayout()
        self.view.layoutIfNeeded()
        keyboardIsShown = true
    }
}

func keyboardWillHide(notification: NSNotification) {
if keyboardIsShown {
    self.infoViewTopConstraint.constant += keyboardSize.height
    self.infoViewBottomConstraint.constant -= keyboardSize.height
    self.view.setNeedsLayout()
    self.view.layoutIfNeeded()
    keyboardIsShown = false
}

@User511 2016-10-27 06:01:41

Try IQKeyboard library.

This will automatically move the text field's up.

@Esha 2016-10-22 07:32:38

In iOS moving keyboard up and taking back for textfields in app is bit confusing and need to implement few methods for same. also you need to make delegate to textfield and take care of it. Code for it will repeat in every class where the text fields exist.

I prefer to use this Github control.

IQKeyboard

In which We do not need to do anything. -- just drag drop control to your project and build. -- It will do everything for your app.

Thanks

May be this will be useful.

@Moxarth 2017-06-29 13:04:50

this is exactly what i am looking for . thanks . i ll implement it right away .

@dreamBegin 2016-10-11 10:08:33

its simple:-

In TextFieldDidBeginEditing:-

self.view.frame=CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y-150, self.view.frame.size.width, self.view.frame.size.height);

In TextFieldShouldEndEditing:-

self.view.frame=CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y+150, self.view.frame.size.width, self.view.frame.size.height);

@Alp Altunel 2018-02-23 22:37:06

this worked perfectly on a xib file shown as popup view

Related Questions

Sponsored Content

22 Answered Questions

18 Answered Questions

[SOLVED] Move UIView up when the keyboard appears in iOS

35 Answered Questions

[SOLVED] iOS - Dismiss keyboard when touching outside of UITextField

1 Answered Questions

0 Answered Questions

6 Answered Questions

[SOLVED] UITextField: move view when keyboard appears

4 Answered Questions

[SOLVED] textFieldDidEndEditing moves the screen when not wanted

2 Answered Questions

[SOLVED] Textfield disappears behind keyboard when start editing

  • 2013-02-19 08:50:00
  • StackFlower
  • 1040 View
  • 1 Score
  • 2 Answer
  • Tags:   ios xamarin.ios

Sponsored Content