我目前正在我的应用中实现聊天。这是一个非常简单的tableview,显示了作为消息的行。我有一个很大的问题,想知道如何对不同的键盘做出反应。
目前我在计算键盘时计算键盘的高度并将其添加为偏移量。我之前发过关于这个主题的问题,人们倾向于告诉我应该使用插图,但我无法使其工作。
我希望tableview的内容像iMessage或Whatsapp一样移动,消息在键盘上向上移动并返回。它适用于标准键盘,但一旦你切换到表情符号,它就会搞砸了。
我需要帮助才能找到解决方案,或者向我展示在tableviews中处理键盘的正确方法。
为了安全每个人的时间我创建了一个虚拟项目,它保存了我当前的聊天状态。我希望有人之前已经实现了这一点并且可以帮助我,因为我现在急需找到解决方案。 https://www.dropbox.com/s/bldknydjfrwknr9/chatOffset.zip?dl=0
也许偏移的方式是错误的,有人可以给我一个更好的解决方案吗?
答案 0 :(得分:3)
您应该实现此代码。请注意,这是在 Swift 2.3 中,但我已经在 Swift 3 上实现了此代码,并且它起作用我只是没有 Swift的副本3 代码现在。
// Tag your bottom Layout Constraint (probably the one at the bottom of your tableView which connects to the self.view or the one connected to your textField to the self.view)
@IBOutlet var bottomLayoutConstraint: NSLayoutConstraint!
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
// this code snippet will observe the showing of keyboard
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.keyboardWillShowNotification(_:)), name: UIKeyboardWillShowNotification, object: nil)
// this code snippet will observe the hiding of keyboard
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.keyboardWillHideNotification(_:)), name: UIKeyboardWillHideNotification, object: nil)
}
func keyboardWillShowNotification(notification: NSNotification) {
updateBottomLayoutConstraintWithNotification(notification)
}
func keyboardWillHideNotification(notification: NSNotification) {
updateBottomLayoutConstraintWithNotification(notification)
}
func updateBottomLayoutConstraintWithNotification(notification: NSNotification) {
let userInfo = notification.userInfo!
// get data from the userInfo
let animationDuration = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue
let keyboardEndFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue()
let convertedKeyboardEndFrame = view.convertRect(keyboardEndFrame, fromView: view.window)
let rawAnimationCurve = (notification.userInfo![UIKeyboardAnimationCurveUserInfoKey] as! NSNumber).unsignedIntValue << 16
let animationCurve = UIViewAnimationOptions(rawValue: UInt(rawAnimationCurve))
bottomLayoutConstraint.constant = CGRectGetMaxY(view.bounds) - CGRectGetMinY(convertedKeyboardEndFrame)
// animate the changes
UIView.animateWithDuration(animationDuration, delay: 0.0, options: [.BeginFromCurrentState, animationCurve], animations: {
self.view.layoutIfNeeded()
}, completion: nil)
}
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
// remove the observers so the code won't be called all the time
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
}
答案 1 :(得分:2)
感谢Zonily Jame
这是我在Xcode 9中将他的代码转换为Swift 3.2
{{1}}
答案 2 :(得分:0)
我遇到一个Zonily Jame和iCyberPaul的答案的问题。在关闭键盘时,我的表格视图(嵌入堆栈视图,底部约束到安全区域底部)在选项卡栏后面延伸。此修改版本仅将底部约束常量设置为0即可隐藏。此版本还提供了一个嵌入式处理程序。
用法:
HandlesKeyboard
子类(例如UIViewController
)中使用extension MyViewController: HandlesKeyboard { }
协议bottomConstraintForKeyboardHandling
@IBOutlet
。startHandlingKeyboardChanges()
或viewDidLoad
中的viewWillAppear
。stopHandlingKeyboardChanges()
,以将self
删除为观察者,并在deinit
或viewWillDisappear
中对其进行调用。import UIKit
protocol HandlesKeyboard where Self: UIViewController {
var bottomConstraintForKeyboardHandling: NSLayoutConstraint! { get }
func startHandlingKeyboardChanges()
func stopHandlingKeyboardChanges()
}
extension HandlesKeyboard {
/// Registers caller to start handling keyboard will show and will hide notifications
/// - Warning: Caller *must* implement `stopHandlingKeyboardChanges()` to unregister, e.g., in `deinit`
/// ```
/// func stopHandlingKeyboardChanges() {
/// NotificationCenter.default.removeObserver(self)
/// }
///
/// deinit {
/// stopHandlingKeyboardChanges()
/// }
/// ```
func startHandlingKeyboardChanges() {
NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillShowNotification, object: nil, queue: nil) { [weak self] in
self?.updateBottomConstraint(notification: $0)
}
NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillHideNotification, object: nil, queue: nil) { [weak self] in
self?.updateBottomConstraint(notification: $0)
}
}
// Intentionally not implemented to ensure caller unregisters
// func stopHandlingKeyboardChanges() {
// NotificationCenter.default.removeObserver(self)
// }
func updateBottomConstraint(notification: Notification) {
guard let userInfo = notification.userInfo,
let animationDuration = (userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue,
let keyboardEndFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue,
let rawAnimationCurve = (userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as? NSNumber)?.uint32Value
else { return }
if notification.name == UIResponder.keyboardWillHideNotification {
bottomConstraintForKeyboardHandling.constant = 0.0
} else {
bottomConstraintForKeyboardHandling.constant = view.bounds.maxY - view.convert(keyboardEndFrame, to: view.window).minY
}
let animationCurve = UIView.AnimationOptions(rawValue: UInt(rawAnimationCurve << 16))
UIView.animate(withDuration: animationDuration, delay: 0.0, options: [.beginFromCurrentState, animationCurve], animations: { [weak self] in
self?.view.layoutIfNeeded()
}, completion: nil)
}
}