NeuroAgent

UITextField Auto-Scroll with Keyboard in iOS

Learn how to make UITextField automatically scroll up when keyboard appears in iOS. Complete guide with code examples for UIScrollView keyboard handling and text field centering.

Question

How can I make a UITextField automatically scroll up when the keyboard appears in iOS development? I have a UIView with UITextFields that bring up a keyboard, and I need to:

  1. Allow scrolling of the contents of the UIScrollView to see other text fields once the keyboard is brought up
  2. Automatically scroll up to center the active text field in the visible area

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, with minimal code.

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

I’ve tried implementing a solution by resizing the UIScrollView frame when the keyboard goes up and down:

objc
-(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.

NeuroAgent

To make a UITextField automatically scroll up when the keyboard appears in iOS development, you need to properly implement keyboard handling with UIScrollView. The key issue is that you need both a container UIView and a UIScrollView working together - the UIScrollView should be inside the UIView to enable proper scrolling behavior.

Contents

Understanding the View Hierarchy

You need a proper view hierarchy where the UIScrollView is embedded within your main UIView. Here’s the recommended structure:

UIView (main container from UITabBar)
└── UIScrollView
    └── UIView (content view)
        └── UITextFields and other UI elements

The UIScrollView provides the scrolling functionality, while its content view contains all your text fields and controls. The main UIView from your tab bar controller acts as the container.

Interface Builder Setup

  1. Add UIScrollView to your main view

    • Drag a UIScrollView onto your main view in Interface Builder
    • Add constraints: pin to all four sides of the superview with 0 spacing
  2. Add content view to UIScrollView

    • Drag a UIView inside the UIScrollView
    • Pin content view to all four sides of UIScrollView with 0 spacing
    • Set content view’s width to be equal to UIScrollView’s width
  3. Add UITextFields to content view

    • Add your text fields to the content view
    • Set proper constraints between text fields and content view edges
  4. Configure scroll view properties

    • Enable “Scrolling Enabled” in UIScrollView attributes
    • Set content size appropriately (usually equal to content view’s frame)

Programmatic Implementation

The most reliable approach involves using UITextField delegate methods to adjust the scroll view’s contentOffset. Here’s how to implement it:

objc
// In your view controller header
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
@property (weak, nonatomic) UITextField *activeTextField;

// In your view controller implementation
- (void)viewDidLoad {
    [super viewDidLoad];
    
    // Set up 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)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];
    
    // Set initial content size
    self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width, 
                                           self.contentContainerView.frame.size.height);
}

// UITextField delegate methods
- (void)textFieldDidBeginEditing:(UITextField *)textField {
    self.activeTextField = textField;
    
    // Calculate new content offset to center the text field
    CGPoint scrollPoint = CGPointMake(0, 
                                    textField.frame.origin.y - (self.scrollView.frame.size.height / 2) + (textField.frame.size.height / 2));
    
    [self.scrollView setContentOffset:scrollPoint animated:YES];
}

- (void)textFieldDidEndEditing:(UITextField *)textField {
    self.activeTextField = nil;
    
    // Return to original position
    [self.scrollView setContentOffset:CGPointMake(0, 0) animated:YES];
}

// Keyboard notification handlers
- (void)keyboardWillShow:(NSNotification *)notification {
    NSDictionary *userInfo = [notification userInfo];
    CGSize keyboardSize = [[userInfo objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
    
    // Adjust content inset
    self.scrollView.contentInset = UIEdgeInsetsMake(0, 0, keyboardSize.height, 0);
    self.scrollView.scrollIndicatorInsets = self.scrollView.contentInset;
    
    // If active text field is visible, scroll to it
    if (self.activeTextField) {
        [self scrollViewToVisible:self.activeTextField animated:YES];
    }
}

- (void)keyboardWillHide:(NSNotification *)notification {
    // Reset content inset
    self.scrollView.contentInset = UIEdgeInsetsZero;
    self.scrollView.scrollIndicatorInsets = UIEdgeInsetsZero;
}

// Helper method to scroll to specific view
- (void)scrollViewToVisible:(UIView *)view animated:(BOOL)animated {
    CGRect rect = [view convertRect:view.bounds toView:self.scrollView];
    [self.scrollView scrollRectToVisible:rect animated:animated];
}

Keyboard Notification Approach

For more robust keyboard handling, use keyboard notifications along with content offset adjustments:

objc
- (void)keyboardWillShow:(NSNotification *)notification {
    NSDictionary *userInfo = [notification userInfo];
    CGSize keyboardSize = [[userInfo objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
    NSTimeInterval animationDuration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    
    // Adjust scroll view content size
    UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize.height, 0.0);
    self.scrollView.contentInset = contentInsets;
    self.scrollView.scrollIndicatorInsets = contentInsets;
    
    // Scroll to active text field
    if (self.activeTextField) {
        CGRect textFieldRect = [self.activeTextField frame];
        [self.scrollView scrollRectToVisible:textFieldRect animated:YES];
    }
}

- (void)keyboardWillHide:(NSNotification *)notification {
    NSDictionary *userInfo = [notification userInfo];
    NSTimeInterval animationDuration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    
    // Reset scroll view
    self.scrollView.contentInset = UIEdgeInsetsZero;
    self.scrollView.scrollIndicatorInsets = UIEdgeInsetsZero;
    
    // Return to top
    [self.scrollView setContentOffset:CGPointZero animated:YES];
}

Auto Layout Solution

For Auto Layout compatibility, use this approach that calculates the proper position:

objc
- (void)textFieldDidBeginEditing:(UITextField *)textField {
    self.activeTextField = textField;
    
    // Calculate the position to center the text field above keyboard
    CGPoint contentOffset = CGPointMake(0, 
                                      [self.scrollView convertPoint:CGPointZero fromView:textField].y - 60);
    
    [self.scrollView setContentOffset:contentOffset animated:YES];
}

Complete Implementation Example

Here’s a complete solution that combines the best approaches:

objc
// In your view controller
@interface YourViewController () <UITextFieldDelegate>
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
@property (weak, nonatomic) UIView *contentContainerView;
@property (weak, nonatomic) UITextField *activeTextField;
@end

@implementation YourViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // Set up delegates
    for (UITextField *textField in self.textFields) {
        textField.delegate = self;
    }
    
    // Register 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)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];
    
    // Set content size
    self.scrollView.contentSize = CGSizeMake(self.scrollView.bounds.size.width, 
                                           self.contentContainerView.bounds.size.height);
}

#pragma mark - UITextField Delegate

- (void)textFieldDidBeginEditing:(UITextField *)textField {
    self.activeTextField = textField;
    
    // Calculate optimal scroll position
    [self adjustScrollViewForKeyboard:YES];
}

- (void)textFieldDidEndEditing:(UITextField *)textField {
    self.activeTextField = nil;
    
    // Reset scroll position
    [self adjustScrollViewForKeyboard:NO];
}

- (BOOL)textFieldShouldReturn:(UITextField *)textField {
    [textField resignFirstResponder];
    return YES;
}

#pragma mark - Keyboard Handling

- (void)adjustScrollViewForKeyboard:(BOOL)show {
    if (!self.activeTextField) return;
    
    CGRect textFieldRect = [self.activeTextField convertRect:self.activeTextField.bounds 
                                                     toView:self.scrollView.window];
    
    if (show) {
        // Scroll to make text field visible
        [self.scrollView scrollRectToVisible:textFieldRect animated:YES];
    } else {
        // Return to top
        [self.scrollView setContentOffset:CGPointZero animated:YES];
    }
}

- (void)keyboardWillShow:(NSNotification *)notification {
    NSDictionary *userInfo = [notification userInfo];
    CGSize keyboardSize = [[userInfo objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
    
    // Adjust content inset
    self.scrollView.contentInset = UIEdgeInsetsMake(0, 0, keyboardSize.height, 0);
    self.scrollView.scrollIndicatorInsets = self.scrollView.contentInset;
}

- (void)keyboardWillHide:(NSNotification *)notification {
    self.scrollView.contentInset = UIEdgeInsetsZero;
    self.scrollView.scrollIndicatorInsets = UIEdgeInsetsZero;
}

- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

@end

Troubleshooting Common Issues

Issue: Text fields still get hidden behind keyboard

  • Ensure you’re setting both contentInset and scrollIndicatorInsets
  • Check that your content view is properly sized within the scroll view

Issue: Scroll view doesn’t scroll properly

  • Verify that scrollEnabled is set to YES
  • Check that content size is larger than scroll view bounds
  • Ensure constraints are properly set in Interface Builder

Issue: Animation is choppy

  • Use the animation duration from keyboard notifications
  • Implement smooth transitions with animated:YES

Issue: Tab bar functionality affected

  • Make sure your main view controller handles tab bar navigation properly
  • The scroll view implementation shouldn’t interfere with tab bar functionality

The key is to combine proper view hierarchy setup with keyboard notifications and UITextField delegate methods to create a seamless user experience where text fields automatically become visible when the keyboard appears.

Sources

  1. iPhone - Keyboard Scroll on Active Text Field - Scrolling to Out of View? - Stack Overflow
  2. iOS - ScrollView and keyboard in Swift - Stack Overflow
  3. Autolayout for ScrollView + Keyboard Handling in iOS | by Andy Nguyen | Medium
  4. iOS - How can I make a UITextField move up when the keyboard is present - on starting to edit? - Stack Overflow
  5. iPhone - How to make a UIScrollView auto scroll when a UITextField becomes a first responder - Stack Overflow
  6. iPhone - How to move UIScrollView automatically to make UITextfield visible based on keyboard? - Stack Overflow
  7. Move view when keyboard is shown (guide)

Conclusion

Successfully implementing automatic scrolling for UITextField when the keyboard appears requires a combination of proper view hierarchy setup, keyboard notifications, and delegate methods. The key takeaways are:

  1. Use the correct view hierarchy: Your main UIView (from UITabBar) should contain a UIScrollView, which in turn contains a content view with your UITextFields.

  2. Implement keyboard notifications: Use UIKeyboardWillShowNotification and UIKeyboardWillHideNotification to adjust content insets and scroll indicators.

  3. Leverage UITextField delegate methods: Use textFieldDidBeginEditing: and textFieldDidEndEditing: to automatically scroll to and from the active text field.

  4. Set proper content offset: Calculate the optimal scroll position to center the active text field above the keyboard using setContentOffset:animated:.

  5. Combine Interface Builder with code: Set up the basic structure in Interface Builder but implement the scrolling logic programmatically for better control.

The solution provided addresses both your requirements: allowing scrolling to see other text fields once the keyboard appears, and automatically centering the active text field. This approach works seamlessly with UITabBar navigation and provides a smooth user experience.