Ios SWIFT:UIView随键盘向上移动,在初始移动后移动非常奇怪,不';不要再下来了

Ios SWIFT:UIView随键盘向上移动,在初始移动后移动非常奇怪,不';不要再下来了,ios,swift,keyboard,uitextfield,constraints,Ios,Swift,Keyboard,Uitextfield,Constraints,因此,我有一个UIView,当其中的文本字段正在编辑和关闭时,我想上下移动它(键盘显示和隐藏)。以下是我的键盘观察者和UIView的默认约束,都在viewDidLoad中: NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIWindow.keyboardWillShowNotification, object: nil) NotificationCente

因此,我有一个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, attribute: .bottom, 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()

     })
    }

}

约束[18]是我在viewDidLoad中创建的约束。当我第一次点击文本字段时,UIView会向上移动正确的数量。然后,当我输入第一个字符时,它再次向上移动相同的数量,现在接近屏幕顶部。当我关闭它时,它会向下移动到之前的高度(刚好高于键盘的高度,现在已关闭)。下次我编辑文本时,它会再次向上移动,但不会向上移动整个键盘。由于某些原因,高度会增加。当我退出时,它会下降到整个键盘高度。然后重复此操作,直到UIView从屏幕底部脱落。这个动作很奇怪,我不知道是什么问题。我只想让它随着键盘上下移动。有没有办法解决这个问题?谢谢

您做错了太多事情,我无法列出,所以我刚刚修复了您的项目并提出了请求。将拉取请求合并到您的回购协议中,您将看到它现在运行良好

为了记录在案,以下是你做错的一些主要事情:

  • 您在代码中将底部约束添加到蓝色视图中。但您已经在蓝色视图上设置了底部约束。因此,您现在有两个,其中一个的任何更改都将导致冲突。Xcode控制台非常清楚地告诉您这正在发生,但您忽略了它告诉您的内容

  • 您正在更改约束常数,但同时也在更改蓝色视图
    中心
    。这可能没有造成伤害,但毫无意义。如果使用约束来控制视图,则不能通过其
    中心来控制视图的位置;它们是对立的

  • 在显示和隐藏方法中,您检查了
    键盘框架BeginUserInfo
    。那是错误的。您要检查
    键盘FrameEndUserInfoKey
    。问题不在于键盘现在在哪里,而在于它移动完毕后会在哪里

  • 动画是错误的。不需要UIView动画;您已经在动画块中。只要调用
    layoutifneed
    ,动画就会随着键盘的移动而发生

  • 您谈论和访问约束的整个方式都是错误的。您使用了不正确的表达式
    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()
        }
    }
}
类ViewController:UIViewController{
@IBOutlet弱var sampleTextField:UITextField!
@IBOutlet弱var底部约束:NSLayoutConstraint!
变量原始常量:CGFloat=0
重写func viewDidLoad(){
super.viewDidLoad()
NotificationCenter.default.addObserver(self,选择器:#选择器(keyboardWillShow),名称:UIWindow.keyboardWillShowNotification,对象:nil)
NotificationCenter.default.addObserver(self,选择器:#选择器(keyboardWillHide),名称:UIWindow.keyboardWillHideNotification,对象:nil)
self.originalConstant=bottomConstraint.constant
}
覆盖函数touchesend(touchs:Set,带有事件:UIEvent?){
sampleTextField.endEditing(真)
}
}
扩展视图控制器{
@objc func键盘将显示(通知:NSNotification){
打印(“键盘显示”)
如果让keyboardSize=(notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey]作为?NSValue)?.cgRectValue{
self.bottomConstraint.constant+=键盘大小.高度+5
self.view.layoutifneed()
}
}
@objc func键盘将隐藏(通知:NSNotification){
打印(“键盘将隐藏”)
如果让keyboardSize=(notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey]作为?NSValue)?.cgRectValue{
self.bottomConstraint.constant=self.originalConstant
self.view.layoutifneed()
}
}
}

尽管如此,代码仍然是错误的,因为您没有考虑到当键盘已经显示时,您将收到
键盘将显示
通知的真实可能性。但是,我将此留给您以后的研究。

当文本字段即将被虚拟键盘遮挡时,如何移动界面是一个已确定解决方案的解决方案。我建议使用其中一种。这就是我正在尝试做的,我一直在研究解决方案,这个实现就是其中之一。我正在努力让它为我的项目工作,正如你所看到的,这给我带来了麻烦。很明显,这不是一个很好的解决方案你能理解为什么我的解决方案如此不可靠吗?当我读到它时,它看起来并没有那么糟糕,但它不起作用。我以前问过一个关于如何做这件事的问题,在他的回答中有人告诉我我做这件事的方式是错误的,所以他给了我一些解决方案。我的代码就是基于其中的一个。我已经看了很多,但我就是不能让它对我起作用——可能是我。:)当然,我最喜欢我自己的解决方案:好吧,非常感谢你的时间和努力。我感谢你的帮助。正如你所看到的,我对约束和观点非常陌生,哈哈。我是一个