Перемещение текстового поля, когда клавиатура отображается быстро

Я использую 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") } } 

25 Solutions collect form web for “Перемещение текстового поля, когда клавиатура отображается быстро”

Есть несколько улучшений в существующих ответах.

Во-первых, 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 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 (endFrame?.origin.y)! >= 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) } } 

Swift 2.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 NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.keyboardNotification(_:)), name: UIKeyboardWillChangeFrameNotification, object: nil) } deinit { NSNotificationCenter.defaultCenter().removeObserver(self) } func keyboardNotification(notification: NSNotification) { 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) if endFrame?.origin.y >= UIScreen.mainScreen().bounds.size.height { self.keyboardHeightLayoutConstraint?.constant = 0.0 } else { self.keyboardHeightLayoutConstraint?.constant = endFrame?.size.height ?? 0.0 } UIView.animateWithDuration(duration, delay: NSTimeInterval(0), options: animationCurve, animations: { self.view.layoutIfNeeded() }, completion: nil) } } 

(Отредактировано для учета анимирования клавиатуры вне экрана вместо сокращения, согласно замечанию @ Gabox's awesome ниже)

Если вы используете автоматический макет, я предполагаю, что вы установили ограничение Bottom Space на Superview . Если это так, вам просто нужно обновить значение ограничения. Вот как вы делаете это с небольшой анимацией.

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

Hardcoded 20 добавляется только для того, чтобы немного погладить текстовое поле над клавиатурой. В противном случае верхний край клавиатуры и нижнее поле текстового поля будут касаться.

Когда клавиатура уволена, сбросьте значение ограничения на исходное.

Простым решением является перемещение вверх с постоянной высоты клавиатуры.

 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 } 

Swift 3

  NotificationCenter.default.addObserver(self, selector: #selector(RegisterViewController.keyboardWillShow(sender:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(RegisterViewController.keyboardWillHide(sender:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil) 

Для перемещения вашего вида во время редактирования текстового поля попробуйте это, я применил это, его работа отлично

 func textFieldDidBeginEditing(textField: UITextField) { animateViewMoving(true, moveValue: 100) } func textFieldDidEndEditing(textField: UITextField) { animateViewMoving(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() } 

Я получил этот ответ из этого источника UITextField, когда клавиатура появляется в Swift

Я люблю чистый код Swift. Итак, вот самый жесткий код, который я мог бы придумать для перемещения текстового представления вверх / вниз с помощью клавиатуры. В настоящее время он работает в приложении iOS8 / 9 Swift 2.

ОБНОВЛЕНИЕ (март 2016 года): Я как можно больше подтянул свой предыдущий код. Кроме того, здесь есть множество популярных ответов, в которых жестко задаются параметры высоты и анимации клавиатуры. Нет необходимости в этом, не говоря уже о том, что цифры в этих ответах не всегда совпадают с фактическими значениями, которые я вижу на своих 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 ) } 

ПРИМЕЧАНИЕ. Этот код охватывает большинство комментариев / общий случай. Тем не менее, для обработки различных ориентаций и / или пользовательских клавиатур может потребоваться больше кода. Ниже приведена подробная статья о работе с клавиатурой iOS. Если вам нужно обрабатывать все сценарии, это может помочь.

Изменить : я рекомендую более простое и чистое решение. Просто измените класс ограничения нижнего интервала на KeyboardLayoutConstraint . Он автоматически расширится до высоты клавиатуры.


Это улучшенная версия ответа @JosephLord.

Как протестировано на iOS 8.3 iPad Simulator, 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) } } 

Это улучшенная версия ответов @JosephLord и @ Hlung. Он может применяться, есть ли у вас панель или нет. И это прекрасно восстановит вид, который перемещается клавиатурой в исходное положение.

 // 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) } } 
 struct MoveKeyboard { static let KEYBOARD_ANIMATION_DURATION : CGFloat = 0.3 static let MINIMUM_SCROLL_FRACTION : CGFloat = 0.2; static let MAXIMUM_SCROLL_FRACTION : CGFloat = 0.8; static let PORTRAIT_KEYBOARD_HEIGHT : CGFloat = 216; static let LANDSCAPE_KEYBOARD_HEIGHT : CGFloat = 162; } func textFieldDidBeginEditing(textField: UITextField) { let textFieldRect : CGRect = self.view.window!.convertRect(textField.bounds, fromView: textField) let viewRect : CGRect = self.view.window!.convertRect(self.view.bounds, fromView: self.view) let midline : CGFloat = textFieldRect.origin.y + 0.5 * textFieldRect.size.height let numerator : CGFloat = midline - viewRect.origin.y - MoveKeyboard.MINIMUM_SCROLL_FRACTION * viewRect.size.height let denominator : CGFloat = (MoveKeyboard.MAXIMUM_SCROLL_FRACTION - MoveKeyboard.MINIMUM_SCROLL_FRACTION) * viewRect.size.height var heightFraction : CGFloat = numerator / denominator if heightFraction < 0.0 { heightFraction = 0.0 } else if heightFraction > 1.0 { heightFraction = 1.0 } let orientation : UIInterfaceOrientation = UIApplication.sharedApplication().statusBarOrientation if (orientation == UIInterfaceOrientation.Portrait || orientation == UIInterfaceOrientation.PortraitUpsideDown) { animateDistance = floor(MoveKeyboard.PORTRAIT_KEYBOARD_HEIGHT * heightFraction) } else { animateDistance = floor(MoveKeyboard.LANDSCAPE_KEYBOARD_HEIGHT * heightFraction) } var viewFrame : CGRect = self.view.frame viewFrame.origin.y -= animateDistance UIView.beginAnimations(nil, context: nil) UIView.setAnimationBeginsFromCurrentState(true) UIView.setAnimationDuration(NSTimeInterval(MoveKeyboard.KEYBOARD_ANIMATION_DURATION)) self.view.frame = viewFrame UIView.commitAnimations() } func textFieldDidEndEditing(textField: UITextField) { var viewFrame : CGRect = self.view.frame viewFrame.origin.y += animateDistance UIView.beginAnimations(nil, context: nil) UIView.setAnimationBeginsFromCurrentState(true) UIView.setAnimationDuration(NSTimeInterval(MoveKeyboard.KEYBOARD_ANIMATION_DURATION)) self.view.frame = viewFrame UIView.commitAnimations() } 

И, наконец, поскольку мы используем методы делегатов

 func textFieldShouldReturn(textField: UITextField) -> Bool { textField.resignFirstResponder() return true } 

рефакторинг с использованием объектно-с http://www.cocoawithlove.com/2008/10/sliding-uitextfields-around-to-avoid.html

Другое решение, которое не зависит от автоматического отключения, ограничений или любых выходов. То, что вам нужно, это ваше поле (ы) в scrollview.

 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 2.2:

Первый регистр для показа / закрытия уведомлений клавиатуры

 NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(MessageThreadVC.keyboardWillShow(_:)), name: UIKeyboardWillShowNotification, object: nil) NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(MessageThreadVC.keyboardWillHide(_:)), name: UIKeyboardWillHideNotification, object: nil) 

Затем в методах, отвечающих за эти уведомления, перемещается основной вид вверх или вниз

 func keyboardWillShow(sender: NSNotification) { if let keyboardSize = (sender.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue() { self.view.frame.origin.y = -keyboardSize.height } } func keyboardWillHide(sender: NSNotification) { self.view.frame.origin.y = 0 } 

Трюк находится в разделе «keyboardWillShow», который получает вызовы каждый раз, когда «панель подсказок QuickType» расширяется или сворачивается. Затем мы всегда устанавливаем координату y основного вида, которая равна отрицательному значению общей высоты клавиатуры (с или без части «QuickType bar»).

В конце не забудьте удалить наблюдателей

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

Я использовал этот учебник для перемещения текстового поля над клавиатурой. Код чист и не глючит.

http://www.buildsucceeded.com/2014/swift-move-uitextfield-so-keyboard-does-not-hide-it-ios-8-xcode-6-swift/

Следующее – простое решение, при котором текстовое поле имеет ограничение, связывающее его с нижним макетом. Он просто добавляет высоту клавиатуры к константе ограничения.

 // This constraint ties the text field to the bottom layout guide @IBOutlet var textFieldToBottomLayoutGuideConstraint: NSLayoutConstraint! override func viewDidLoad() { super.viewDidLoad() NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillShow:", name:UIKeyboardWillShowNotification, object: nil); NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillHide:", name:UIKeyboardWillHideNotification, object: nil); } func keyboardWillShow(sender: NSNotification) { if let keyboardSize = (sender.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() { self.textFieldToBottomLayoutGuideConstraint?.constant += keyboardSize.height } } func keyboardWillHide(sender: NSNotification) { if let keyboardSize = (sender.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() { self.textFieldToBottomLayoutGuideConstraint?.constant -= keyboardSize.height } } 

Ну, я думаю, что может быть слишком поздно, но я нашел еще одну простую версию ответа Сакиба. Я использую Autolayout с ограничениями. У меня есть небольшой вид внутри другого основного вида с полями имени пользователя и пароля. Вместо изменения y-координаты представления я сохраняю исходное значение ограничения в переменной и изменяю константу ограничения на некоторое значение, и снова после отклонения клавиатуры я устанавливаю ограничение на исходное. Таким образом, он избегает проблемы, с которой отвечает Сакиб, (вид продолжает двигаться вверх и не останавливается). Ниже мой код …

 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); self.originalConstraint = self.centerYConstraint.constant } func keyboardWillShow(sender: NSNotification) { self.centerYConstraint.constant += 30 } func keyboardWillHide(sender: NSNotification) { self.centerYConstraint.constant = self.originalConstraint } 

Я сделал следующее:

Это полезно, когда просмотр суперполя выглядит

 class AdminLoginViewController: UIViewController, UITextFieldDelegate{ @IBOutlet weak var txtUserName: UITextField! @IBOutlet weak var txtUserPassword: UITextField! @IBOutlet weak var btnAdminLogin: UIButton! private var activeField : UIView? var param:String! var adminUser : Admin? = nil var kbHeight: CGFloat! override func viewDidLoad() { self.addKeyBoardObserver() self.addGestureForHideKeyBoard() } override func viewWillDisappear(animated: Bool) { super.viewWillDisappear(animated) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } func addGestureForHideKeyBoard() { let tapGesture = UITapGestureRecognizer(target: self, action: Selector("hideKeyboard")) tapGesture.cancelsTouchesInView = false view.addGestureRecognizer(tapGesture) } func hideKeyboard() { self.view.endEditing(true) } func addKeyBoardObserver(){ NSNotificationCenter.defaultCenter().addObserver(self, selector: "willChangeKeyboardFrame:", name:UIKeyboardWillShowNotification, object: nil) NSNotificationCenter.defaultCenter().addObserver(self, selector: "willChangeKeyboardFrame:", name:UIKeyboardWillHideNotification, object: nil) } func removeObserver(){ NSNotificationCenter.defaultCenter().removeObserver(self) } //MARK:- textfiled Delegate func textFieldShouldBeginEditing(textField: UITextField) -> Bool { activeField = textField return true } func textFieldShouldEndEditing(textField: UITextField) -> Bool { if activeField == textField { activeField = nil } return true } func textFieldShouldReturn(textField: UITextField) -> Bool { if txtUserName == textField { txtUserPassword.becomeFirstResponder() } else if (textField == txtUserPassword) { self.btnAdminLoginAction(nil) } return true; } func willChangeKeyboardFrame(aNotification : NSNotification) { if self.activeField != nil && self.activeField!.isFirstResponder() { if let keyboardSize = (aNotification.userInfo![UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() { let dy = (self.activeField?.superview?.convertRect((self.activeField?.frame)!, toView: view).origin.y)! let height = (self.view.frame.size.height - keyboardSize.size.height) if dy > height { var frame = self.view.frame frame.origin.y = -((dy - height) + (self.activeField?.frame.size.height)! + 20) self.view.frame = frame } } } else { var frame = self.view.frame frame.origin.y = 0 self.view.frame = frame } } } 

Самый простой способ, который не требует никакого кода:

  1. Загрузите KeyboardLayoutConstraint.swift и добавьте (перетащите и перетащите) файл в свой проект, если вы уже не используете фреймворк Spring.
  2. В своем раскадровке создайте нижнее ограничение для объекта / вида / текстового поля, выберите ограничение (дважды щелкните его) и в Identity Inspector, измените его класс с NSLayoutConstraint на KeyboardLayoutConstraint.
  3. Готово!

Объект будет автоматически перемещаться с помощью клавиатуры в синхронизации.

Такое простое расширение 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) } } 

Example of usage

 override func viewWillDisappear(animated: Bool) { super.viewDidDisappear(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() }) } 
  func registerForKeyboardNotifications() { //Keyboard NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(keyboardWasShown), name: UIKeyboardDidShowNotification, object: nil) NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(keyboardWillBeHidden), name: UIKeyboardDidHideNotification, object: nil) } func deregisterFromKeyboardNotifications(){ NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil) NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil) } func keyboardWasShown(notification: NSNotification){ let userInfo: NSDictionary = notification.userInfo! let keyboardInfoFrame = userInfo.objectForKey(UIKeyboardFrameEndUserInfoKey)?.CGRectValue() let windowFrame:CGRect = (UIApplication.sharedApplication().keyWindow!.convertRect(self.view.frame, fromView:self.view)) let keyboardFrame = CGRectIntersection(windowFrame, keyboardInfoFrame!) let coveredFrame = UIApplication.sharedApplication().keyWindow!.convertRect(keyboardFrame, toView:self.view) let contentInsets = UIEdgeInsetsMake(0, 0, (coveredFrame.size.height), 0.0) self.scrollViewInAddCase .contentInset = contentInsets; self.scrollViewInAddCase.scrollIndicatorInsets = contentInsets; self.scrollViewInAddCase.contentSize = CGSizeMake((self.scrollViewInAddCase.contentSize.width), (self.scrollViewInAddCase.contentSize.height)) } /** this method will fire when keyboard was hidden - parameter notification: contains keyboard details */ func keyboardWillBeHidden (notification: NSNotification) { self.scrollViewInAddCase.contentInset = UIEdgeInsetsZero self.scrollViewInAddCase.scrollIndicatorInsets = UIEdgeInsetsZero } 

I created a Swift 3 protocol to handle the keyboard appearance / disappearance

 import Foundation 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) { (notification) in self.keyboardWillShow(notification) } // Deal with rotations NotificationCenter.default.addObserver(forName: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil, queue: nil) { (notification) in self.keyboardWillShow(notification) } // Deal with keyboard change (emoji, numerical, etc.) NotificationCenter.default.addObserver(forName: NSNotification.Name.UITextInputCurrentInputModeDidChange, object: nil, queue: nil) { (notification) in self.keyboardWillShow(notification) } NotificationCenter.default.addObserver(forName: NSNotification.Name.UIKeyboardWillHide, object: nil, queue: nil) { (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) } } 

Then, to implement it in a UIViewController, do the following:

  • 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) Content view bottom constraint

  • change the constraint priority of the top constraint to 250 (low)

Content view top constraint

This is to let the whole content view slide upwards when the keyboard appears. The priority must be lower than any other constraint priority in the subviews, including content hugging priorities / content compression resistance priorities.

  • Make sure that your Autolayout has enough constraints to determine how the contentView should slide up.

You may have to add a "greater than equal" constraint for this: "greater than equal" constraint

And here you go! Without keyboard

With keyboard

I have done in following manner :

 class SignInController: UIViewController , UITextFieldDelegate { @IBOutlet weak var scrollView: UIScrollView! // outlet declartion @IBOutlet weak var signInTextView: UITextField! var kbHeight: CGFloat! /** * * @method viewDidLoad * */ override func viewDidLoad() { super.viewDidLoad() self.signInTextView.delegate = self }// end viewDidLoad /** * * @method viewWillAppear * */ override func viewWillAppear(animated: Bool) { super.viewWillAppear(animated) NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name: UIKeyboardWillShowNotification, object: nil) NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name: UIKeyboardWillHideNotification, object: nil) }// end viewWillAppear /** * * @method viewDidAppear * */ override func viewDidAppear(animated: Bool) { super.viewDidAppear(animated) }// end viewDidAppear /** * * @method viewWillDisappear * */ override func viewWillDisappear(animated: Bool) { super.viewWillDisappear(animated) NSNotificationCenter.defaultCenter().removeObserver(self) } /** * * @method textFieldShouldReturn * retun the keyboard value * */ // MARK - func textFieldShouldReturn(textField: UITextField) -> Bool { signInTextView.resignFirstResponder() return true; }// end textFieldShouldReturn // MARK - keyboardWillShow func keyboardWillShow(notification: NSNotification) { if let userInfo = notification.userInfo { if let keyboardSize = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() { kbHeight = keyboardSize.height self.animateTextField(true) } } }// end keyboardWillShow // MARK - keyboardWillHide func keyboardWillHide(notification: NSNotification) { self.animateTextField(false) }// end keyboardWillHide // MARK - animateTextField func animateTextField(up: Bool) { var movement = (up ? -kbHeight : kbHeight) UIView.animateWithDuration(0.3, animations: { self.view.frame = CGRectOffset(self.view.frame, 0, movement) }) }// end animateTextField /** * * @method didReceiveMemoryWarning * */ override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. }// end didReceiveMemoryWarning }// end SignInController 

You can use this library and just one line of code in appDidFinishedLaunching and u are done..

 func application(application: UIApplication,didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { IQKeyboardManager.sharedManager().enable = true return true } 

IQKeyboardManager – adjust view whenever keyboard appear link – https://github.com/hackiftekhar/IQKeyboardManager

If you are like me who has tried all the above solutions and still your problem is not solved, I have a got a great solution for you that works like a charm. First I want clarify few things about some of solutions mentioned above.

  1. In my case IQkeyboardmanager was working only when there is no auto layout applied on the elements, if it is applied then IQkeyboard manager will not work the way we think.
  2. Same thing with upward movement of self.view.
  3. i have wriiten a objective c header with a swift support for pushing UITexfield upward when user clicks on it, solving the problem of keyboard covering the UITextfield : https://github.com/coolvasanth/smart_keyboard .
  4. One who has An intermediate or higher level in iOS app development can easily understand the repository and implement it. All the best

If you don't mind using Objective-C library in your Swift project, perhaps you can use this helper . It comes with an example for Swift usage too.

I modified @Simpa solution a little bit………

 override func viewDidLoad() { super.viewDidLoad() NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("makeSpaceForKeyboard:"), name:UIKeyboardWillShowNotification, object: nil); NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("makeSpaceForKeyboard:"), name:UIKeyboardWillHideNotification, object: nil); } deinit{ NSNotificationCenter.defaultCenter().removeObserver(self) } var keyboardIsVisible = false override 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 && keyboardIsVisible == false{ keyboardIsVisible = true UIView.animateWithDuration(duration, animations: { () -> Void in var frame = self.view.frame frame.size.height = frame.size.height - keyboardHeight self.view.frame = frame }) } else if keyboardIsVisible == true && notification.name == UIKeyboardWillShowNotification{ }else { keyboardIsVisible = false UIView.animateWithDuration(duration, animations: { () -> Void in var frame = self.view.frame frame.size.height = frame.size.height + keyboardHeight self.view.frame = frame }) } } 

None of them worked for and I ended up using content insets to move my view up when the keyboard appears.

Note: I was using a UITableView

Referenced solution @ keyboard-content-offset which was entirely written in objective C, the below solution is clean Swift.

Add the notification observer @ viewDidLoad()

 NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(yourClass.keyboardWillBeShown), name:UIKeyboardWillShowNotification, object: nil); NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(yourClass.keyboardWillBeHidden), name:UIKeyboardWillHideNotification, object: nil); 

To get the keyboard size, we first get the userInfo dictionary from the notification object, which stores any additional objects that our receiver might use.

From that dictionary we can get the CGRect object describing the keyboard's frame by using the key UIKeyboardFrameBeginUserInfoKey.

Apply the content inset for the table view @ keyboardWillBeShown method,

 func keyboardWillBeShown(sender: NSNotification) { // Move the table view if let keyboardSize = (sender.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.CGRectValue() { let contentInsets = UIEdgeInsetsMake(0.0, 0.0, (keyboardSize.height), 0.0); yourTableView.contentInset = contentInsets; yourTableView.scrollIndicatorInsets = contentInsets; } } 

Restore the view @ keyboardWillBeHidden method

 func keyboardWillBeHidden(sender: NSNotification) { // Moving back the table view back to the default position yourTableView.contentInset = UIEdgeInsetsZero; yourTableView.scrollIndicatorInsets = UIEdgeInsetsZero; } 

If you want to keep the device orientation also into consideration, use conditional statements to tailor the code to your needs.

 // Portrait UIEdgeInsetsMake(0.0, 0.0, (keyboardSize.height), 0.0); // Landscape UIEdgeInsetsMake(0.0, 0.0, (keyboardSize.width), 0.0); 
 override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil) } func keyboardWillShow(_ notification:Notification) { if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue { tableView.contentInset = UIEdgeInsetsMake(0, 0, keyboardSize.height, 0) } } func keyboardWillHide(_ notification:Notification) { if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue { tableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0) } } [enter image description here][1] 
  • UITextField не прокручивается до конца после реализации textRectForBounds и редактированияRectForBounds в подклассе?
  • Изменение размера текстового поля при вводе большого текста
  • Подзаголовок UITextField UIImageView не отвечает на события касания
  • Назначить себя UITextFieldDelegate работает в iOS 8 не в iOS 7
  • Переместите UITextField в пользовательский UITableViewCell в центр экрана, чтобы клавиатура не закрывала его
  • willTransitionToState (UITableViewCell) не вызывается в определенной ситуации
  • Shake Animation для UITextField / UIView в Swift
  • UITextField в UIAlertController (border, backgroundColor)
  • Использование UITextInput протокола для UITextField и UITextView для управления результатами отбора при сбое
  • Добавление кнопки отмены на клавиатуру UITextField
  • UIAlertController не является иерархией окон
  • Interesting Posts

    Facebook iOS SDK-Mobile App Install Отслеживание не работает

    Передача данных из всплывающего контроллера

    Как обнаружить Retina Display в MonoTouch

    Разница между двумя объектами NSDate – результат также NSDate

    Размер приложения для iphone меньше экрана

    Как написать единичный тест для получения асинхронности nsnotification?

    iAd Banner не отображается в одобренном приложении для iPhone

    Что такое регулярное выражение для этих случаев?

    Пользовательская анимация Segue

    WebAPI не может анализировать сообщение multipart / form-data

    Как диагностировать сбои в dlopen () на устройствах iOS

    Запрос запроса журнала AFNetworking для многочастных / форм-данных

    Прокрутите UITextField над клавиатурой в UITableViewCell на обычном UIViewController

    SceneKit и CoreMotion «отстают» на iPhone 5, но нормально на iPhone 6

    Обратный отсчет NSTimer в заголовке UIAlertController, получающий нуль вместо времени в секундах

    PhoneC: Разработка iOS проста с помощью XCode, Swift3, UITableView, cocatouch, давайте создадим приложения для iPhone, iPad и Macbook.