我使用Swift与iOS编程,我使用这段代码来移动UITextField,但它不起作用。我正确地调用了函数keyboardWillShow,但是文本字段没有移动。我正在使用自动布局。

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")
    }
}

当前回答

我喜欢简洁的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
    )

}

注意:这段代码涵盖了大多数注释/一般情况。然而,处理不同的方向和/或自定义键盘可能需要更多的代码。如果你需要处理每一个场景,这可能会有所帮助。

其他回答

编辑:我推荐一个更简单、更干净的解决方案。只需将底部间距约束的类更改为KeyboardLayoutConstraint。它会自动展开到键盘高度。


这是一个改进版的@JosephLord的回答。

在iOS 8.3 iPad模拟器上测试,Portrait。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)
        }
    }

另一个解决方案,不依赖于自动布局,约束或任何出口。您所需要的是滚动视图中的字段。

override func viewDidLoad() {
    super.viewDidLoad()

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

func makeSpaceForKeyboard(notification: NSNotification) {
    let info = notification.userInfo!
    let keyboardHeight:CGFloat = (info[UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue().size.height
    let duration:Double = info[UIKeyboardAnimationDurationUserInfoKey] as! Double

    if notification.name == UIKeyboardWillShowNotification {
        UIView.animateWithDuration(duration, animations: { () -> Void in
            var frame = self.view.frame
            frame.size.height = frame.size.height - keyboardHeight
            self.view.frame = frame
        })
    } else {
        UIView.animateWithDuration(duration, animations: { () -> Void in
            var frame = self.view.frame
            frame.size.height = frame.size.height + keyboardHeight
            self.view.frame = frame
        })
    }

}

我创建了一个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)
  }

}

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

let the viewController conform to this protocol : class FormMailVC: UIViewControlle, KeyboardHandler { start observing keyboard changes in viewWillAppear: // MARK: - View controller life cycle override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) startObservingKeyboardChanges() } stop observing keyboard changes in viewWillDisappear: override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) stopObservingKeyboardChanges() } create an IBOutlet for the bottom constraint from the storyboard: // NSLayoutConstraints @IBOutlet weak var bottomConstraint: NSLayoutConstraint! (I recommend having all of your UI embedded inside a "contentView", and linking to this property the bottom constraint from this contentView to the bottom layout guide) change the constraint priority of the top constraint to 250 (low)

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

确保你的自动布局有足够的约束来决定contentView应该如何滑动。

你可能需要添加一个“大于等于”的约束:

给你!

我正在使用swift 4,我解决了这个问题,没有使用任何额外的底部约束,看我的代码在这里。这对我的案子很有帮助

1)在did load中添加通知观察者

override func viewDidLoad() { super.viewDidLoad () setupManager () //加载视图后进行任何额外的设置。 addobserver (self, selector: #selector(self. keyboardwillshow), name: NSNotification.Name。对象:nil) addobserver (self, selector: #selector(self. keyboardwillhide), name: NSNotification.Name。对象:nil) }

2)删除通知观察者

Deinit { NotificationCenter.default.removeObserver(self) }

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()
            })
        }
    }

4)添加textfield delegate和touchesBegan方法。usefull用于在屏幕上的textfield外触摸时隐藏键盘

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

    }

非常简单,不需要编写更多代码。 只需在podfile中添加pod 'IQKeyboardManagerSwift',并在AppDelegate页面中添加下面的代码。

import IQKeyboardManagerSwift

在方法didFinishLaunchingWithOptions()类型中

IQKeyboardManager.shared.enable = true

就是这样。 查看这个视频链接,以更好地了解https://youtu.be/eOM94K1ZWN8 希望这对你有所帮助。