У нас есть представление коллекции, которое отображает некоторую болтовню. Пользователи могут вставлять свои сообщения в коллекцию, нажимая кнопки
Мы ожидаем, что ячейки появятся слева направо, и если в них не осталось места строка должна создать новую строку
Это происходит, но обратите внимание на короткое мгновение, когда вся коллекция прокручивается вверх и назад, когда появляется второе сообщение подряд
Мы прочесал весь код и не может понять, вызвали ли мы его, или нам не хватает какой-то настройки, чтобы предотвратить это
Мы используем пользовательский UICollectionViewFlowLayout
и реализуем UICollectionViewDelegateFlowLayout
sizeFor
![enter image description here](https://i.stack.imgur.com/2b7Vo.gif)
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
}
}