UICollectionView с пользовательским UICollectionViewFlowLayout scrollview отскакивает при добавлении ячеек - PullRequest
0 голосов
/ 17 марта 2020

У нас есть представление коллекции, которое отображает некоторую болтовню. Пользователи могут вставлять свои сообщения в коллекцию, нажимая кнопки

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

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

Мы прочесал весь код и не может понять, вызвали ли мы его, или нам не хватает какой-то настройки, чтобы предотвратить это

Мы используем пользовательский UICollectionViewFlowLayout и реализуем UICollectionViewDelegateFlowLayout sizeFor

enter image description here

extension PublicChatMessagesController: UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        guard indexPath.row < messages.count else {return CGSize.zero}
        let item = messages[indexPath.row]
        let maxWidth = collectionView.frame.width - 16 - 8 - ChatMessageView.labelHorizontalInsets

        var itemSize = item.attributedString.boundingRect(with: CGSize(width: maxWidth, height: CGFloat.greatestFiniteMagnitude), options: [.usesLineFragmentOrigin, .usesFontLeading], context: nil).size
        itemSize.width = ceil(itemSize.width + ChatMessageView.labelHorizontalInsets)
        itemSize.height = ceil(itemSize.height + ChatMessageView.labelVerticalInsets)
        return itemSize
    }
}

class ChatCollectionViewFlowLayout: UICollectionViewAlignedLayout {

    var shouldScrollToBottom = true

    required init?(coder: NSCoder) {
        super.init(coder: coder)
        scrollDirection = .vertical
        sectionInset = UIEdgeInsets(top: 0, left: 16, bottom: 16, right: 8)
        minimumLineSpacing = 6
        minimumInteritemSpacing = 6
    }

    override func prepare() {
        super.prepare()
        guard let collectionView = collectionView else { return }
        let topInset = sectionInset.top
        if (topInset != sectionInset.top), shouldScrollToBottom {
            collectionView.contentOffset.y -= 30
        }
        scrollToBottomIfNeeded(animated: true)
    }

    func scrollToBottomIfNeeded(animated: Bool) {
        guard let collectionView = collectionView, shouldScrollToBottom else { return }
        let offset = max(0, collectionViewContentSize.height - collectionView.frame.size.height)
        if offset != collectionView.contentOffset.y {
            collectionView.setContentOffset(CGPoint(x: 0, y: offset), animated: animated)
        }
    }

    override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
        return collectionView?.bounds.width != newBounds.width || collectionView?.bounds.height != newBounds.height
    }
}
...