Как реализовать перетаскивание клавиатуры вниз в виде прокрутки без клавиатурыDismissMode? - PullRequest
0 голосов
/ 04 февраля 2019

Я создал страницу комментариев с 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()
    })
}
...