Ios 如何将底部视图移动到键盘顶部

Ios 如何将底部视图移动到键盘顶部,ios,Ios,嗨,我正在尝试使视图的底部与键盘的顶部对齐 更新1:我已经创建了一个github项目,如果您想尝试一下: 注意:我需要的aView是动态的 更新2:刚刚按下-使用帧包括 我可能已经看这个太久了,我不能把我的大脑围绕在它上面:-) 你知道怎么做吗 我如何知道UIC键盘是在向下还是向上 如果UIKeyboard是向上的,那么如何将其与视图对齐(attachKeyboardToFrame-请参阅代码) 我发现以下UIView扩展: import UIKit extension UIView {

嗨,我正在尝试使视图的底部与键盘的顶部对齐

更新1:我已经创建了一个github项目,如果您想尝试一下:

注意:我需要的aView是动态的

更新2:刚刚按下-使用帧包括

我可能已经看这个太久了,我不能把我的大脑围绕在它上面:-)

你知道怎么做吗

  • 我如何知道UIC键盘是在向下还是向上

  • 如果UIKeyboard是向上的,那么如何将其与视图对齐(attachKeyboardToFrame-请参阅代码)

  • 我发现以下UIView扩展:

    import UIKit
    
    extension UIView {
    
        func bindToKeyboard(){
            NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChange), name: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil)
        }
    
        func unbindFromKeyboard(){
            NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil)
        }
    
        @objc
        func keyboardWillChange(notification: NSNotification) {
    
            guard let userInfo = notification.userInfo else { return }
    
            let duration = userInfo[UIKeyboardAnimationDurationUserInfoKey] as! Double
            let curve = userInfo[UIKeyboardAnimationCurveUserInfoKey] as! UInt
            let curFrame = (userInfo[UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
            let targetFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
    
            // To get the total height of view
            let topView = UIApplication.shared.windows.last
            //
            let attachKeyboardToFrame = Singleton.sharedInstance.attachKeyboardToFrame
            let global_attachKeyboardToFrame = self.superview?.convert(attachKeyboardToFrame!, to: topView)
    
            if (targetFrame.height + attachKeyboardToFrame!.height) > (topView?.frame.height)! {
                self.frame.origin.y = -targetFrame.origin.y
            }else{
    
            }
    
        }
    }
    

    您可以使用以下自动布局解决方案来实现它

    首先,您需要使用模拟键盘感知的底部锚定的
    UILayoutGuide
    ,以及控制此布局指南的
    NSLayoutConstraint

    fileprivate let keyboardAwareBottomLayoutGuide: UILayoutGuide = UILayoutGuide()
    fileprivate var keyboardTopAnchorConstraint: NSLayoutConstraint!
    
    viewdiload
    中,将
    键盘awarebottomlayoutGuide
    添加到视图中,并设置适当的约束:

    self.view.addLayoutGuide(self.keyboardAwareBottomLayoutGuide)
    // this will control keyboardAwareBottomLayoutGuide.topAnchor to be so far from bottom of the bottom as is the height of the presented keyboard
    self.keyboardTopAnchorConstraint = self.view.layoutMarginsGuide.bottomAnchor.constraint(equalTo: keyboardAwareBottomLayoutGuide.topAnchor, constant: 0)
    self.keyboardTopAnchorConstraint.isActive = true
    self.keyboardAwareBottomLayoutGuide.bottomAnchor.constraint(equalTo: view.layoutMarginsGuide.bottomAnchor).isActive = true
    
    然后使用以下行开始收听键盘显示和隐藏:

    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShowNotification(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHideNotification(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
    
    最后,使用以下方法控制
    键盘awarebotomlayoutGuide
    以模拟键盘:

    @objc fileprivate func keyboardWillShowNotification(notification: NSNotification) {
        updateKeyboardAwareBottomLayoutGuide(with: notification, hiding: false)
    }
    
    @objc fileprivate func keyboardWillHideNotification(notification: NSNotification) {
        updateKeyboardAwareBottomLayoutGuide(with: notification, hiding: true)
    }
    
    fileprivate func updateKeyboardAwareBottomLayoutGuide(with notification: NSNotification, hiding: Bool) {
        let userInfo = notification.userInfo
    
        let animationDuration = (userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue
        let keyboardEndFrame = (userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue
    
        let rawAnimationCurve = (userInfo?[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber)?.uint32Value
    
        guard let animDuration = animationDuration,
            let keybrdEndFrame = keyboardEndFrame,
            let rawAnimCurve = rawAnimationCurve else {
                return
        }
    
        let convertedKeyboardEndFrame = view.convert(keybrdEndFrame, from: view.window)
    
        let rawAnimCurveAdjusted = UInt(rawAnimCurve << 16)
        let animationCurve = UIViewAnimationOptions(rawValue: rawAnimCurveAdjusted)
    
        // this will move the topAnchor of the keyboardAwareBottomLayoutGuide to height of the keyboard
        self.keyboardTopAnchorConstraint.constant = hiding ? 0 : convertedKeyboardEndFrame.size.height
    
        self.view.setNeedsLayout()
    
        UIView.animate(withDuration: animDuration, delay: 0.0, options: [.beginFromCurrentState, animationCurve], animations: {
            self.view.layoutIfNeeded()
        }, completion: { success in
            //
        })
    }
    
    编辑:直接设置帧

    虽然我强烈建议您使用Autolayout,但在无法使用Autolayout的情况下,直接设置帧也是一种解决方案。你可以使用同样的原理。在这种方法中,您不需要布局指南,因此不需要任何其他实例属性。只需使用
    viewDidLoad
    注册监听通知:

    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShowNotification(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHideNotification(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
    
    @objc fileprivate func keyboardWillShowNotification(notification: NSNotification) {
        adjustToKeyboard(with: notification, hiding: false)
    }
    
    @objc fileprivate func keyboardWillHideNotification(notification: NSNotification) {
        adjustToKeyboard(with: notification, hiding: true)
    }
    
    fileprivate func adjustToKeyboard(with notification: NSNotification, hiding: Bool) {
        let userInfo = notification.userInfo
    
        let animationDuration = (userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue
        let keyboardEndFrame = (userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue
    
        let rawAnimationCurve = (userInfo?[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber)?.uint32Value
    
        guard let animDuration = animationDuration,
            let keybrdEndFrame = keyboardEndFrame,
            let rawAnimCurve = rawAnimationCurve else {
                return
        }
    
        let convertedKeyboardEndFrame = view.convert(keybrdEndFrame, from: view.window)
    
        let rawAnimCurveAdjusted = UInt(rawAnimCurve << 16)
        let animationCurve = UIViewAnimationOptions(rawValue: rawAnimCurveAdjusted)
    
        // we will go either up or down depending on whether the keyboard is being hidden or shown
        let diffInHeight = hiding ? convertedKeyboardEndFrame.size.height : -convertedKeyboardEndFrame.size.height
    
        UIView.animate(withDuration: animDuration, delay: 0.0, options: [.beginFromCurrentState, animationCurve], animations: {
            // this will move the frame of the aView according to the diffInHeight calculated above
            // of course here you need to set all the frames that would be affected by the keyboard (this is why I prefer using autolayout)
            self.aView?.frame = (self.aView?.frame.offsetBy(dx: 0, dy: diff))!
    
            // of course, you can do anything more complex than just moving the aView up..
        })
    }
    
    然后实施将对这些通知作出反应的方法:

    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShowNotification(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHideNotification(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
    
    @objc fileprivate func keyboardWillShowNotification(notification: NSNotification) {
        adjustToKeyboard(with: notification, hiding: false)
    }
    
    @objc fileprivate func keyboardWillHideNotification(notification: NSNotification) {
        adjustToKeyboard(with: notification, hiding: true)
    }
    
    fileprivate func adjustToKeyboard(with notification: NSNotification, hiding: Bool) {
        let userInfo = notification.userInfo
    
        let animationDuration = (userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue
        let keyboardEndFrame = (userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue
    
        let rawAnimationCurve = (userInfo?[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber)?.uint32Value
    
        guard let animDuration = animationDuration,
            let keybrdEndFrame = keyboardEndFrame,
            let rawAnimCurve = rawAnimationCurve else {
                return
        }
    
        let convertedKeyboardEndFrame = view.convert(keybrdEndFrame, from: view.window)
    
        let rawAnimCurveAdjusted = UInt(rawAnimCurve << 16)
        let animationCurve = UIViewAnimationOptions(rawValue: rawAnimCurveAdjusted)
    
        // we will go either up or down depending on whether the keyboard is being hidden or shown
        let diffInHeight = hiding ? convertedKeyboardEndFrame.size.height : -convertedKeyboardEndFrame.size.height
    
        UIView.animate(withDuration: animDuration, delay: 0.0, options: [.beginFromCurrentState, animationCurve], animations: {
            // this will move the frame of the aView according to the diffInHeight calculated above
            // of course here you need to set all the frames that would be affected by the keyboard (this is why I prefer using autolayout)
            self.aView?.frame = (self.aView?.frame.offsetBy(dx: 0, dy: diff))!
    
            // of course, you can do anything more complex than just moving the aView up..
        })
    }
    

    您可以使用以下自动布局解决方案来实现它

    首先,您需要使用模拟键盘感知的底部锚定的
    UILayoutGuide
    ,以及控制此布局指南的
    NSLayoutConstraint

    fileprivate let keyboardAwareBottomLayoutGuide: UILayoutGuide = UILayoutGuide()
    fileprivate var keyboardTopAnchorConstraint: NSLayoutConstraint!
    
    viewdiload
    中,将
    键盘awarebottomlayoutGuide
    添加到视图中,并设置适当的约束:

    self.view.addLayoutGuide(self.keyboardAwareBottomLayoutGuide)
    // this will control keyboardAwareBottomLayoutGuide.topAnchor to be so far from bottom of the bottom as is the height of the presented keyboard
    self.keyboardTopAnchorConstraint = self.view.layoutMarginsGuide.bottomAnchor.constraint(equalTo: keyboardAwareBottomLayoutGuide.topAnchor, constant: 0)
    self.keyboardTopAnchorConstraint.isActive = true
    self.keyboardAwareBottomLayoutGuide.bottomAnchor.constraint(equalTo: view.layoutMarginsGuide.bottomAnchor).isActive = true
    
    然后使用以下行开始收听键盘显示和隐藏:

    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShowNotification(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHideNotification(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
    
    最后,使用以下方法控制
    键盘awarebotomlayoutGuide
    以模拟键盘:

    @objc fileprivate func keyboardWillShowNotification(notification: NSNotification) {
        updateKeyboardAwareBottomLayoutGuide(with: notification, hiding: false)
    }
    
    @objc fileprivate func keyboardWillHideNotification(notification: NSNotification) {
        updateKeyboardAwareBottomLayoutGuide(with: notification, hiding: true)
    }
    
    fileprivate func updateKeyboardAwareBottomLayoutGuide(with notification: NSNotification, hiding: Bool) {
        let userInfo = notification.userInfo
    
        let animationDuration = (userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue
        let keyboardEndFrame = (userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue
    
        let rawAnimationCurve = (userInfo?[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber)?.uint32Value
    
        guard let animDuration = animationDuration,
            let keybrdEndFrame = keyboardEndFrame,
            let rawAnimCurve = rawAnimationCurve else {
                return
        }
    
        let convertedKeyboardEndFrame = view.convert(keybrdEndFrame, from: view.window)
    
        let rawAnimCurveAdjusted = UInt(rawAnimCurve << 16)
        let animationCurve = UIViewAnimationOptions(rawValue: rawAnimCurveAdjusted)
    
        // this will move the topAnchor of the keyboardAwareBottomLayoutGuide to height of the keyboard
        self.keyboardTopAnchorConstraint.constant = hiding ? 0 : convertedKeyboardEndFrame.size.height
    
        self.view.setNeedsLayout()
    
        UIView.animate(withDuration: animDuration, delay: 0.0, options: [.beginFromCurrentState, animationCurve], animations: {
            self.view.layoutIfNeeded()
        }, completion: { success in
            //
        })
    }
    
    编辑:直接设置帧

    虽然我强烈建议您使用Autolayout,但在无法使用Autolayout的情况下,直接设置帧也是一种解决方案。你可以使用同样的原理。在这种方法中,您不需要布局指南,因此不需要任何其他实例属性。只需使用
    viewDidLoad
    注册监听通知:

    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShowNotification(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHideNotification(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
    
    @objc fileprivate func keyboardWillShowNotification(notification: NSNotification) {
        adjustToKeyboard(with: notification, hiding: false)
    }
    
    @objc fileprivate func keyboardWillHideNotification(notification: NSNotification) {
        adjustToKeyboard(with: notification, hiding: true)
    }
    
    fileprivate func adjustToKeyboard(with notification: NSNotification, hiding: Bool) {
        let userInfo = notification.userInfo
    
        let animationDuration = (userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue
        let keyboardEndFrame = (userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue
    
        let rawAnimationCurve = (userInfo?[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber)?.uint32Value
    
        guard let animDuration = animationDuration,
            let keybrdEndFrame = keyboardEndFrame,
            let rawAnimCurve = rawAnimationCurve else {
                return
        }
    
        let convertedKeyboardEndFrame = view.convert(keybrdEndFrame, from: view.window)
    
        let rawAnimCurveAdjusted = UInt(rawAnimCurve << 16)
        let animationCurve = UIViewAnimationOptions(rawValue: rawAnimCurveAdjusted)
    
        // we will go either up or down depending on whether the keyboard is being hidden or shown
        let diffInHeight = hiding ? convertedKeyboardEndFrame.size.height : -convertedKeyboardEndFrame.size.height
    
        UIView.animate(withDuration: animDuration, delay: 0.0, options: [.beginFromCurrentState, animationCurve], animations: {
            // this will move the frame of the aView according to the diffInHeight calculated above
            // of course here you need to set all the frames that would be affected by the keyboard (this is why I prefer using autolayout)
            self.aView?.frame = (self.aView?.frame.offsetBy(dx: 0, dy: diff))!
    
            // of course, you can do anything more complex than just moving the aView up..
        })
    }
    
    然后实施将对这些通知作出反应的方法:

    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShowNotification(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHideNotification(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
    
    @objc fileprivate func keyboardWillShowNotification(notification: NSNotification) {
        adjustToKeyboard(with: notification, hiding: false)
    }
    
    @objc fileprivate func keyboardWillHideNotification(notification: NSNotification) {
        adjustToKeyboard(with: notification, hiding: true)
    }
    
    fileprivate func adjustToKeyboard(with notification: NSNotification, hiding: Bool) {
        let userInfo = notification.userInfo
    
        let animationDuration = (userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue
        let keyboardEndFrame = (userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue
    
        let rawAnimationCurve = (userInfo?[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber)?.uint32Value
    
        guard let animDuration = animationDuration,
            let keybrdEndFrame = keyboardEndFrame,
            let rawAnimCurve = rawAnimationCurve else {
                return
        }
    
        let convertedKeyboardEndFrame = view.convert(keybrdEndFrame, from: view.window)
    
        let rawAnimCurveAdjusted = UInt(rawAnimCurve << 16)
        let animationCurve = UIViewAnimationOptions(rawValue: rawAnimCurveAdjusted)
    
        // we will go either up or down depending on whether the keyboard is being hidden or shown
        let diffInHeight = hiding ? convertedKeyboardEndFrame.size.height : -convertedKeyboardEndFrame.size.height
    
        UIView.animate(withDuration: animDuration, delay: 0.0, options: [.beginFromCurrentState, animationCurve], animations: {
            // this will move the frame of the aView according to the diffInHeight calculated above
            // of course here you need to set all the frames that would be affected by the keyboard (this is why I prefer using autolayout)
            self.aView?.frame = (self.aView?.frame.offsetBy(dx: 0, dy: diff))!
    
            // of course, you can do anything more complex than just moving the aView up..
        })
    }
    

    to 1:使用UIKeyboardWillShow和UIKeyboardWillHide代替UIKeyboardWillChangeFrame另一个谜团是当按键盘向下箭头时UIKeyboardWillHide没有被调用。to 1:使用UIKeyboardWillShow和UIKeyboardWillHide代替UIKeyboardWillChangeFrame另一个谜团是当按键盘向下箭头时UIKeyboardWillHide没有被调用键盘向下箭头。谢谢。即使这两种观点有不同的父母,这会起作用吗?哪两种观点?我不太确定我是否理解你想说的话。。我的解决方案只创建了一个调整到键盘的人工锚。。因此,不要根据左、右、上和下放置视图,而是根据左、右、上和键盘布局视图A重新定位到MLayoutGuide.topAnchor。换句话说,像往常一样使用自动布局,而不是使用viewController.view.bottomAnchor使用KeyboardAwaReboottomLayoutGuide.topAnchor。因此,无论您想在视图中约束什么,都可以像往常一样进行约束,只需使用新的布局指南而不是静态视图。bottomAnchor如果您不习惯自动布局,您可以通过编程方式进行布局,而不是设置self.keyboardTopAnchorConstraint.constant=隐藏?0:convertedKeyboardEndFrame.size.height(
    convertedKeyboardEndFrame.size.height
    提供了
    CGFloat
    数字,告诉您由于键盘的缘故,您的空间减少了多少)。不过,我还是建议采用autolayout,因为它大大简化了事情。您好,我最终使用了RxKeyboard。谢谢。即使这两种观点有不同的父母,这会起作用吗?哪两种观点?我不太确定我是否理解你想说的话。。我的解决方案只创建了一个调整到键盘的人工锚。。因此,不要根据左、右、上和下放置视图,而是根据左、右、上和键盘布局视图A重新定位到MLayoutGuide.topAnchor。换句话说,像往常一样使用自动布局,而不是使用viewController.view.bottomAnchor使用KeyboardAwaReboottomLayoutGuide.topAnchor。因此,无论您想在视图中约束什么,都可以像往常一样进行约束,只需使用新的布局指南而不是静态视图。bottomAnchor如果您不习惯自动布局,您可以通过编程方式进行布局,而不是设置self.keyboardTopAnchorConstraint.constant=隐藏?0:convertedKeyboardEndFrame.size.height(
    convertedKeyboardEndFrame.size.height
    提供了
    CGFloat
    数字,告诉您由于键盘的缘故,您的空间减少了多少)。不过,我还是建议采用autolayout,因为它大大简化了事情。您好,我最终使用了RxKeyboard。