我正在构建一个聊天应用。键盘出现时我必须移动文本字段。我使用以下代码执行此操作:
func keyboardWillShow(notification: NSNotification) {
if let userInfo = notification.userInfo {
if let keyboardSize = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
kbHeight = keyboardSize.height
self.animateTextField(true)
}
}
}
func keyboardWillHide(notification: NSNotification) {
self.animateTextField(false)
}
func animateTextField(up: Bool) {
var movement = (up ? -kbHeight : kbHeight)
UIView.animateWithDuration(0.3, animations: {
self.view.frame = CGRectOffset(self.view.frame, 0, movement)
})
}
但是当我使用此代码时,第一条消息不显示。我想我必须调整tableview的大小。
以下是屏幕截图之前和之后:
http://imgim.com/iossimulatorscreenshot7haz2015114958.png http://imgim.com/iossimulatorscreenshot7haz2015115000.png
我正在使用自动布局。
如何解决此问题?
答案 0 :(得分:15)
您可以创建表格视图底部自动布局约束的插座。
然后只需使用此代码:
func keyboardWillShow(sender: NSNotification) {
let info = sender.userInfo!
var keyboardSize = (info[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue.height
bottomConstraint.constant = keyboardSize - bottomLayoutGuide.length
let duration: TimeInterval = (info[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue
UIView.animate(withDuration: duration) { self.view.layoutIfNeeded() }
}
func keyboardWillHide(sender: NSNotification) {
let info = sender.userInfo!
let duration: TimeInterval = (info[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue
bottomConstraint.constant = 0
UIView.animate(withDuration: duration) { self.view.layoutIfNeeded() }
}
如果您在创建底部约束时遇到问题:
在故事板中
|-[]-|
。现在您可以将其拖动到视图控制器并将其添加为插座。
另一种解决方案是设置tableView.contentInset.bottom
。但我以前没有这样做过。如果您愿意,我可以尝试解释一下。
使用inset:
func keyboardWillShow(sender: NSNotification) {
let info = sender.userInfo!
let keyboardSize = (info[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue.height
tableView.contentInset.bottom = keyboardSize
}
func keyboardWillHide(sender: NSNotification) {
tableView.contentInset.bottom = 0
}
您可以尝试使用此代码设置插图。我自己还没试过,但它应该是那样的。
编辑:根据nacho4d
的建议更改持续时间答案 1 :(得分:11)
基于Eendje的概念.........
1)将KUIViewController复制并粘贴到您的项目中,
2)创建约束 - 它只是您内容的“底部约束”
3)不要忘记简单地将约束ID拖到bottomConstraintForKeyboard
那么“你应该调整哪个视图?”
注意,您可以不使用.view
- 视图控制器的主视图 - 遗憾的是,您无法在iOS中调整.view
的大小!
因此,只需将UIView命名为“holder”。
它位于.view
内。
将你的一切都放在持有人手中。
持有人当然会对.view
上下/左/右四个简单约束。
这里的“持有人”的底部约束确实是bottomConstraintForKeyboard
。
(当然,通常情况下,当kayboard到达时,你想要“一切”压扁。在不寻常的情况下,你可能更喜欢让其他特定的东西向上移动,剩下的就是其余的。如果你想这样做,在使用KUIViewController
方法时你有足够的灵活性。你可以将约束附加到你想要的任何东西。当然,几乎总是它只是“整个屏幕” - 因此只是有一个包含所有东西的“持有者”,并附加那个。)
通常在现代用户体验中,如果你点击“背景”(所以:远离任何按钮,输入字段等),它应该关闭键盘。
KUIViewController
类完全自动化了这种需求。你什么都不做,这是自动的。
class KUIViewController: UIViewController {
@IBOutlet var bottomConstraintForKeyboard: NSLayoutConstraint!
func keyboardWillShow(sender: NSNotification) {
let i = sender.userInfo!
let k = (i[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue.height
bottomConstraintForKeyboard.constant = k - bottomLayoutGuide.length
let s: TimeInterval = (i[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue
UIView.animate(withDuration: s) { self.view.layoutIfNeeded() }
}
func keyboardWillHide(sender: NSNotification) {
let info = sender.userInfo!
let s: TimeInterval = (info[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue
bottomConstraintForKeyboard.constant = 0
UIView.animate(withDuration: s) { self.view.layoutIfNeeded() }
}
func keyboardNotifications() {
NotificationCenter.default.addObserver(self,
selector: #selector(keyboardWillShow),
name: Notification.Name.UIKeyboardWillShow,
object: nil)
NotificationCenter.default.addObserver(self,
selector: #selector(keyboardWillHide),
name: Notification.Name.UIKeyboardWillHide,
object: nil)
}
func clearKeyboard() {
view.endEditing(true)
}
override func viewDidLoad() {
super.viewDidLoad()
keyboardNotifications()
let t = UITapGestureRecognizer(target: self, action: #selector(clearKeyboard))
view.addGestureRecognizer(t)
t.cancelsTouchesInView = false
}
}
你可以
class AddCustomer: KUIViewController, SomeProtocol {
class CustomerPicker: KUIViewController {
在这些屏幕上:
当键盘在那里时,页面(您的。holder
视图)会自动调整大小以允许键盘。它会很好地制作动画。
当用户点击“关闭”(点击“背景”)时,它会关闭键盘。
详细信息 - (不幸的是)点击您的内容也会关闭键盘。 (他们都得到了这个活动。)然而:确实,这几乎总是正常的Apple风格的正确行为:试一试。没有简单的方法可以避免这种情况。请务必阅读@iPruch答案以获取示例。
答案 2 :(得分:2)
来自@Fattie的消息:
详细信息 - (不幸的是)点击您的内容也会关闭键盘。 (他们都得到了这个事件。)然而,这几乎总是正确的行为;试试看。没有理由避免这种情况,所以不要理会它并使用Apple-flow。
这可以通过实施以下 UIGestureRecognizerDelegate 的方法来解决:
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
return !(touch.view?.isKind(of: UIControl.self) ?? true)
}
这样,如果用户触摸任何UIControl
(UIButton,UITextField等),手势识别器将不会调用clearKeyboard()
方法。
为此,请记住在类定义或扩展名中继承UIGestureRecognizerDelegate。然后,在viewDidLoad()中,您应该将手势识别器委托指定为self。
准备复制并粘贴代码:
// 1. Subclass UIGestureRecognizerDelegate
class KUIViewController: UIViewController, UIGestureRecognizerDelegate {
@IBOutlet var bottomConstraintForKeyboard: NSLayoutConstraint!
func keyboardWillShow(sender: NSNotification) {
let i = sender.userInfo!
let k = (i[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue.height
bottomConstraintForKeyboard.constant = k - bottomLayoutGuide.length
let s: TimeInterval = (i[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue
UIView.animate(withDuration: s) { self.view.layoutIfNeeded() }
}
func keyboardWillHide(sender: NSNotification) {
let info = sender.userInfo!
let s: TimeInterval = (info[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue
bottomConstraintForKeyboard.constant = 0
UIView.animate(withDuration: s) { self.view.layoutIfNeeded() }
}
func keyboardNotifications() {
NotificationCenter.default.addObserver(self,
selector: #selector(keyboardWillShow),
name: Notification.Name.UIKeyboardWillShow,
object: nil)
NotificationCenter.default.addObserver(self,
selector: #selector(keyboardWillHide),
name: Notification.Name.UIKeyboardWillHide,
object: nil)
}
func clearKeyboard() {
view.endEditing(true)
}
override func viewDidLoad() {
super.viewDidLoad()
keyboardNotifications()
let t = UITapGestureRecognizer(target: self, action: #selector(clearKeyboard))
view.addGestureRecognizer(t)
t.cancelsTouchesInView = false
// 2. Set the gesture recognizer's delegate as self
t.delegate = self
}
// 3. Implement this method from UIGestureRecognizerDelegate
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
return !(touch.view?.isKind(of: UIControl.self) ?? true)
}
}
答案 3 :(得分:1)
如果您不想自己与之抗争,可能会发现TPKeyboardAvoiding框架很有用
只需按照“安装说明”进行操作即可。即将适当的.h / .m文件拖放到项目中,然后让ScrollView / TableView成为如下的子类:
答案 4 :(得分:1)
也许会帮助别人。 您完全可以完全不用界面构建器来实现所需的行为
首先,您将需要创建约束并计算安全区域插入量,以正确支持无按钮设备
var container: UIView!
var bottomConstraint: NSLayoutConstraint!
let safeInsets = UIApplication.shared.windows[0].safeAreaInsets
然后将其初始化为代码中的某个地方
container = UIView()
bottomConstraint = container.bottomAnchor.constraint(equalTo: view.bottomAnchor)
附加它以查看和激活
view.addSubview(container)
NSLayoutConstraint.activate([
...
container.leadingAnchor.constraint(equalTo: view.leadingAnchor),
container.trailingAnchor.constraint(equalTo: view.trailingAnchor),
container.topAnchor.constraint(equalTo: view.topAnchor),
bottomConstraint,
...
])
最后
@objc func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
if bottomConstraint.constant == 0 {
bottomConstraint.constant = -keyboardSize.height + safeInsets.bottom
view.layoutIfNeeded()
}
}
}
@objc func keyboardWillHide(notification: NSNotification) {
bottomConstraint.constant = 0
view.layoutIfNeeded()
}
如果您的视图是可滚动的,并且您想使用键盘将其向上移动并在键盘隐藏时返回到初始位置,则可以更改视图的contentOffset
view.contentOffset = CGPoint(x: view.contentOffset.x, y: view.contentOffset.y + keyboardSize.height - safeInsets.bottom)
用于向上滚动,
view.contentOffset = CGPoint(x: view.contentOffset.x, y: view.contentOffset.y - keyboardSize.height + safeInsets.bottom)
将其下移