Странная анимация при удалении элемента из UICollectionView, когда отображается UIContextMenu

Я использую UIContextMenuInteraction чтобы показать контекстное меню для UICollectionView следующее:

func collectiovnView(_ collectionView: UICollectionView, contextMenuConfigurationForItemAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? {
    return UIContextMenuConfiguration(identifier: nil, previewProvider: nil, actionProvider: { _ in
        let deleteAction = UIAction(title: "Delete", image: UIImage(systemName: "trash"), attributes: .destructive) { _ in
            self.deleteItem(at: indexPath)
        }
        return UIMenu(title: "Actions", children: [deleteAction])
    })
}

func deleteItem(at indexPath: IndexPath) {
    self.collectionView.performBatchUpdates({
        self.items.remove(at: indexPath.item)
        self.collectionView.deleteItems(at: [indexPath])
    })
}

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

Если я позвоню collectionView.deleteItems() пока контекстное меню не отображается, анимация удаления работает должным образом.

1 ответ

Решение

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

  1. Анимация удаления: при нажатии на элемент "Удалить"collectionView.deleteItems() вызывается, и указанный элемент коллекции удаляется с анимацией.
  2. Анимация закрытия меню: после нажатия на пункт меню контекстное меню также закрывается с другой анимацией, которая показывает удаленный элемент в течение доли секунды.

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

func deleteItem(at indexPath: IndexPath) {
    let delay = 0.4 // Seconds
    DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
        self.collectionView.performBatchUpdates({
            self.items.remove(at: indexPath.item)
            self.collectionView.deleteItems(at: [indexPath])
        })
    }
}

В 0.4 секунды - это самая короткая задержка, которая сработала для меня.

Другие вопросы по тегам