Отключение автоматической прокрутки UITableView при редактировании UITextField внутри UITableViewCell - PullRequest
51 голосов
/ 09 марта 2012

Я использую пользовательские UITableViewCell s внутри моего UITableView. Каждый из этих UITableViewCell довольно высокий и содержит UITextField вверху.

Когда пользователь нажимает UITextField, чтобы редактировать его, появляется клавиатура, и UITableView автоматически прокручивается, так что ячейка находится в верхней части экрана.

Проблема в том, что это прокручивает UITableView к нижней части UITableViewCell, а не к вершине. Когда значение UITableViewCell высокое и отредактировано, UITextField находится сверху, поэтому вы не можете видеть UITextField. Я знаю, как прокручивать UITableView программно, но я просто не знаю, как отключить эту автоматическую прокрутку, чтобы я мог прокручивать UITableView самостоятельно. Как я могу это сделать?

Ответы [ 8 ]

66 голосов
/ 17 августа 2012

Поведение автопрокрутки находится в функциональности UITableViewController.

Чтобы отключить автоматическую прокрутку, я нашел два способа:

  1. Используйте вместо UITableViewController просто UIViewController - установите источник данных и делегируйте его самостоятельно.
  2. Переопределить метод viewWillAppear и не вызывать [super viewWillAppear: animated]

В обоих решениях вы отключаете не только автопрокрутку, но и некоторые другие приятные, но не важные функции, которые описаны в обзоре класса Apple:

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

8 голосов
/ 05 августа 2013

Определите свойства для вашего UITableViewController:

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

Перед вызовом becomeFirstResponder:

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

Добавьте следующий код в ваш контроллер табличного представления:

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

После того, как вы позвоните resignFirstResponder, установите scrollDisabled = NO.

4 голосов
/ 12 апреля 2013

Вы можете сделать следующее:

- (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;
    });
}

Затем реализуйте этот метод UIScrollViewDelegate

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

!!! Но имейте в виду, что если пользователь коснется места в UITextField, которое будет закрыто клавиатурой, оно не будет прокручиваться.

С моей точки зрения, лучше всего убедиться, что все ячейки сверху вниз с одной ячейкой с включенным UITextField будут видны, когда появится клавиатура.

1 голос
/ 15 декабря 2016

Лучший способ - создать подкласс UITableView, а затем переопределить setContentOffset(_ contentOffset: CGPoint, animated: Bool), а не вызывать super.setContentOffset(_ contentOffset: CGPoint, animated: Bool). В этом методе контроллер представления выполняет автоматическую прокрутку.

override func setContentOffset(_ contentOffset: CGPoint, animated: Bool)
{
    //Do nothing
}
1 голос
/ 03 апреля 2015

К сожалению, переопределение -viewWillAppear: у меня не работает в iOS 8.

Вот мое решение (как в реализации UITableViewController):

- (void)viewDidLoad {

[super viewDidLoad];

[[NSNotificationCenter defaultCenter] removeObserver:self.tableView name:UIKeyboardWillShowNotification object:nil];

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

Поскольку автопрокруткаповедение вызывается уведомлениями UIKeyboard о показе / скрытии, поэтому просто НЕ наблюдайте за ними.

1 голос
/ 28 февраля 2015

Для меня проблема была не столько в том, что он прокручивался, сколько в том, что текстовый вид редактировался с экрана.

Таким образом, вместо предотвращения прокрутки, я просто переназначаю табличное представление туда, куда я хочу, когда начинается редактирование, например:

public func textViewShouldBeginEditing(textView: UITextView) -> Bool {            
  dispatch_async(dispatch_get_main_queue()) {
    tableViewController.tableView.scrollToRowAtIndexPath(self.indexPath!, atScrollPosition: UITableViewScrollPosition.Middle, animated: true)
  }
  return true
}
0 голосов
/ 12 ноября 2012

Вы можете попробовать сделать следующее:

self.tableView.scrollEnabled = NO;

Это должно отключить просмотр прокрутки в представлении таблицы.

0 голосов
/ 10 марта 2012

Вы пытались установить для "scrollsToTop" - свойство tableview значение NO. По умолчанию это ДА.

...