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

更新1:如果您想尝试一下,我已经创建了一个github项目:https://github.com/JCzz/KeyboardProject

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

更新2:刚推-包括使用框架

我可能已经看了太久了,我无法绕开它:-)

你知不知道怎么?


我怎么知道UIKeyboard是向下还是向上?
如果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!


viewDidLoad中,将keyboardAwareBottomLayoutGuide添加到视图中并设置适当的约束:

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)


最后,使用以下方法控制keyboardAwareBottomLayoutGuide以模仿键盘:

@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
        //
    })
}


现在,完成所有这些设置后,您可以使用“自动布局”将视图限制为keyboardAwareBottomLayoutGuide.topAnchor而不是self.view.layoutMarginsGuide.bottomAnchor(或self.view.bottomAnchor,以您所使用的为准)。 keyboardAwareBottomLayoutGuide将自动调整为显示或隐藏的键盘。

例:

uiTextField.bottomAnchor.constraint(equalTo: keyboardAwareBottomLayoutGuide.topAnchor).isActive = true


编辑:直接设置框架

虽然我强烈建议您使用自动版式,但在无法使用自动版式的情况下,直接设置框架也是一种解决方案。您可以使用相同的原理。在这种方法中,您不需要布局指南,因此不需要任何其他实例属性。只需使用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..
    })
}


在这两种情况下,一旦取消初始化viewController以防止保留周期,请不要忘记注销观察通知的注册:

deinit {
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}

关于ios - 如何将底 View 移到UIKeyboard的顶部,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/46235188/

10-14 09:31