如何解决SWIFT:使用键盘向上移动的UIView,在初始移动后会非常奇怪地移动,不会回落
所以我有一个UIView,由于其中的文本字段正在编辑和关闭(键盘显示和隐藏),所以我想上下移动它。这是我的键盘观察器以及UIView的默认约束,都在viewDidLoad内部:
NotificationCenter.default.addObserver(self,selector: #selector(keyboardWillShow),name: UIWindow.keyboardWillShowNotification,object: nil)
NotificationCenter.default.addObserver(self,selector: #selector(keyboardWillHide),name: UIWindow.keyboardWillHideNotification,object: nil)
let radiusViewConstraint = NSLayoutConstraint(item: searchRadiusView!,attribute: .bottom,relatedBy: .equal,toItem: super.view,multiplier: 1.0,constant: -30.0)
以下是键盘功能:
@objc func keyboardWillShow(notification: NSNotification) {
print("keyboardWillShow")
if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
self.searchRadiusView.center.y += (-1 * keyboardSize.height)
view.constraints[18].constant += (-1 * keyboardSize.height)
UIView.animate(withDuration: 0.5,animations: {
self.view.layoutIfNeeded()
})
}
}
@objc func keyboardWillHide(notification: NSNotification){
print("keyboardWillHide")
if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
self.searchRadiusView.center.y += 1 * keyboardSize.height
view.constraints[18].constant -= (-1 * keyboardSize.height)
UIView.animate(withDuration: 0.5,animations: {
self.view.layoutIfNeeded()
})
}
}
constraints [18]是我在viewDidLoad中创建的约束。当我第一次点击文本字段时,UIView向上移动了正确的数量。然后,当我键入第一个字符时,它将再次向上移动相同的数量,并且现在位于屏幕顶部附近。当我关闭它时,它会向下移动到以前的高度(刚好高于现在已关闭的键盘高度)。下次我编辑文本时,它会再次向上移动,但由于某种原因,它不会移到完整的keyboard.height值上。当我解雇时,它会降低全键盘的高度。然后重复此操作,直到UIView脱离屏幕底部为止。这个运动是如此奇怪,我不知道问题出在哪里。我想要的只是让它可以通过键盘上下移动。任何想法如何解决这一问题?谢谢
解决方法
您做错了太多事情,我无法列出,因此我刚刚修复了您的项目并提出了请求请求。将拉取请求合并到您的仓库中,您会发现它现在可以正常工作。
仅作记录,以下是您做错的一些主要事情:
-
您已在代码中向蓝色视图添加了底部约束。但是您已经 在蓝色视图上有一个底部约束。因此,您现在拥有两个,并且其中之一的任何更改都将导致冲突。 Xcode控制台非常清楚地告诉您这正在发生,但是您忽略了它告诉您的内容。
-
您正在更改约束常数,但还更改了蓝色视图
center
。那可能不会造成任何伤害,但这毫无意义。如果要使用约束来约束视图的位置,则不能通过其center
来约束视图的位置;他们是相反的。 -
在显示和隐藏方法中,您检查了
keyboardFrameBeginUserInfoKey
。错了您要检查keyboardFrameEndUserInfoKey
。问题不是键盘现在在哪里,而是键盘在完成移动后将在哪里 。 -
动画错误。不需要UIView动画。您已经处于动画块中。只需调用
layoutIfNeeded
,动画就会随着键盘的移动而发生。 -
您所说的整个方式和访问约束都是错误的。您使用了错误的表达式
super.view
(您可能是指self.view
)。但更重要的是,您尝试通过说出self.constraints[2]
来访问所需的约束。这种事情在极端情况下是脆弱的。正确的方法是保留对实际约束(实例属性)的引用。在这种情况下,由于约束已经存在(在情节提要中),因此该引用可以是出口。
因此,话虽如此,这是我对您的代码的重写;这是所需的完整代码:
class ViewController: UIViewController {
@IBOutlet weak var sampleTextField: UITextField!
@IBOutlet weak var bottomConstraint: NSLayoutConstraint!
var originalConstant: CGFloat = 0
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self,selector: #selector(keyboardWillShow),name: UIWindow.keyboardWillShowNotification,object: nil)
NotificationCenter.default.addObserver(self,selector: #selector(keyboardWillHide),name: UIWindow.keyboardWillHideNotification,object: nil)
self.originalConstant = bottomConstraint.constant
}
override func touchesEnded(_ touches: Set<UITouch>,with event: UIEvent?) {
sampleTextField.endEditing(true)
}
}
extension ViewController {
@objc func keyboardWillShow(notification: NSNotification) {
print("keyboardWillShow")
if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
self.bottomConstraint.constant += keyboardSize.height + 5
self.view.layoutIfNeeded()
}
}
@objc func keyboardWillHide(notification: NSNotification){
print("keyboardWillHide")
if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
self.bottomConstraint.constant = self.originalConstant
self.view.layoutIfNeeded()
}
}
}
话虽如此,代码仍然是 错误,因为您没有考虑到非常有可能在键盘输入keyboardWillShow
通知的可能性已经显示。但是,我将其留给您以后进行调查。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。