我正在使用聊天屏幕,其中有一个InputAccessoryView
用户输入消息,其中UICollectionView
包含聊天内容。
我想在用户在UICollectionView中发送最新的聊天消息时显示它。
问题是,当用户键入消息InputAccessoryView进入键盘,而UICollectionView退回到键盘时,最新消息不可见。
我想在出现键盘时将UICollectionView移至键盘高度。
我正在使用以下代码。
这将为键盘隐藏和显示事件注册观察者。
func handleKeyBoard(){
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}
@objc func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
var contentInset = self.collectionView?.contentInset
contentInset?.bottom = keyboardSize.height
self.collectionView?.contentInset = contentInset!
if self.messages.count > 0{
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: {
self.view.layoutIfNeeded()
}, completion: { (completed:Bool) in
let indexPath = IndexPath(item: self.messages.count - 1, section: 0)
self.collectionView?.scrollToItem(at: indexPath, at: .bottom, animated: true)
})
}
}
}
在上面的功能中,当键盘出现时,我得到的高度总是50,我不知道为什么可能是由于InputAccessoryView
引起的。
获得键盘高度后,我将InputAccessoryView
的高度再增加50,然后更改contentInset
的{{1}},并在动画完成时滚动到最后一条消息,该消息将滚动UICollectionViewController是它的最后一条消息。
但这没有发生。
这是我的默认UICollectionView UICollectionViewController
。
contentInset
之后
UIEdgeInsets(top: 8, left: 0, bottom: 52, right: 0)
contentInset变成这个。
var contentInset = self.collectionView?.contentInset
contentInset?.bottom = keyboardSize.height
self.collectionView?.contentInset = contentInset!
以下操作将在键盘隐藏后为集合视图设置默认插入
UIEdgeInsets(top: 8, left: 0, bottom: 52, right: 0)
谁能帮助我找到正确的方法来做到这一点。那将非常有帮助。 几乎所有聊天应用都具有此功能,当他们键入内容时,便可以在该聊天视图中看到新消息。
谢谢。
答案 0 :(得分:0)
最好的方法是将约束添加到collectionView和InputAccessoryView,以使collectionview的底部视图附加到附件视图,而附件视图附加到超级视图的底部。
下一步使.m文件中的底部空间的出口受到限制,并调用为scrollViewBottomSpace并添加以下代码。 约束将为您完成工作。
#pragma标记-键盘通知
- (void)addObservers
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
- (void)removeObservers
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}
#pragma mark - Keyboard notification handlers
- (void)keyboardWillShow:(NSNotification *)notification
{
if(_keyboardIsVisible) return;
CGFloat height = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height;
[UIView animateWithDuration:0.2 animations:^{
scrollViewBottomSpace.constant = height+40;
} completion:^(BOOL finished) {
}];
_keyboardIsVisible = YES;
}
- (void)keyboardWillHide:(NSNotification *)notification
{
if(!_keyboardIsVisible) return;
[UIView animateWithDuration:0.2 animations:^{
scrollViewBottomSpace.constant = 0;
} completion:^(BOOL finished) {
}];
_keyboardIsVisible = NO;
}
答案 1 :(得分:0)
这非常简单,如果您使用的是UICollectionViewController
,则无需自己管理contentInset
,只需让CollectionViewController
自行处理即可,是当“ textView”或“ textField”成为第一响应者或发送消息时向下滚动
要向下滚动collectionView
,只需使用此功能
func scrollToBottom() {
let numberOfSections = self.collectionView!.numberOfSections
if numberOfSections > 0 {
let numberOfRows = self.collectionView!.numberOfItems(inSection: numberOfSections - 1)
if numberOfRows > 0 {
let indexPath = IndexPath(row: numberOfRows-1, section: (numberOfSections-1))
self.collectionView!.scrollToItem(at: indexPath, at: .bottom, animated: true)
}
}
}
答案 2 :(得分:0)
在此thread,我已经回答了这个问题,问题出在UIKeyboardFrameBeginUserInfoKey
,而不是我使用的UIKeyboardFrameEndUserInfoKey