How to make a UIScrollView auto scroll when a UITextField becomes a first responder

46,225

Solution 1

I hope this example will help you You can scroll to any point by this code.

scrollView.contentOffset = CGPointMake(0,0);

So if you have textfield, it must have some x,y position on view, so you can use

CGPoint point = textfield.frame.origin ;
scrollView.contentOffset = point 

This should do the trick,

But if you don't know when to call this code, so you should learn UITextFieldDelegate methods

Implement this method in your code

- (void)textFieldDidBeginEditing:(UITextField *)textField {
// Place Scroll Code here
}

I hope you know how to use delegate methods.

Solution 2

I know this question has already been answered, but I thought I would share the code combination that I used from @Adeel and @Basil answer, as it seems to work perfectly for me on iOS 9.

-(void)textFieldDidBeginEditing:(UITextField *)textField {

    // Scroll to the text field so that it is
    // not hidden by the keyboard during editing.
    [scroll setContentOffset:CGPointMake(0, (textField.superview.frame.origin.y + (textField.frame.origin.y))) animated:YES];
}

-(void)textFieldDidEndEditing:(UITextField *)textField {

    // Remove any content offset from the scroll
    // view otherwise the scroll view will look odd.
    [scroll setContentOffset:CGPointMake(0, 0) animated:YES];
}

I also used the animated method, it makes for a much smoother transition.

Solution 3

Here is the Swift 4 update to @Supertecnoboff's answer. It worked great for me.

func textFieldDidBeginEditing(_ textField: UITextField) {
    scroll.setContentOffset(CGPoint(x: 0, y: (textField.superview?.frame.origin.y)!), animated: true)
}

func textFieldDidEndEditing(_ textField: UITextField) {
    scroll.setContentOffset(CGPoint(x: 0, y: 0), animated: true)
}

Make sure to extend UITextFieldDelegate and set the textfields' delegate to self.

Solution 4

There is nothing you have to do manually. It is the default behavior. There are two possibilities as to why you are not seeing the behavior

  1. The most likely reason is that the keyboard is covering your UITextField. See below for solution
  2. The other possibility is that you have another UIScrollView somewhere in the view hierarchy between the UITextField and the UIScrollView that you want to auto scroll. This is less likely but can still cause problems.

For #1, you want to implement something similar to Apple's recommendations for Moving Content That Is Located Under the Keyboard. Note that the code provided by Apple does not account for rotation. For improvements on their code, check out this blog post's implementation of the keyboardDidShow method that properly translates the keyboard's frame using the window.

Solution 5

- (void)textFieldDidBeginEditing:(UITextField *)textField {
    CGRect rect = [textField bounds];
    rect = [textField convertRect:rect toView:self.scrollView];
    rect.origin.x = 0 ;
    rect.origin.y -= 60 ;
    rect.size.height = 400;

    [self.scrollView scrollRectToVisible:rect animated:YES];
}
Share:
46,225
Nosrettap
Author by

Nosrettap

I recently graduated from Duke University as a computer science and economics double major. I am now working full time as a software developer. I am proficient in Objective-C and Java, and I know (to some degree) C, C++, Python, Perl, SML, Assembly, HTML, CSS, JavaScript.

Updated on February 16, 2022

Comments

  • Nosrettap
    Nosrettap over 2 years

    I've seen posts around here that suggest that UIScrollViews should automatically scroll if a subview UITextField becomes the first responder; however, I can't figure out how to get this to work.

    What I have is a UIViewController that has a UIScrollView and within the UIScrollView there are multiple textfields.

    I know how to do this manually if necessary; however, from what I've been reading, it seems possible to have it autoscroll. Help please.

  • onegray
    onegray over 11 years
    The question is how to make auto scroll, but not how to implement it manually.
  • ChrisBorg
    ChrisBorg over 10 years
    I would use [self.scrollView setContentOffset:point animated:YES] to make the transition nice and smooth :)
  • George
    George about 9 years
    It's a bad idea to use 216.0 as a constant for keyboard height
  • Supertecnoboff
    Supertecnoboff over 8 years
    @ChrisBorg iOS 7 and upwards don't seem to actually scroll when doing that. So that doesn't really achieve the desired effect.
  • Supertecnoboff
    Supertecnoboff over 8 years
    Do [scroll setContentOffset:CGPointMake(0, point.y) animated:YES]; to get the scroll view to animate the offset.
  • Supertecnoboff
    Supertecnoboff over 8 years
    @AdeelPervaiz There is still one problem though. What if you have set the scroll view to only scroll a short distance? Then this won't work because it can't scroll right? For example [scroll setContentSize:CGSizeMake(320, 690)]; Well if point.y is greater than 690, then it won't work???
  • Supertecnoboff
    Supertecnoboff over 8 years
    Why would you bother with textField1/2/3.. etc?? If you are using one of the delegate methods like textFieldDidBeginEditing:(UITextField *)textField then you just use textField.
  • Supertecnoboff
    Supertecnoboff over 8 years
    @George Agreed, especially how we have custom keyboards in iOS these days.
  • Adeel Pervaiz
    Adeel Pervaiz over 8 years
    @Supertecnoboff What are you trying to reproduce, A glitch in IOS ?
  • Scooter
    Scooter over 8 years
    Works perfectly for me. Thanks! I wasted a ton of time trying to get a solution working based on the keyBoard appearing, and then searching for which UITextView triggered it. This solution avoids that search.
  • Jonathan Cabrera
    Jonathan Cabrera almost 6 years
    I found that with this solution, if the UITextField is in a scroll view and you scroll, it will reset the contentOffset to the default, basically hiding the text field back behind the keyboard.
  • Rob
    Rob over 5 years
    This is so much easier than the convoluted bs I was doing before.
  • jsadler
    jsadler over 3 years
    This could also be happening if the constraints determining the scroll view's content size are ambiguous. Since my scroll view scrolls only vertically, the only constraints I set up for the scroll view's contentLayoutGuide were for the topAnchor and bottomAnchor. Adding constraints for the leading and trailing anchors made the content size fully non-ambiguous and solved the problem for me.
  • shadow of arman
    shadow of arman about 3 years
    Wont this be inefficient performance wise? Since it is going through all the subviews to find the first responder?
  • liudasbar
    liudasbar over 2 years
    Confirming. Works great with Swift 5 in my project.