当键盘快速显示时移动文本字段

Ped*_*edi 205 keyboard cocoa-touch uitextfield ios swift

我正在使用Swift进行iOS编程,我正在使用此代码移动UITextField,但它不起作用.我keyboardWillShow正确调用该函数,但文本字段不移动.我正在使用autolayout.

override func viewDidLoad() {
    super.viewDidLoad()
    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name:UIKeyboardWillShowNotification, object: nil);
    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name:UIKeyboardWillHideNotification, object: nil);
}

deinit {
    NSNotificationCenter.defaultCenter().removeObserver(self);
}

func keyboardWillShow(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
        //let contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height, right: 0)

        var frame = self.ChatField.frame
        frame.origin.y = frame.origin.y - keyboardSize.height + 167
        self.chatField.frame = frame
        println("asdasd")
    }
}
Run Code Online (Sandbox Code Playgroud)

Jos*_*ord 298

对现有答案进行了一些改进.

首先,UIKeyboardWillChangeFrameNotification可能是最好的通知,因为它处理的变化不仅仅是显示/隐藏,而是由于键盘更改(语言,使用第三方键盘等)和旋转而发生的变化(但是下面的注释注释表明键盘将隐藏应该也可以处理以支持硬件键盘连接).

其次,可以从通知中提取动画参数,以确保动画正确地组合在一起.

有一些选项可以清理这些代码,特别是如果您对使用强制解包字典代码感到满意的话.

Swift 3.x/4.x.

class MyViewController: UIViewController {

// This constraint ties an element at zero points from the bottom layout guide
@IBOutlet var keyboardHeightLayoutConstraint: NSLayoutConstraint?

override func viewDidLoad() {
    super.viewDidLoad()
    // Note that SO highlighting makes the new selector syntax (#selector()) look
    // like a comment but it isn't one
    NotificationCenter.default.addObserver(self,
        selector: #selector(self.keyboardNotification(notification:)),
        name: NSNotification.Name.UIKeyboardWillChangeFrame,
        object: nil)
}

deinit {
    NotificationCenter.default.removeObserver(self)
}

@objc func keyboardNotification(notification: NSNotification) {
    if let userInfo = notification.userInfo {
        let endFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue
        let endFrameY = endFrame.origin.y ?? 0
        let duration:TimeInterval = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0
        let animationCurveRawNSN = userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber
        let animationCurveRaw = animationCurveRawNSN?.uintValue ?? UIViewAnimationOptions.curveEaseInOut.rawValue
        let animationCurve:UIViewAnimationOptions = UIViewAnimationOptions(rawValue: animationCurveRaw)
        if endFrameY >= UIScreen.main.bounds.size.height {
            self.keyboardHeightLayoutConstraint?.constant = 0.0
        } else {
            self.keyboardHeightLayoutConstraint?.constant = endFrame?.size.height ?? 0.0
        }
        UIView.animate(withDuration: duration,
                                   delay: TimeInterval(0),
                                   options: animationCurve,
                                   animations: { self.view.layoutIfNeeded() },
                                   completion: nil)
    }
}
Run Code Online (Sandbox Code Playgroud)

(根据@Gabox下面的精彩评论,编辑为屏幕外的键盘动画而不是收缩)

  • 如果键盘没有隐藏,请尝试使用此代码如果endFrame?.origin.y> = UIScreen.mainScreen().bounds.size.height {self.keyboardHeightLayoutConstraint?.constant = 0.0} else {self.keyboardHeightLayoutConstraint?.constant = endFrame.size.height} (8认同)
  • keyBoardHeightLayoutConstraint是InterfaceBuilder中定义的约束,用于约束要移动/缩小到底部布局指南的视图底部或视图控制器主视图的底部.常量初始设置为零,并将进行调整,以便在键盘出现或更改大小时为键盘腾出空间. (3认同)
  • 请注意,即使iOS键盘消失,连接硬件键盘时也不会触发`.UIKeyboardWillChangeFrame`.您还需要观察`.UIKeyboardWillHide`以捕获该边缘情况. (2认同)

Isu*_*uru 127

如果您正在使用自动布局,我假设您已将" 底部空间"设置为"超级视图" 约束.如果是这种情况,您只需更新约束的值即可.这是你用一点点动画做到的.

func keyboardWasShown(notification: NSNotification) {
    let info = notification.userInfo!
    let keyboardFrame: CGRect = (info[UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue()

    UIView.animateWithDuration(0.1, animations: { () -> Void in
        self.bottomConstraint.constant = keyboardFrame.size.height + 20
    })
}
Run Code Online (Sandbox Code Playgroud)

添加硬编码20只是为了弹出键盘上方的文本字段.否则键盘的上边距和文本字段的下边距将会触及.

键盘关闭后,将约束的值重置为其原始值.

  • @AdamJohns要为约束更改设置动画,请更新`animateWithDuration`之外的常量,并在animate块内调用`self.view.layoutIfNeeded()`. (7认同)
  • bottomConstraint是我给约束的名字.我选择了constrant,拖动并创建了一个IBOutlet并给出了它的名字.您可以像处理按钮和文本字段等其他UI元素一样创建IBOutlet到约束. (4认同)
  • 除了动画对我来说立即发生之外,这个答案效果很好。检查 [如何为约束更改设置动画?](http://stackoverflow.com/a/12664093/1438339) 了解如何正确设置动画。 (3认同)
  • @ vinbhai4u您必须注册"UIKeyboardWillShowNotification"通知.看一下OP问题中的代码. (2认同)

Saq*_*mer 97

一个简单的解决方案是使用键盘高度不变来向上移动视图.

override func viewDidLoad() {
   super.viewDidLoad()        
   NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name:UIKeyboardWillShowNotification, object: nil);
   NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name:UIKeyboardWillHideNotification, object: nil);
}

func keyboardWillShow(sender: NSNotification) {
     self.view.frame.origin.y = -150 // Move view 150 points upward 
}

func keyboardWillHide(sender: NSNotification) {
     self.view.frame.origin.y = 0 // Move view to original position  
}
Run Code Online (Sandbox Code Playgroud)

斯威夫特3

NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(sender:)), name: UIResponder.keyboardWillShowNotification, object: nil);

NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(sender:)), name: UIResponder.keyboardWillHideNotification, object: nil);
Run Code Online (Sandbox Code Playgroud)

  • 我喜欢这个简单的解决方案 但是我添加了一个keyboardShowing boolean,因为我移动了一个文本字段.我只在键盘显示时移动一次.谢谢. (4认同)
  • 而不是使用`self.view.frame.origin.y - = 150`使用`self.view.frame.origin.y = -150`而不是'self.view.frame.origin.y + = 150`使用`self.view.frame.origin.y = 0`.这防止了每次触摸新场时视图移动150. (4认同)
  • 而不是移动视图,移动 textView (2认同)

Jog*_*Com 40

为了在编辑textfield时移动你的视图试试这个,我已经应用了它,它的工作正常

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    NotificationCenter.default.addObserver( self, selector: #selector(keyboardWillShow(notification:)), name:  UIResponder.keyboardWillShowNotification, object: nil )
}
override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
}

@objc func keyboardWillShow( notification: Notification) {
    if let keyboardFrame: NSValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue {
        let newHeight: CGFloat
        let duration:TimeInterval = (notification.userInfo![UIResponder.keyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0
        let animationCurveRawNSN = notification.userInfo![UIResponder.keyboardAnimationCurveUserInfoKey] as? NSNumber
        let animationCurveRaw = animationCurveRawNSN?.uintValue ?? UIView.AnimationOptions.curveEaseInOut.rawValue
        let animationCurve:UIView.AnimationOptions = UIView.AnimationOptions(rawValue: animationCurveRaw)
        if #available(iOS 11.0, *) {
            newHeight = keyboardFrame.cgRectValue.height - self.view.safeAreaInsets.bottom
        } else {
            newHeight = keyboardFrame.cgRectValue.height
        }
        let keyboardHeight = newHeight  + 10 // **10 is bottom margin of View**  and **this newHeight will be keyboard height**
        UIView.animate(withDuration: duration,
                       delay: TimeInterval(0),
                       options: animationCurve,
                       animations: {
                        self.view.textViewBottomConstraint.constant = keyboardHeight **//Here you can manage your view constraints for animated show**
                        self.view.layoutIfNeeded() },
                       completion: nil)
    }
}
Run Code Online (Sandbox Code Playgroud)

我从这个源获得了这个答案UITextField在键盘出现在Swift时向上移动

在Swift 4 ---

func textFieldDidBeginEditing(textField: UITextField) {
        self.animateViewMoving(up: true, moveValue: 100)
}
func textFieldDidEndEditing(textField: UITextField) {
        self.animateViewMoving(up: false, moveValue: 100)
}

func animateViewMoving (up:Bool, moveValue :CGFloat){
    var movementDuration:NSTimeInterval = 0.3
    var movement:CGFloat = ( up ? -moveValue : moveValue)
    UIView.beginAnimations( "animateView", context: nil)
    UIView.setAnimationBeginsFromCurrentState(true)
    UIView.setAnimationDuration(movementDuration )
    self.view.frame = CGRectOffset(self.view.frame, 0,  movement)
    UIView.commitAnimations()
}
Run Code Online (Sandbox Code Playgroud)


sco*_*rmg 20

我喜欢干净的Swift代码.所以这是我用键盘上下移动文本视图的最紧密的代码.它目前正在使用iOS8/9 Swift 2制作应用程序.

更新(2016年3月):我尽可能地收紧了以前的代码.此外,这里有一堆流行的答案硬编码键盘高度和动画参数.没有必要这样做,更不用说这些答案中的数字并不总是符合我在6s + iOS9上看到的实际值(键盘高度为226,持续时间为0.25,动画曲线为7).在任何情况下,几乎没有额外的代码可以直接从系统中获取这些值.见下文.

override func viewDidLoad() {
    super.viewDidLoad()

    NSNotificationCenter.defaultCenter().addObserver(self, selector: "animateWithKeyboard:", name: UIKeyboardWillShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "animateWithKeyboard:", name: UIKeyboardWillHideNotification, object: nil)
}

func animateWithKeyboard(notification: NSNotification) {

    // Based on both Apple's docs and personal experience, 
    // I assume userInfo and its documented keys are available.
    // If you'd like, you can remove the forced unwrapping and add your own default values.

    let userInfo = notification.userInfo!
    let keyboardHeight = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue().height
    let duration = userInfo[UIKeyboardAnimationDurationUserInfoKey] as! Double
    let curve = userInfo[UIKeyboardAnimationCurveUserInfoKey] as! UInt
    let moveUp = (notification.name == UIKeyboardWillShowNotification)

    // baseContraint is your Auto Layout constraint that pins the
    // text view to the bottom of the superview.

    baseConstraint.constant = moveUp ? -keyboardHeight : 0

    let options = UIViewAnimationOptions(rawValue: curve << 16)
    UIView.animateWithDuration(duration, delay: 0, options: options,
        animations: {
            self.view.layoutIfNeeded()
        },
        completion: nil
    )

}
Run Code Online (Sandbox Code Playgroud)

注意:此代码涵盖了大多数评论/一般情况.但是,可能需要更多代码来处理不同的方向和/或自定义键盘这是一篇关于使用iOS键盘的深入文章.如果您需要处理每个场景,这可能会有所帮助.


Hlu*_*ung 15

编辑:我建议更简单,更清洁的解决方案.只需将底部间距约束的类更改为KeyboardLayoutConstraint.它会自动扩展到键盘高度.


这是@JosephLord答案的改进版本.

在iOS 8.3 iPad模拟器,肖像测试.Xcode6.3 BETA4,我发现当键盘被隐藏,因为他的回答不工作UIKeyboardFrameEndUserInfoKey"NSRect: {{0, 1024}, {768, 264}}";.高度永远不会0.

这可以追溯到使用传统的UIKeyboardWillShowNotification,UIKeyboardWillHideNotification更好地告诉键盘何时隐藏而不是依赖于终端框架的高度.UIKeyboardWillShowNotification键盘框架更改时也会发送,因此它应覆盖所有用例.

    // You have to set this up in storyboard first!. 
    // It's a vertical spacing constraint between view and bottom of superview.
    @IBOutlet weak var bottomSpacingConstraint: NSLayoutConstraint! 

    override func viewDidLoad() {
        super.viewDidLoad()

        NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardNotification:"), name:UIKeyboardWillShowNotification, object: nil);
        NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardNotification:"), name:UIKeyboardWillHideNotification, object: nil);
    }

    deinit {
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }

    func keyboardNotification(notification: NSNotification) {

        let isShowing = notification.name == UIKeyboardWillShowNotification

        if let userInfo = notification.userInfo {
            let endFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue()
            let endFrameHeight = endFrame?.size.height ?? 0.0
            let duration:NSTimeInterval = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0
            let animationCurveRawNSN = userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber
            let animationCurveRaw = animationCurveRawNSN?.unsignedLongValue ?? UIViewAnimationOptions.CurveEaseInOut.rawValue
            let animationCurve:UIViewAnimationOptions = UIViewAnimationOptions(rawValue: animationCurveRaw)
            self.bottomSpacingConstraint?.constant = isShowing ? endFrameHeight : 0.0
            UIView.animateWithDuration(duration,
                delay: NSTimeInterval(0),
                options: animationCurve,
                animations: { self.view.layoutIfNeeded() },
                completion: nil)
        }
    }
Run Code Online (Sandbox Code Playgroud)


pan*_*hay 9

我正在使用swift 4,我解决了这个问题,没有使用任何额外的底部约束看看我的代码在这里.真的在我的情况下工作

1)在加载中添加通知观察者

override func viewDidLoad() {
        super.viewDidLoad()
        setupManager()
        // Do any additional setup after loading the view.
        NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
    }
Run Code Online (Sandbox Code Playgroud)

2)删除通知观察器之类的

deinit {
        NotificationCenter.default.removeObserver(self)
    }
Run Code Online (Sandbox Code Playgroud)

3)添加键盘显示/隐藏方法

 @objc func keyboardWillShow(notification: NSNotification) {
            if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
                UIView.animate(withDuration: 0.1, animations: { () -> Void in
                    self.view.frame.origin.y -= keyboardSize.height
                    self.view.layoutIfNeeded()
                })
            }
        }

@objc func keyboardWillHide(notification: NSNotification) {
        if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
            UIView.animate(withDuration: 0.1, animations: { () -> Void in
                self.view.frame.origin.y += keyboardSize.height
                self.view.layoutIfNeeded()
            })
        }
    }
Run Code Online (Sandbox Code Playgroud)

4)添加textfeild委托并添加touchesBegan方法.usefull用于在屏幕上的textfeild外触摸时隐藏键盘

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        view.endEditing(true)

    }
Run Code Online (Sandbox Code Playgroud)


Avi*_*are 8

管理键盘的完整代码。

        override func viewWillAppear(_ animated: Bool) {
            NotificationCenter.default.addObserver(self, selector: #selector(StoryMediaVC.keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
            NotificationCenter.default.addObserver(self, selector: #selector(StoryMediaVC.keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
        }
        override func viewWillDisappear(_ animated: Bool) {
            NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
            NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
        }
        @objc func keyboardWillShow(notification: NSNotification) {
            guard let userInfo = notification.userInfo else {return}
            guard let keyboardSize = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else {return}
            let keyboardFrame = keyboardSize.cgRectValue

            if self.view.bounds.origin.y == 0{
                self.view.bounds.origin.y += keyboardFrame.height
            }
        }


        @objc func keyboardWillHide(notification: NSNotification) {
            if self.view.bounds.origin.y != 0 {
                self.view.bounds.origin.y = 0
            }
        }
Run Code Online (Sandbox Code Playgroud)


Jef*_*ang 7

这是@JosephLord和@Hlung的回答的改进版本.无论您是否有tabbar,它都可以适用.它可以完美地恢复键盘移动到原始位置的视图.

// You have to set this up in storyboard first!. 
// It's a vertical spacing constraint between view and bottom of superview.
@IBOutlet weak var bottomSpacingConstraint: NSLayoutConstraint! 

override func viewDidLoad() {
        super.viewDidLoad()            

        //    Receive(Get) Notification
        NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardNotification:", name: UIKeyboardWillShowNotification, object: nil)
        NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardNotification:", name: UIKeyboardWillHideNotification, object: nil)


        self.originalConstraint = self.keyboardHeightLayoutConstraint?.constant //for original coordinate.
}

func keyboardNotification(notification: NSNotification) {
        let isShowing = notification.name == UIKeyboardWillShowNotification

        var tabbarHeight: CGFloat = 0
        if self.tabBarController? != nil {
            tabbarHeight = self.tabBarController!.tabBar.frame.height
        }
        if let userInfo = notification.userInfo {
            let endFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue()
            let duration:NSTimeInterval = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0
            let animationCurveRawNSN = userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber
            let animationCurveRaw = animationCurveRawNSN?.unsignedLongValue ?? UIViewAnimationOptions.CurveEaseInOut.rawValue
            let animationCurve:UIViewAnimationOptions = UIViewAnimationOptions(rawValue: animationCurveRaw)
            self.keyboardHeightLayoutConstraint?.constant = isShowing ? (endFrame!.size.height - tabbarHeight) : self.originalConstraint!
            UIView.animateWithDuration(duration,
                delay: NSTimeInterval(0),
                options: animationCurve,
                animations: { self.view.layoutIfNeeded() },
                completion: nil)
        }
}
Run Code Online (Sandbox Code Playgroud)


gam*_*ill 6

最简单的方法,不需要任何代码:

  1. 如果您还没有使用Spring动画框架,请下载KeyboardLayoutConstraint.swift并将文件添加(拖放)到您的项目中.
  2. 在故事板中,为对象/视图/文本字段创建底部约束,选择约束(双击它),然后在Identity Inspector中,将其类从NSLayoutConstraint更改为KeyboardLayoutConstraint.
  3. 完成!

该对象将与键盘同步自动向上移动.

  • 很好的解决方案!但是您需要“安全区域”作为约束的第一项(第二项对我不起作用)。并且将常量设置为0时效果最佳,因为它可以保留常量并对其进行调整,而不仅仅是将其移动到足以显示字段和键盘的程度。 (2认同)

ale*_*tro 6

可以使用这种简单的UIViewController 扩展

//MARK: - Observers
extension UIViewController {

    func addObserverForNotification(notificationName: String, actionBlock: (NSNotification) -> Void) {
        NSNotificationCenter.defaultCenter().addObserverForName(notificationName, object: nil, queue: NSOperationQueue.mainQueue(), usingBlock: actionBlock)
    }

    func removeObserver(observer: AnyObject, notificationName: String) {
        NSNotificationCenter.defaultCenter().removeObserver(observer, name: notificationName, object: nil)
    }
}

//MARK: - Keyboard observers
extension UIViewController {

    typealias KeyboardHeightClosure = (CGFloat) -> ()

    func addKeyboardChangeFrameObserver(willShow willShowClosure: KeyboardHeightClosure?,
        willHide willHideClosure: KeyboardHeightClosure?) {
            NSNotificationCenter.defaultCenter().addObserverForName(UIKeyboardWillChangeFrameNotification,
                object: nil, queue: NSOperationQueue.mainQueue(), usingBlock: { [weak self](notification) in
                    if let userInfo = notification.userInfo,
                        let frame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue(),
                        let duration = userInfo[UIKeyboardAnimationDurationUserInfoKey] as? Double,
                        let c = userInfo[UIKeyboardAnimationCurveUserInfoKey] as? UInt,
                        let kFrame = self?.view.convertRect(frame, fromView: nil),
                        let kBounds = self?.view.bounds {

                            let animationType = UIViewAnimationOptions(rawValue: c)
                            let kHeight = kFrame.size.height
                            UIView.animateWithDuration(duration, delay: 0, options: animationType, animations: {
                                if CGRectIntersectsRect(kBounds, kFrame) { // keyboard will be shown
                                    willShowClosure?(kHeight)
                                } else { // keyboard will be hidden
                                    willHideClosure?(kHeight)
                                }
                                }, completion: nil)
                    } else {
                            print("Invalid conditions for UIKeyboardWillChangeFrameNotification")
                    }
            })
    }

    func removeKeyboardObserver() {
        removeObserver(self, notificationName: UIKeyboardWillChangeFrameNotification)
    }
}
Run Code Online (Sandbox Code Playgroud)

用法示例

override func viewWillDisappear(animated: Bool) {
        super.viewWillDisappear(animated)

        removeKeyboardObserver()
    }

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)

    addKeyboardChangeFrameObserver(willShow: { [weak self](height) in
        //Update constraints here
        self?.view.setNeedsUpdateConstraints()
        }, willHide: { [weak self](height) in
        //Reset constraints here
        self?.view.setNeedsUpdateConstraints()
    })
}
Run Code Online (Sandbox Code Playgroud)

Swift 4解决方案

//MARK: - Observers
extension UIViewController {

  func addObserverForNotification(_ notificationName: Notification.Name, actionBlock: @escaping (Notification) -> Void) {
    NotificationCenter.default.addObserver(forName: notificationName, object: nil, queue: OperationQueue.main, using: actionBlock)
  }

  func removeObserver(_ observer: AnyObject, notificationName: Notification.Name) {
    NotificationCenter.default.removeObserver(observer, name: notificationName, object: nil)
  }
}

//MARK: - Keyboard handling
extension UIViewController {

  typealias KeyboardHeightClosure = (CGFloat) -> ()

  func addKeyboardChangeFrameObserver(willShow willShowClosure: KeyboardHeightClosure?,
                                      willHide willHideClosure: KeyboardHeightClosure?) {
    NotificationCenter.default.addObserver(forName: NSNotification.Name.UIKeyboardWillChangeFrame,
                                           object: nil, queue: OperationQueue.main, using: { [weak self](notification) in
                                            if let userInfo = notification.userInfo,
                                              let frame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue,
                                              let duration = userInfo[UIKeyboardAnimationDurationUserInfoKey] as? Double,
                                              let c = userInfo[UIKeyboardAnimationCurveUserInfoKey] as? UInt,
                                              let kFrame = self?.view.convert(frame, from: nil),
                                              let kBounds = self?.view.bounds {

                                              let animationType = UIViewAnimationOptions(rawValue: c)
                                              let kHeight = kFrame.size.height
                                              UIView.animate(withDuration: duration, delay: 0, options: animationType, animations: {
                                                if kBounds.intersects(kFrame) { // keyboard will be shown
                                                  willShowClosure?(kHeight)
                                                } else { // keyboard will be hidden
                                                  willHideClosure?(kHeight)
                                                }
                                              }, completion: nil)
                                            } else {
                                              print("Invalid conditions for UIKeyboardWillChangeFrameNotification")
                                            }
    })
  }

  func removeKeyboardObserver() {
    removeObserver(self, notificationName: NSNotification.Name.UIKeyboardWillChangeFrame)
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 更多"Swift"比其他解决方案更好/可以在每个控制器中重复使用而无需重写所有内容 - >绝对是最好的一个:) (2认同)

Fré*_*dda 6

我创建了一个Swift 3协议来处理键盘外观/消失

import UIKit

protocol KeyboardHandler: class {

var bottomConstraint: NSLayoutConstraint! { get set }

    func keyboardWillShow(_ notification: Notification)
    func keyboardWillHide(_ notification: Notification)
    func startObservingKeyboardChanges()
    func stopObservingKeyboardChanges()
}


extension KeyboardHandler where Self: UIViewController {

    func startObservingKeyboardChanges() {

        // NotificationCenter observers
        NotificationCenter.default.addObserver(forName: NSNotification.Name.UIKeyboardWillShow, object: nil, queue: nil) { [weak self] notification in
          self?.keyboardWillShow(notification)
        }

        // Deal with rotations
        NotificationCenter.default.addObserver(forName: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil, queue: nil) { [weak self] notification in
          self?.keyboardWillShow(notification)
        }

        // Deal with keyboard change (emoji, numerical, etc.)
        NotificationCenter.default.addObserver(forName: NSNotification.Name.UITextInputCurrentInputModeDidChange, object: nil, queue: nil) { [weak self] notification in
          self?.keyboardWillShow(notification)
        }

        NotificationCenter.default.addObserver(forName: NSNotification.Name.UIKeyboardWillHide, object: nil, queue: nil) { [weak self] notification in
          self?.keyboardWillHide(notification)
        }
    }


    func keyboardWillShow(_ notification: Notification) {

      let verticalPadding: CGFloat = 20 // Padding between the bottom of the view and the top of the keyboard

      guard let value = notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue else { return }
      let keyboardHeight = value.cgRectValue.height

      // Here you could have more complex rules, like checking if the textField currently selected is actually covered by the keyboard, but that's out of this scope.
      self.bottomConstraint.constant = keyboardHeight + verticalPadding

      UIView.animate(withDuration: 0.1, animations: { () -> Void in
          self.view.layoutIfNeeded()
      })
  }


  func keyboardWillHide(_ notification: Notification) {
      self.bottomConstraint.constant = 0

      UIView.animate(withDuration: 0.1, animations: { () -> Void in
          self.view.layoutIfNeeded()
      })
  }


  func stopObservingKeyboardChanges() {
      NotificationCenter.default.removeObserver(self)
  }

}
Run Code Online (Sandbox Code Playgroud)

然后,要在UIViewController中实现它,请执行以下操作:

  • 让viewController符合这个协议:

    class FormMailVC: UIViewControlle, KeyboardHandler {
    
    Run Code Online (Sandbox Code Playgroud)
  • 开始观察viewWillAppear中的键盘更改:

    // MARK: - View controller life cycle
    override func viewWillAppear(_ animated: Bool) {
      super.viewWillAppear(animated)
      startObservingKeyboardChanges()
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 停止观察viewWillDisappear中的键盘更改:

    override func viewWillDisappear(_ animated: Bool) {
      super.viewWillDisappear(animated)
      stopObservingKeyboardChanges()
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 从故事板为底部约束创建一个IBOutlet:

    // NSLayoutConstraints
    @IBOutlet weak var bottomConstraint: NSLayoutConstraint!
    
    Run Code Online (Sandbox Code Playgroud)

    (我建议将所有UI嵌入到"contentView"中,并将此contentView的底部约束链接到底部布局指南) 内容视图底部约束

  • 顶部约束的约束优先级更改为250(低)

内容视图顶部约束

这是为了让键盘出现时整个内容视图向上滑动.优先级必须低于子视图中的任何其他约束优先级,包括拥抱优先级/内容压缩阻力优先级的内容.

  • 确保您的Autolayout有足够的约束来确定contentView应该如何向上滑动.

您可能必须为此添加"大于等于"的约束:

你走吧! 没有键盘

用键盘


Abd*_*rim 5

您可以使用此库,只需完成appDidFinishedLaunching和u中的一行代码即可。

func application(application: UIApplication,didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

    IQKeyboardManager.sharedManager().enable = true
    return true
}
Run Code Online (Sandbox Code Playgroud)

IQKeyboardManager-每当键盘出现链接时调整视图-https: //github.com/hackiftekhar/IQKeyboardManager


Mes*_*ery 5

fr\xc3\xa9d\xc3\xa9ric-addaSwift 5的解决方案:

\n
\nprotocol KeyboardHandler: class {\n    var bottomConstraint: NSLayoutConstraint! { get set }\n    \n    func keyboardWillShow(_ notification: Notification)\n    func keyboardWillHide(_ notification: Notification)\n    func startObservingKeyboardChanges()\n    func stopObservingKeyboardChanges()\n}\n\n\nextension KeyboardHandler where Self: UIViewController {\n\n    func startObservingKeyboardChanges() {\n\n        // NotificationCenter observers\n        NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillShowNotification, object: nil, queue: nil) { [weak self] notification in\n          self?.keyboardWillShow(notification)\n        }\n\n        // Deal with rotations\n        NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillChangeFrameNotification, object: nil, queue: nil) { [weak self] notification in\n          self?.keyboardWillShow(notification)\n        }\n\n        // Deal with keyboard change (emoji, numerical, etc.)\n        NotificationCenter.default.addObserver(forName: UITextInputMode.currentInputModeDidChangeNotification, object: nil, queue: nil) { [weak self] notification in\n          self?.keyboardWillShow(notification)\n        }\n\n        NotificationCenter.default.addObserver(forName: UIResponder.keyboardWillHideNotification, object: nil, queue: nil) { [weak self] notification in\n          self?.keyboardWillHide(notification)\n        }\n    }\n\n\n    func keyboardWillShow(_ notification: Notification) {\n\n      let verticalPadding: CGFloat = 20 // Padding between the bottom of the view and the top of the keyboard\n\n        guard let value = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else { return }\n      let keyboardHeight = value.cgRectValue.height\n\n      // Here you could have more complex rules, like checking if the textField currently selected is actually covered by the keyboard, but that\'s out of this scope.\n      self.bottomConstraint.constant = keyboardHeight + verticalPadding\n\n      UIView.animate(withDuration: 0.1, animations: { () -> Void in\n          self.view.layoutIfNeeded()\n      })\n  }\n\n\n  func keyboardWillHide(_ notification: Notification) {\n      self.bottomConstraint.constant = 0\n\n      UIView.animate(withDuration: 0.1, animations: { () -> Void in\n          self.view.layoutIfNeeded()\n      })\n  }\n\n\n  func stopObservingKeyboardChanges() {\n      NotificationCenter.default.removeObserver(self)\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

在任何UIViewController

\n
    \n
  • 符合KeyboardHandler协议
  • \n
\n
extension AnyViewController: KeyboardHandler {} \n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  • 为屏幕上最后一个底部元素添加底部约束。
  • \n
\n
@IBOutlet var bottomConstraint: NSLayoutConstraint! \n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  • 添加观察者订阅/取消订阅:
  • \n
\n
 override func viewWillAppear(_ animated: Bool) {\n        super.viewWillAppear(animated)\n        startObservingKeyboardChanges()\n }\n    \n override func viewWillDisappear(_ animated: Bool) {\n        super.viewWillDisappear(animated)\n        stopObservingKeyboardChanges()\n }\n
Run Code Online (Sandbox Code Playgroud)\n

享受!

\n