Как прокрутить только что вставленную строку, если она уже прокручена до нижней части таблицы? - PullRequest
0 голосов
/ 15 февраля 2020

Я создаю приложение, в котором строки, содержащие сообщения, вставляются в конец таблицы

messages.append(message)
let indexPath:IndexPath = IndexPath(row:(messages.count - 1), section:0)
tableView.insertRows(at: [indexPath], with: .none)

Затем я прокручиваю до нижней части таблицы

DispatchQueue.main.async {
    let indexPath = IndexPath(
        row: self.numberOfRows(inSection:  self.numberOfSections - 1) - 1,
        section: self.numberOfSections - 1)
    self.scrollToRow(at: indexPath, at: .bottom, animated: true)
}

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

Я пробовал несколько методов, таких как определить, полностью ли видна последняя ячейка { ссылка }, или определить при прокрутке до дна { ссылка }.

Однако моя проблема заключается в том, что scrollToRow устанавливает animated:true, если поступает новое сообщение, но предыдущее сообщение, которое пришло за доли секунды до этого, все еще прокручивается до scrollToRow, тогда автоматическая прокрутка до самого нового сообщения и последующих сообщений не происходит - например, последняя ячейка не будет полностью видна до тех пор, пока анимация не будет завершена, или обнаружение, если вы прокрутите ее до конца, будет ложным, пока анимация не будет завершена.

Можно ли как-нибудь обойти это без настройки animated: false?

1 Ответ

0 голосов
/ 15 февраля 2020

Что бы я сделал, это вставил строку в пакетную операцию, чтобы использовать ее обработчик завершения, который сериализует обновление пользовательского интерфейса. Затем я проверил бы, какие строки видны пользователю, и если последние две строки являются, я думаю, что пользователь находится достаточно близко к нижней части диалога, чтобы вызвать прокрутку вниз.

let lastRow = IndexPath(row: messages.count - 1, section: 0)

DispatchQueue.main.async {

    self.tableView.performBatchUpdates({
        self.tableView.insertRows(at: [lastRow], with: .bottom)
    }, completion: { (finished) in

        guard finished,
            let visiblePaths = self.tableView.indexPathsForVisibleRows else {
                return
        }

        if visiblePaths.contains([0, messages.count - 2]) || visiblePaths.contains([0, messages.count - 1]) { // last 2 rows are visible

            DispatchQueue.main.async {
                self.tableView.scrollToRow(at: lastRow, at: .bottom, animated: true)
            }

        }

    })

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...