Я создаю представление мессенджера в приложении iOs (Swift) с помощью UICollectionView внутри UIViewController.Я черпаю вдохновение из MessageKit, и мне удалось все правильно настроить с помощью простой динамической высоты ячейки.Когда я скрываю клавиатуру, а нижняя вставка представления коллекции уменьшается, а представление коллекции прокручивается вниз, логически перетаскивает ячейки в представление сверху (прокручивает вниз).Я не уверен, что это как-то конфликтует с анимацией, скрывающей клавиатуру, но если это вызывает прокрутку представления коллекции, и поэтому отображаются ячейки, которых не было в представлении, они выглядят не прокрученными, а с какой-то странной анимацией макета.,Это происходит только тогда, когда скрывается клавиатура && collectionView внизу.Пожалуйста, проверьте gif:
ссылку на gif
Построение всего на UITableView сработало, но я стремлюсь к представлению коллекции из-за будущих функций.Я попытался использовать даже фиксированную высоту ячейки в CollectionViewFlowDelegate, но это имеет тот же эффект, что и динамически вычисляемые высоты.
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
Я устанавливаю вставку UICollectionView так же, как в MessageKit:
private func requiredScrollViewBottomInset(forKeyboardFrame keyboardFrame: CGRect) -> CGFloat {
let intersection = chatCollectionView.frame.intersection(keyboardFrame)
if intersection.isNull || (chatCollectionView.frame.maxY - intersection.maxY) > 0.001 {
messagesCollectionView.frame.maxY when dealing with undocked keyboards.
return max(0, additionalBottomInset - automaticallyAddedBottomInset)
} else {
return max(0, intersection.height + additionalBottomInset - automaticallyAddedBottomInset)
}
}
@objc private func handleKeyboardDidChangeState(_ notification: Notification) {
guard !isMessagesControllerBeingDismissed else { return }
guard let keyboardStartFrameInScreenCoords = notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? CGRect else { return }
guard !keyboardStartFrameInScreenCoords.isEmpty || UIDevice.current.userInterfaceIdiom != .pad else {
// WORKAROUND for what seems to be a bug in iPad's keyboard handling in iOS 11: we receive an extra spurious frame change
// notification when undocking the keyboard, with a zero starting frame and an incorrect end frame. The workaround is to
// ignore this notification.
return
}
guard let keyboardEndFrameInScreenCoords = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect else { return }
let keyboardEndFrame = view.convert(keyboardEndFrameInScreenCoords, from: view.window)
let newBottomInset = requiredScrollViewBottomInset(forKeyboardFrame: keyboardEndFrame)
let differenceOfBottomInset = newBottomInset - messageCollectionViewBottomInset
if maintainPositionOnKeyboardFrameChanged && differenceOfBottomInset >/*!=*/ 0 {
let contentOffset = CGPoint(x: chatCollectionView.contentOffset.x, y: chatCollectionView.contentOffset.y + differenceOfBottomInset)
chatCollectionView.setContentOffset(contentOffset, animated: false)
}
messageCollectionViewBottomInset = newBottomInset
}
internal func requiredInitialScrollViewBottomInset() -> CGFloat {
print("accessory view for initial bottom inset: \(inputAccessoryView)")
guard let inputAccessoryView = inputAccessoryView else { return 0 }
return max(0, inputAccessoryView.frame.height + additionalBottomInset - automaticallyAddedBottomInset)
}
Поскольку я не мог найти какую-либо связанную тему, касающуюся этой прокрутки при скрытии клавиатуры, я не уверен, является ли это проблемой reusableCell или конфликтом анимации?
EDIT
Таким образом, частичное решение состоит в том, чтобы сделать макет недействительным только в случае изменения ширины, это предотвратит его аннулирование клавиатурой при скрытии:
open override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
return collectionView?.bounds.width != newBounds.width
}
Но это также предотвратит аннулирование липких заголовков и, следовательно, их отставание в виде залипания.Я углубился в invalidationContext, поскольку это выглядело как потенциальное полное решение, хотя я получаю то же самое поведение.
open override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
invalidateLayout(with: invalidationContext(forBoundsChange: newBounds))
return collectionView?.bounds.width != newBounds.width
}
open override func invalidationContext(forBoundsChange newBounds: CGRect) -> UICollectionViewLayoutInvalidationContext {
let context = super.invalidationContext(forBoundsChange: newBounds)
guard let flowLayoutContext = context as? UICollectionViewFlowLayoutInvalidationContext else { return context }
let indexes: [IndexPath] = (collectionView?.indexPathsForVisibleSupplementaryElements(ofKind: UICollectionView.elementKindSectionHeader))!
print(indexes)
flowLayoutContext.invalidateSupplementaryElements(ofKind: UICollectionView.elementKindSectionHeader, at: indexes)
print(context.invalidatedSupplementaryIndexPaths)
return flowLayoutContext
}
Операторы печати четко указывают, что только заголовки недействительны, а для остальных я возвращаю false.Но он ведет себя точно так же, как в gif (см. Ссылку - к сожалению, у меня пока недостаточно высокая репутация, чтобы добавить ее прямо здесь).Спасибо за любые комментарии!