Disabling automatic scrolling of UITableView when editing UITextField inside UITableViewCell

23,532

Solution 1

The autoscroll-behavior is located in the UITableViewController functionality.

To disable the automatic scrolling I found two ways:

  1. Use instead of the UITableViewController simply a UIViewController - set the datasource and delegate on your own.
  2. Override the viewWillAppear method and don't call [super viewWillAppear: animated]

With both solution you disable not only the Autoscroll, but also some other nice but not essential features, that are described in the overview of Apple´s class reference:

https://developer.apple.com/documentation/uikit/uitableviewcontroller

Solution 2

Define properties for your UITableViewController:

@property (nonatomic) BOOL scrollDisabled;
@property (nonatomic) CGFloat lastContentOffsetY;

Before you call becomeFirstResponder:

// Save the table view's y content offset 
lastContentOffsetY = tableViewController.tableView.contentOffset.y;
// Enable scrollDisabled
scrollDisabled = YES;

Add the following code to your table view controller:

-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    if (self.scrollDisabled) {
        [self.tableView setContentOffset:CGPointMake(0, lastContentOffsetY)];
    }
    ...
}

After you call resignFirstResponder, set scrollDisabled = NO.

Solution 3

You can do the following:

- (void)registerForKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillShow:)
                                                 name:UIKeyboardWillShowNotification object:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardDidShow:)
                                                 name:UIKeyboardDidShowNotification object:nil];
}

- (void)unregisterForKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidShowNotification object:nil];
}

- (void)keyboardWillShow:(NSNotification *)notification
{
    self.tableView.scrollEnabled = NO;
}

- (void)keyboardDidShow:(NSNotification *)notification
{
    double delayInSeconds = 0.3;
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
            self.tableView.scrollEnabled = YES;
    });
}

Then implement this UIScrollViewDelegate method

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    if (! self.tableView.scrollEnabled)
        [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];
}

!!! But be warned, that if the user taps in a location in the UITextField that will be covered by the Keyboard, then it won't scroll.

From my point of view, the best thing to do is to make sure that all the cells from top to then one with the UITextField included, will be visible when then Keyboard will show.

Solution 4

The best way is to subclass UITableView and then override setContentOffset(_ contentOffset: CGPoint, animated: Bool) and not to call super.setContentOffset(_ contentOffset: CGPoint, animated: Bool). In this method is where the view controller is doing the automatic scroll.

override func setContentOffset(_ contentOffset: CGPoint, animated: Bool)
{
    //Do nothing
}

Solution 5

You could disable the automatic content inset adjustment like so:

tableView.contentInsetAdjustmentBehavior = .never
Share:
23,532
animal_chin
Author by

animal_chin

Updated on July 09, 2022

Comments

  • animal_chin
    animal_chin almost 2 years

    I'm using custom UITableViewCells inside my UITableView. Each of these UITableViewCells is pretty high and contains a UITextField at the top.

    When a user taps the UITextField in order to edit it, a keyboard appears and the UITableView scrolls automatically so that the cell is at the top of the screen.

    The problem is that this scrolls the UITableView to the bottom of the UITableViewCell, not the top. When the UITableViewCell is high and edited the UITextField is at the top so you can't see the UITextField. I know how to scroll the UITableView programmatically, but I just don't know how to disable this automatic scrolling so that I can scroll the UITableView on my own. How can I do this?

  • animal_chin
    animal_chin over 12 years
    tried it yet, but it didn't work...scrollToTop doesn't handle this... thanks for answer anyway!
  • Kudit
    Kudit over 11 years
    This does not prevent the automatic scrolling the UITableViewController does when tapping on a text field within a UITableViewCell
  • Cocoadelica
    Cocoadelica over 11 years
    I had the same problem and solution 2 worked. I've tested this in iOS 5.0.0 and upwards and it holds so far (current release is 6.1.2). I can't vouch for it in 4 but hey, it's 2013, so we can probably say 5.0 is the lowest supported os right now.
  • meaning-matters
    meaning-matters over 10 years
    Problem with this is that the insets are not adapted to accommodate the keyboard, at least not in iOS 7.0.6. This means that more code will be needed to do this by hand: catching keyboard notifications, ... Ugly.
  • Fidel López
    Fidel López about 9 years
    Can't believe I didn't know about this till today.. I was having problems with TPKeyboardAvoiding.. Thanks!!
  • Nikolay Spassov
    Nikolay Spassov almost 9 years
    -scrollViewDidScroll: does indeed get called when automatic scrolling happens, this here is the best solution
  • pkc456
    pkc456 over 8 years
    Point no2 works on 9.1. Good answer @Dominic. Thanks
  • coolcool1994
    coolcool1994 almost 8 years
    Option 2 is so weird. I suddenly had the automatic scrolling disable, and I didn't have super view will appear thingy XDXDXD. How could that change everything LOL
  • ryanipete
    ryanipete over 7 years
    I wouldn't ever override viewWillAppear: without calling super. UITableViewController subclasses UIViewController, and Apple "requires" all UIViewController subclasses to call super. From the UIViewController documentation: "If you override this method, you must call super at some point in your implementation."
  • Pushpendra
    Pushpendra about 7 years
    i am using UITableViewController if i don't use supper.viewWillApper() function then my footer is not coming on the top of keyBoard what should i do for that Means i want to stop auto scrolling and want footer view on the top of keyboard while editing
  • Sophy Swicz
    Sophy Swicz almost 7 years
    This isn't a scrollview problem, is a tableViewController class. The correct answer was the override viewWilAppear
  • simonthumper
    simonthumper over 6 years
    is this still working for you? Can't get it working in iOS 11 / Xcode 9
  • Olle Lind
    Olle Lind over 4 years
    This was the correct answer for me for a UITableView with UITextView in the cells.
  • Felix Marianayagam
    Felix Marianayagam almost 4 years
    This won't work as the keyboard will obscure the cells beneath it.