如何将底视图移到UIKeyboard的顶部 [英] How to move bottom view to top of UIKeyboard

查看:85
本文介绍了如何将底视图移到UIKeyboard的顶部的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Hi I am trying to make a view's bottom align with the top of UIKeyboard.

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

Update 1: I have created a github project if you would like to give it a try: https://github.com/JCzz/KeyboardProject

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

Note: I need the aView to be dynamic.

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

Update 2: Just pushed - to include using frames

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

I might have been looking at this for too long, I can not wrap my brain around it :-)

你知道吗?

  1. 我如何知道UIKeyboard是在向下还是向上?

  1. How do I know if the UIKeyboard is on the way down or up?

如果UIKeyboard处于打开状态,则如何将其与视图对齐(attachKeyboardToFrame-请参见代码).

If UIKeyboard is up, then how to align it with the view(attachKeyboardToFrame - see code).

我找到了以下UIView扩展名:

I have found the following UIView extension:

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{

        }

    }
}

推荐答案

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

You can achieve it using following Autolayout solution.

首先,您需要使用UILayoutGuide来模拟可识别键盘的底部锚点,并使用NSLayoutConstraint来控制此布局指南:

First you need UILayoutGuide that will be used simulate Keyboard aware bottom anchor, and a NSLayoutConstraint that will control this layout guide:

fileprivate let keyboardAwareBottomLayoutGuide: UILayoutGuide = UILayoutGuide()
fileprivate var keyboardTopAnchorConstraint: NSLayoutConstraint!

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

In the viewDidLoad add the keyboardAwareBottomLayoutGuide to the view and setup the appropriate contraints:

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

然后使用以下几行开始收听键盘的显示和隐藏操作:

Then use following lines to start listening to keyboard showing and hiding:

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以模仿键盘:

And finally, use following methods to control the keyboardAwareBottomLayoutGuide to mimic the keyboard:

@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将自动调整为显示或隐藏的键盘.

Now with all this set up, you can use Autolayout to constraint your views to keyboardAwareBottomLayoutGuide.topAnchor instead of self.view.layoutMarginsGuide.bottomAnchor (or self.view.bottomAnchor, whichever you use). keyboardAwareBottomLayoutGuide will automatically adjust to the keyboard showed or hidden.

示例:

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

直接设置框架

虽然我强烈建议您使用自动版式,但如果无法使用自动版式,则直接设置框架也是一种解决方案.您可以使用相同的原理.在这种方法中,您不需要布局指南,因此不需要任何其他实例属性.只需使用viewDidLoad注册收听通知即可:

While I strongly recommend using Autolayout, in cases when you cannot go with this, directly setting frames can be also a solution. You can use the same principle. In this approach you don't need layout guide, so you don't need any additional instance properties. Just use viewDidLoad to register for listening notifications:

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)

然后实现将对这些通知做出反应的方法:

Then implement methods that will react to these notifications:

@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进行了初始化以防止保留周期,请不要忘记注销对通知的观察:

In both cases, don't forget to unregister observing the notifications once the viewController is deinitialized to prevent retain cycles:

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

这篇关于如何将底视图移到UIKeyboard的顶部的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆