Я создал страницу комментариев с UICollectionView
и InputAccessoryView
, которая отображает ячейки комментариев и textView (с кнопкой отправки) внизу.
Я хотел переместиться вверх по экрану, сохраняя текущие позиции ячеекпредставления коллекции, когда появляется клавиатура, без автоматической прокрутки к определенной ячейке.
Итак, я сделал это, изменив y
координату и top contentInset
представления коллекции, когда появляется уведомление keyboardWillShow
, и оно работает хорошокак я хотел.
Однако проблема возникла в свойстве keyboardDismissMode
, которое я дал .interactive
для перетаскивания клавиатуры вниз.Во время перетаскивания клавиатуры появляется белый промежуток между видом коллекции и клавиатурой.Кроме того, если при перетаскивании клавиатуру снова перетаскивают вверх, разрыв белого увеличивается, и экран останавливается.
Поэтому я реализовал вид снизу (текстовое представление + кнопка отправки внутри) как пользовательский вид вместо использования inputAccessoryView
.Чтобы избежать пропусков между видом коллекции и видом снизу, прикрепите нижнюю часть вида коллекции и верхнюю часть вида снизу с помощью автоматического макета.В настоящее время keyboardDismissMode
удален, потому что он перетаскивает только клавиатуру, а не вид снизу.
Вопрос в том, как реализовать перетаскивание клавиатуры вниз в виде прокрутки без клавиатурыDismissMode?
Реализация с inputAccessoryView
:
@objc private func keyboardWillChange(_ sender: NSNotification) {
guard commentsForPost.count > 0 else { return }
guard let keyboardBeginFrame = (sender.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue else { return }
guard let keyboardEndFrame = (sender.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue else { return }
guard !keyboardBeginFrame.equalTo(keyboardEndFrame) else { return }
switch sender.name {
case UIResponder.keyboardWillShowNotification:
self.collectionView.contentInset.top = keyboardEndFrame.height
self.collectionView.frame.origin.y -= keyboardEndFrame.height
case UIResponder.keyboardWillHideNotification:
self.collectionView.frame.origin.y = 0
self.collectionView.contentInset.top = 0
default: break
}
guard let duration = ((sender.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey]) as? NSNumber)?.doubleValue else { return }
UIView.animate(withDuration: duration, delay: 0, options: .curveEaseOut, animations: {
self.view.layoutIfNeeded()
})
collectionView.scrollIndicatorInsets = collectionView.contentInset
}
Реализация с пользовательским видом снизу:
@objc private func keyboardWillChange(_ sender: NSNotification) {
... // Most of the same.
switch sender.name {
case UIResponder.keyboardWillShowNotification:
collectionViewTopAnchor?.constant = -keyboardEndFrame.height
containerViewBottomAnchor?.constant = -keyboardEndFrame.height
// For removing a little gap.
if let lastCellAttributes = self.collectionView.layoutAttributesForItem(at: IndexPath(item: self.commentsForPost.count - 1, section: 0)) {
self.collectionView.contentInset.top += lastCellAttributes.frame.height * 2.5
self.collectionView.contentOffset.y += lastCellAttributes.frame.height
}
case UIResponder.keyboardWillHideNotification:
collectionViewTopAnchor?.constant = 0
containerViewBottomAnchor?.constant = 0
if let lastCellAttributes = self.collectionView.layoutAttributesForItem(at: IndexPath(item: self.commentsForPost.count - 1, section: 0)) {
self.collectionView.contentInset.top = 0
self.collectionView.contentOffset.y -= lastCellAttributes.frame.height
}
default: break
}
UIView.animate(withDuration: duration, delay: 0, options: .curveEaseOut, animations: {
self.view.layoutIfNeeded()
})
}