Swift - 如何在键盘抬起时滚动 collectionView 的内容
Swift -How to scroll the collectionView's contents when the keyboard is raised
这不是关于在键盘升高和降低时升高 collectionView 的问题,这部分工作正常。这是关于collectionView里面的scrollView没有跟着上升的问题
我有一个固定在屏幕底部的视图,在该视图中我有一个 textView。固定到视图顶部的是固定到屏幕顶部的 collectionView
-top of viewController
collectionView
containerView that contains a textView
-bottom of viewController
当轻触 textView 的 textField 时,我使用一个通知来检测键盘何时上升和下降。它工作正常,因为 collectionView 像预期的那样上下移动。问题是 collectionView 的内容。如果 collectionView 的单元格在 collectionView 上升时填满屏幕,则 scrollVIew 不会随之上升,因此单元格位于键盘后面。下面2张图片。
发送键盘通知时,我尝试更改 collectionView 的 contentInset、scrollIndicatorInsets,并尝试滚动到最后一个单元格,但没有任何效果。单元格只是向上滚动了一点点。
@objc fileprivate func keyboardWillShow(notification: Notification) {
guard let keyboardDuration = notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double else { return }
guard let keyboardFrame: NSValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else { return }
let keyboardFrame = keyboardFrame.cgRectValue
let keyboardHeight = keyboardFrame.height
containerViewBottomAnchorConstraint?.isActive = false
containerViewBottomAnchorConstraint = containerView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -keyboardHeight)
containerViewBottomAnchorConstraint?.isActive = true
// I tried this
let item = tableData.count - 1
let indexPath = IndexPath(item: item, section: 0)
if !tableData.isEmpty {
collectionView.scrollToItem(at: indexPath, at: .bottom, animated: true)
}
// I tried this
let contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: -keyboardHeight, right: 0)
collectionView.contentInset = contentInsets
collectionView.scrollIndicatorInsets = contentInsets
UIView.animate(withDuration: keyboardDuration, animations: {
self.view.layoutIfNeeded()
}) { [weak self](_) in
self?.autoScrollToLastCell() // I tried this
}
}
@objc fileprivate func keyboardWillHide(notification: Notification) {
guard let keyboardDuration = notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double else { return }
containerViewBottomAnchorConstraint?.isActive = false
containerViewBottomAnchorConstraint = containerView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: 0)
containerViewBottomAnchorConstraint?.isActive = true
UIView.animate(withDuration: keyboardDuration, animations: {
self.view.layoutIfNeeded()
}) { [weak self](_) in
self?.autoScrollToLastCell()
}
}
func autoScrollToLastCell() {
let section = 0
let item = collectionView.numberOfItems(inSection: section) - 1
let index = IndexPath(item: item, section: section)
if item > 0 {
collectionView.scrollToItem(at: index, at: .bottom, animated: true)
}
}
键盘升起前
键盘升起后,collectionView 已启动,但其内容未启动
修复很简单,我所要做的就是将 collectionView 的内容插入设置为 UIEdgeInsets(top: 0, left: 0, bottom: 8, right: 0)
下面我将 bottom 参数设置为 8,这样看起来最后一个单元格的底部和 containerView 的顶部之间可以有填充
collectionView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 8, right: 0)
为清楚起见,设置 collectionView 的 contentInset
属性 是解决此问题的方法。这与8分无关。即使它是 0,0,0,0,它也能正常工作。 8分只是给appearance/preference的。这里没有使用任何“神奇数字”来解决任何问题。
这应该是公认的答案:
在键盘抬起时添加监听器:
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
然后添加这个函数:
@objc func handleKeyboardWillShow(notification: Notification) {
collectionView.scrollToItem(at: IndexPath(row: messagesList.count - 1, section: chatSection), at: .top, animated: false)
}
注意:如果您有多个部分,请更改 section
值
更改为 keyboardDidShow 可能会解决问题,因为 keyboardWillShow 在键盘出现时被调用。
NotificationCenter.default.addObserver(self, selector: #selector(keyboardDidShow), name: UIResponder.keyboardDidShowNotification, object: nil)
添加该功能将有助于将视图滚动到底部。
@objc func keyboardDidShow() {
self.collectionView.scrollToItem(at: [0, messageList.count - 1],
at: .bottom,
animated: false)
}
这不是关于在键盘升高和降低时升高 collectionView 的问题,这部分工作正常。这是关于collectionView里面的scrollView没有跟着上升的问题
我有一个固定在屏幕底部的视图,在该视图中我有一个 textView。固定到视图顶部的是固定到屏幕顶部的 collectionView
-top of viewController
collectionView
containerView that contains a textView
-bottom of viewController
当轻触 textView 的 textField 时,我使用一个通知来检测键盘何时上升和下降。它工作正常,因为 collectionView 像预期的那样上下移动。问题是 collectionView 的内容。如果 collectionView 的单元格在 collectionView 上升时填满屏幕,则 scrollVIew 不会随之上升,因此单元格位于键盘后面。下面2张图片。
发送键盘通知时,我尝试更改 collectionView 的 contentInset、scrollIndicatorInsets,并尝试滚动到最后一个单元格,但没有任何效果。单元格只是向上滚动了一点点。
@objc fileprivate func keyboardWillShow(notification: Notification) {
guard let keyboardDuration = notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double else { return }
guard let keyboardFrame: NSValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else { return }
let keyboardFrame = keyboardFrame.cgRectValue
let keyboardHeight = keyboardFrame.height
containerViewBottomAnchorConstraint?.isActive = false
containerViewBottomAnchorConstraint = containerView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -keyboardHeight)
containerViewBottomAnchorConstraint?.isActive = true
// I tried this
let item = tableData.count - 1
let indexPath = IndexPath(item: item, section: 0)
if !tableData.isEmpty {
collectionView.scrollToItem(at: indexPath, at: .bottom, animated: true)
}
// I tried this
let contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: -keyboardHeight, right: 0)
collectionView.contentInset = contentInsets
collectionView.scrollIndicatorInsets = contentInsets
UIView.animate(withDuration: keyboardDuration, animations: {
self.view.layoutIfNeeded()
}) { [weak self](_) in
self?.autoScrollToLastCell() // I tried this
}
}
@objc fileprivate func keyboardWillHide(notification: Notification) {
guard let keyboardDuration = notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double else { return }
containerViewBottomAnchorConstraint?.isActive = false
containerViewBottomAnchorConstraint = containerView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: 0)
containerViewBottomAnchorConstraint?.isActive = true
UIView.animate(withDuration: keyboardDuration, animations: {
self.view.layoutIfNeeded()
}) { [weak self](_) in
self?.autoScrollToLastCell()
}
}
func autoScrollToLastCell() {
let section = 0
let item = collectionView.numberOfItems(inSection: section) - 1
let index = IndexPath(item: item, section: section)
if item > 0 {
collectionView.scrollToItem(at: index, at: .bottom, animated: true)
}
}
键盘升起前
键盘升起后,collectionView 已启动,但其内容未启动
修复很简单,我所要做的就是将 collectionView 的内容插入设置为 UIEdgeInsets(top: 0, left: 0, bottom: 8, right: 0)
下面我将 bottom 参数设置为 8,这样看起来最后一个单元格的底部和 containerView 的顶部之间可以有填充
collectionView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 8, right: 0)
为清楚起见,设置 collectionView 的 contentInset
属性 是解决此问题的方法。这与8分无关。即使它是 0,0,0,0,它也能正常工作。 8分只是给appearance/preference的。这里没有使用任何“神奇数字”来解决任何问题。
这应该是公认的答案:
在键盘抬起时添加监听器:
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
然后添加这个函数:
@objc func handleKeyboardWillShow(notification: Notification) {
collectionView.scrollToItem(at: IndexPath(row: messagesList.count - 1, section: chatSection), at: .top, animated: false)
}
注意:如果您有多个部分,请更改 section
值
更改为 keyboardDidShow 可能会解决问题,因为 keyboardWillShow 在键盘出现时被调用。
NotificationCenter.default.addObserver(self, selector: #selector(keyboardDidShow), name: UIResponder.keyboardDidShowNotification, object: nil)
添加该功能将有助于将视图滚动到底部。
@objc func keyboardDidShow() {
self.collectionView.scrollToItem(at: [0, messageList.count - 1],
at: .bottom,
animated: false)
}