UITableView прокрутите вниз, чтобы увидеть анимацию вставки

У меня есть UITableView, я добавляю строку с анимацией (используя insertRowsAtIndexPaths:withRowAnimation:). Все это хорошо, если таблица не длиннее экрана.

Если он больше экрана, я пытаюсь прокрутить его до нижней части, но он не работает так, как я хочу. Если я перейду к новой строке после ее добавления, я пропущу анимацию. Если я попытаюсь прокрутить до этого indexPath до того, как он будет добавлен, он выдает исключение (об этом не является допустимым indexPath)

Есть ли решение для этого, кроме добавления пустой строки?

Ответ 1

Да, есть решение без добавления пустой строки.

Примечание. В коде я считаю, что существует только 1 раздел, но много строк. Вы можете изменить код для управления несколькими разделами.

- (void)theMethodInWhichYouInsertARowInTheTableView
{
     //Add the object in the array which feeds the tableview
     NSString *newStringObject = @"New Object";
     [arrayWhichFeeds addObject:newStringObject];

     [myTableView beginUpdates]; 

     NSArray *paths = [NSArray arrayWithObject:[NSIndexPath indexPathForRow:([arrayWhichFeeds count] - 1) inSection:0]];
     [myTableView insertRowsAtIndexPaths:paths withRowAnimation:NO];

     [myTableView endUpdates];
     [myTableView reloadData];
     [myTableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:([arrayWhichFeeds count] - 1) inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:YES];   
}

Ответ 2

У меня была такая же проблема. Вот мое решение.

Сначала - Обновление источника данных

Второй -

NSIndexPath *path = [NSIndexPath indexPathForRow:([arrayWhichFeeds count] - 1 inSection:0]];
NSArray *paths = [NSArray arrayWithObject:path];
[myTableView insertRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationTop]; 
[myTableView scrollToRowAtIndexPath:path atScrollPosition:UITableViewScrollPositionBottom animated:YES];

* Обратите внимание, что это НЕ ОБНАРУЖЕН в код [tableView beginUpdades] и [tableView endUpdates]. Если вы это сделаете, это не будет работать по желанию.

Попробуйте, он должен анимироваться в новых строках снизу при прокрутке к ним.

Ответ 3

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

  • Добавить новый элемент во внутреннюю коллекцию dataSource.
  • Установите флаг в элементе, который указывает, что он "новый". Принудительное отображение ячейки, чтобы ничего не показывать, когда этот флаг установлен.
  • Немедленно вызовите tableView: reloadData:
  • Теперь новый элемент находится в этой таблице, но визуально будет пустым (из-за флага).
  • Убедитесь, что этот новый элемент виден с помощью tableView.indexPathsForVisibleRows.
  • Если элемент был на экране, немедленно переверните этот "новый" флаг в элементе dataSource на NO и вызовите tableView: reloadRowsAtIndexPaths с набором анимаций. Теперь он будет выглядеть так, как будто этот элемент был добавлен. (в этом случае вы закончите)
  • Если это не было на экране, прокрутите его в представлении с помощью tableView: scrollToRowAtIndexPath: но не сразу вызывайте reloadRowsAtIndexPath...
  • Обращайтесь с сообщением (void) scrollViewDidEndScrollingAnimation: и сделайте то же самое reloadRowsAtIndexPath с шага 6. Я подозреваю, что этот метод вызывается в любое время прокрутки, поэтому вам нужно будет определить, когда он вызвал с шага 7 и когда он вызывается, потому что пользователь прокручивается.

Я работал над этой техникой (и написал этот ответ), когда я начал разработку iOS, но это уже давно наработало.

Ответ 4

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

Ответ 5

В общем случае для прокрутки до нижней части:

NSIndexPath *scrollIndexPath = [NSIndexPath indexPathForRow:([self.table numberOfRowsInSection:([self.table numberOfSections] - 1)] - 1) inSection:([self.table numberOfSections] - 1)];
[self.table scrollToRowAtIndexPath:scrollIndexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];

Ответ 6

Это работает для меня. Вместо того, чтобы вставлять строку, я просто выделяю ее (вытесняя ее.) Принцип один и тот же.

if let definiteIndexPath = indexPathDelegate.getIndexPath(toDoItem) {
    UIView.animateWithDuration(0.5, delay: 0, options: UIViewAnimationOptions.CurveEaseInOut, animations: {

        self.tableView.scrollToRowAtIndexPath(definiteIndexPath, atScrollPosition: .Middle, animated: false)

        }, completion: {
            (finished: Bool) -> Void in

            // Once the scrolling is done fade the text out and back in.
            UIView.animateWithDuration(5, delay: 1, options: .Repeat | .Autoreverse, animations: {
                self.tableView.reloadRowsAtIndexPaths([definiteIndexPath], withRowAnimation: UITableViewRowAnimation.Fade)

                }, completion: nil)

    })

}

Ответ 7

  • Обновить источник данных
  • Вставить строку внизу
  • Прокрутите вниз

Пример:

YOUR_ARRAY.append("new string")    
tableView.insertRows(at: [IndexPath(row: YOUR_ARRAY.count-1, section: 0)], with: .automatic)
tableView.scrollToRow(at: IndexPath(row: YOUR_ARRAY.count-1, section: 0), at: UITableViewScrollPosition.bottom, animated: true)