Подтвердить что ты не робот

Отключение автоматической прокрутки UITableView при редактировании UITextField внутри UITableViewCell

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

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

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

4b9b3361

Ответ 1

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

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

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

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

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

Ответ 2

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

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

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

// Save the table view 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.

Ответ 3

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

- (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 будут видны, когда появится Keyboard.

Ответ 4

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

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

public func textViewShouldBeginEditing(textView: UITextView) -> Bool {            
  dispatch_async(dispatch_get_main_queue()) {
    tableViewController.tableView.scrollToRowAtIndexPath(self.indexPath!, atScrollPosition: UITableViewScrollPosition.Middle, animated: true)
  }
  return true
}

Ответ 5

К сожалению, переопределение -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];
}

Так как поведение автоматической прокрутки вызывается оповещениями show/hide уведомлений UIKeyboard, поэтому просто НЕ наблюдайте их.

Ответ 6

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

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

Ответ 7

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

Ответ 8

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

self.tableView.scrollEnabled = NO;

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