最近一个朋友做了一个类似于聊天室的界面, 但是遇到了发送消息后, 消息列表中并没有显示的问题, 刚开始也以为是数据源没有更新, 列表没有刷新等问题造成的, 但是在解决过程中发现并不是这么简单, 于是直接写了一个demo, 从头实现了一遍, 而本文主要是讲述其中两个事情: 键盘事件, 更新对话列表.
添加键盘事件通知
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(keyBoardWillShow), name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyBoardWillDiss), name: .UIKeyboardWillHide, object: nil)
}
收到通知, 触发方法:
注: 通过修改输入框所在的View与底部Safe Area.Bottom的距离实现页面与键盘的布局变化.
// MARK: - 通知
extension ChatRoomVC {
@objc func keyBoardWillShow(notification: NSNotification) {
let keyBoardCGRect = notification.userInfo?["UIKeyboardFrameEndUserInfoKey"] as? CGRect
let height = keyBoardCGRect?.height ?? 0
let duration = notification.userInfo?["UIKeyboardAnimationDurationUserInfoKey"] as? CGFloat
UIView.animate(withDuration: TimeInterval(duration ?? 0)) { [weak self] in
self?.bottomLayoutConstraint.constant = -height
self?.view.layoutIfNeeded()
}
tableView.scrollToRow(at: IndexPath(row: dataSourceArray.count - 1, section: 0), at: .bottom, animated: false)
}
@objc func keyBoardWillDiss(notification: NSNotification) {
let duration = notification.userInfo?["UIKeyboardAnimationDurationUserInfoKey"] as? CGFloat
UIView.animate(withDuration: TimeInterval(duration ?? 0)) { [weak self] in
self?.bottomLayoutConstraint.constant = 0
self?.view.layoutIfNeeded()
}
tableView.scrollToRow(at: IndexPath(row: dataSourceArray.count - 1, section: 0), at: .bottom, animated: false)
}
处理消息发送, 更新对话列表
注: 这里只是简单的直接修改了本地数据集合, 而实际开发中, 需要通过socket连接, 来完成数据的同步工作.
// MARK: - UITextFieldDelegate
extension ChatRoomVC: UITextFieldDelegate {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
dataSourceArray.append(textField.text ?? "")
let indexPath = IndexPath(row: dataSourceArray.count - 1, section: 0)
tableView.insertRows(at: [indexPath], with: .bottom)
tableView.scrollToRow(at: indexPath, at: .bottom, animated: true)
textField.text = nil
return true
}
}
以下是两个注意点: 当滑动列表或者点击了列表时, 需要回收键盘.
滑动列表时
// MARK: - UIScrollViewDelegate
extension ChatRoomVC: UIScrollViewDelegate {
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
textField.endEditing(true)
}
}
点击列表, 这里面有一个问题, 就是UIScrollView, UITableView, UICollectionView是不响应touch事件的, 也就是说只是简单的重写touch的方法是没有用的, 方法不会触发, 如果想让其响应touch事件, 需要下面的处理方法:
//MARK : - 处理UIScrollView类型不响应touch事件的问题
extension UITableView {
open override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
let view = super.hitTest(point, with: event)
self.viewController()?.view.endEditing(true)
if view != nil && view!.isKind(of: UITableView.self) {
return self
}else {
return view
}
}
}
// 重写touch触发的方法
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
textField.endEditing(true)
}
网友评论