it-swarm.com.ru

Переместить вид с клавиатуры с помощью Swift

У меня есть приложение, у которого есть текстовое поле в нижней части представления . Это означает, что, когда я иду печатать в текстовом поле, клавиатура закрывает текстовое поле.

Как бы я переместил вид вверх при наборе текста, чтобы я мог видеть то, что я печатаю, а затем переместил его обратно на исходное место, когда клавиатура исчезла?

Я искал повсюду, но все решения, похоже, в Obj-C, которые я пока не могу конвертировать.

Любая помощь будет принята с благодарностью.

222
Alex Catchpole

Вот решение без обработки переключения с одного textField на другое:

 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(notification: NSNotification) {            
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
        self.view.frame.Origin.y -= keyboardSize.height
    }            
}

func keyboardWillHide(notification: NSNotification) {
    self.view.frame.Origin.y = 0
}

Чтобы решить эту проблему, замените две функции keyboardWillShow/Hide на эти:

func keyboardWillShow(notification: NSNotification) {        
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
        if view.frame.Origin.y == 0 {
            self.view.frame.Origin.y -= keyboardSize.height
        }
    }        
}

func keyboardWillHide(notification: NSNotification) {
    if view.frame.Origin.y != 0 {
        self.view.frame.Origin.y = 0
    }
}

РЕДАКТИРОВАТЬ ДЛЯ Swift 3.0:

override func viewDidLoad() {
    super.viewDidLoad()            
    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)    
}

@objc func keyboardWillShow(notification: NSNotification) {        
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
        if self.view.frame.Origin.y == 0 {
            self.view.frame.Origin.y -= keyboardSize.height
        }
    }        
}

@objc func keyboardWillHide(notification: NSNotification) {
    if self.view.frame.Origin.y != 0 {
        self.view.frame.Origin.y = 0
    }
}

РЕДАКТИРОВАТЬ ДЛЯ Swift 4.0:

override func viewDidLoad() {
    super.viewDidLoad()            
    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)    
}

@objc func keyboardWillShow(notification: NSNotification) {        
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
        if self.view.frame.Origin.y == 0 {
            self.view.frame.Origin.y -= keyboardSize.height
        }
    }        
}

@objc func keyboardWillHide(notification: NSNotification) {
    if self.view.frame.Origin.y != 0 {
        self.view.frame.Origin.y = 0
    }
}

РЕДАКТИРОВАТЬ ДЛЯ Swift 4.2:

override func viewDidLoad() {
    super.viewDidLoad()            
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
}

@objc func keyboardWillShow(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
        if self.view.frame.Origin.y == 0 {
            self.view.frame.Origin.y -= keyboardSize.height
        }
    }
}

@objc func keyboardWillHide(notification: NSNotification) {
    if self.view.frame.Origin.y != 0 {
        self.view.frame.Origin.y = 0
    }
}
564
Boris

Один из популярных ответов в этой теме использует следующий код: 

func keyboardWillShow(sender: NSNotification) {
    self.view.frame.Origin.y -= 150
}
func keyboardWillHide(sender: NSNotification) {
    self.view.frame.Origin.y += 150
}

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

Вот решение, которое работает на всех устройствах и обрабатывает Edge-случай, когда пользователь скрывает предиктивное текстовое поле при вводе.

Решение

Важно отметить, что мы передаем self.view.window в качестве нашего параметра объекта. Это предоставит нам данные с нашей клавиатуры, такие как ее высота!

@IBOutlet weak var messageField: UITextField!

override func viewDidLoad() {
    super.viewDidLoad()

    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name:UIKeyboardWillShowNotification, object: self.view.window)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name:UIKeyboardWillHideNotification, object: self.view.window)
}

func keyboardWillHide(sender: NSNotification) {
    let userInfo: [NSObject : AnyObject] = sender.userInfo!
    let keyboardSize: CGSize = userInfo[UIKeyboardFrameBeginUserInfoKey]!.CGRectValue.size
    self.view.frame.Origin.y += keyboardSize.height
}

Мы сделаем так, чтобы он выглядел хорошо на всех устройствах, и разберем случай, когда пользователь добавляет или удаляет интеллектуальное текстовое поле.

func keyboardWillShow(sender: NSNotification) {
    let userInfo: [NSObject : AnyObject] = sender.userInfo!
    let keyboardSize: CGSize = userInfo[UIKeyboardFrameBeginUserInfoKey]!.CGRectValue.size
    let offset: CGSize = userInfo[UIKeyboardFrameEndUserInfoKey]!.CGRectValue.size

    if keyboardSize.height == offset.height {
        UIView.animateWithDuration(0.1, animations: { () -> Void in
            self.view.frame.Origin.y -= keyboardSize.height
        })
    } else {
        UIView.animateWithDuration(0.1, animations: { () -> Void in
            self.view.frame.Origin.y += keyboardSize.height - offset.height
        })
    }
}

Удалить наблюдателей

Не забудьте удалить своих наблюдателей, прежде чем покинуть вид, чтобы предотвратить передачу ненужных сообщений.

override func viewWillDisappear(animated: Bool) {
    NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: self.view.window)
    NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: self.view.window)
}

Обновление на основе вопроса из комментариев:

Если у вас есть два или более текстовых поля, вы можете проверить, равен ли ваш view.frame.Origin.y нулю. 

func keyboardWillShow(sender: NSNotification) {
    let userInfo: [NSObject : AnyObject] = sender.userInfo!

    let keyboardSize: CGSize = userInfo[UIKeyboardFrameBeginUserInfoKey]!.CGRectValue.size
    let offset: CGSize = userInfo[UIKeyboardFrameEndUserInfoKey]!.CGRectValue.size

    if keyboardSize.height == offset.height {
        if self.view.frame.Origin.y == 0 {
            UIView.animateWithDuration(0.1, animations: { () -> Void in
                self.view.frame.Origin.y -= keyboardSize.height
            })
        }
    } else {
        UIView.animateWithDuration(0.1, animations: { () -> Void in
            self.view.frame.Origin.y += keyboardSize.height - offset.height
        })
    }
     print(self.view.frame.Origin.y)
}
63
Dan Beaulieu

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

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

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

62
gammachill

Добавьте это к вашему viewcontroller. Работает как шарм. Просто настройте значения.

override func viewDidLoad() {
    super.viewDidLoad()        
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name:NSNotification.Name.UIKeyboardWillShow, object: nil);
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name:NSNotification.Name.UIKeyboardWillHide, object: nil);
}

@objc func keyboardWillShow(sender: NSNotification) {
    self.view.frame.Origin.y -= 150
}
@objc func keyboardWillHide(sender: NSNotification) {
    self.view.frame.Origin.y += 150
}
30
user3677173

Я немного улучшил один из ответов, чтобы он работал с разными клавиатурами и различными текстовыми представлениями/полями на одной странице:

Добавить наблюдателей:  

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

    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChange(notification:)), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)

    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
}

func keyboardWillHide() {
    self.view.frame.Origin.y = 0
}

func keyboardWillChange(notification: NSNotification) {

    if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
        if YOURTEXTVIEW.isFirstResponder {
            self.view.frame.Origin.y = -keyboardSize.height
        }
    }
}

Удалить наблюдателей:

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

    NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
    NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
}
21
scipianne

Для ошибки черного экрана (Swift 4 и 4.2)

Я исправил проблему черного экрана. В проверенном решении Высота клавиатуры после нажатия изменяется, и это вызывает черный экран.

Необходимо использовать UIKeyboardFrameEndUserInfoKey вместо UIKeyboardFrameBeginUserInfoKey

var isKeyboardAppear = false

override func viewDidLoad() {
    super.viewDidLoad() 
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}

@objc func keyboardWillShow(notification: NSNotification) {
    if !isKeyboardAppear {
        if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
            if self.view.frame.Origin.y == 0{
                self.view.frame.Origin.y -= keyboardSize.height
            }
        }
        isKeyboardAppear = true
    }
}

@objc func keyboardWillHide(notification: NSNotification) {
    if isKeyboardAppear {
        if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
            if self.view.frame.Origin.y != 0{
                self.view.frame.Origin.y += keyboardSize.height
            }
        }
         isKeyboardAppear = false
    }
}
13
codeByThey

Я вижу, что все ответы перемещают само представление на величину высоты клавиатуры. Ну, у меня есть подробный ответ, который может быть полезен, если вы используете ограничения, т.е. autolayout, который перемещает представление путем изменения его значения ограничения (например, нижнего или верхнего ограничения) на предварительно определенное значение или вы можете использовать значение размера клавиатуры.

В этом примере я использую нижнее ограничение от текстового поля до Bottom Layout View с начальным значением 175.

@IBOutlet weak var bottomConstraint: NSLayoutConstraint!

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(notification: NSNotification) {
    //To retrieve keyboard size, uncomment following line
    //let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue()
    bottomConstraint.constant = 260
    UIView.animateWithDuration(0.3) {
        self.view.layoutIfNeeded()
    }
}

func keyboardWillHide(notification: NSNotification) {
    //To retrieve keyboard size, uncomment following line
    //let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue()
    bottomConstraint.constant = 175
    UIView.animateWithDuration(0.3) {
        self.view.layoutIfNeeded()
    }
}
12
Amro Shafie

В том, как мы определяем KeyboardWillHideNotification, произошли некоторые изменения.

Это решение работает с Swift 4.2

NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(ViewController.keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)


@objc func keyboardWillShow(_ notification:Notification) {
    if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
        self.view.frame.Origin.y -= keyboardSize.height
    }
}

@objc func keyboardWillHide(_ notification:Notification) {
    if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
        self.view.frame.Origin.y += keyboardSize.height
    }
}
7
Ivan Le Hjelmeland

Для Swift 3 я сделал подкласс UIViewController, так как мне нужно было постоянное поведение во всех контроллерах представления. 

class SomeClassVC: UIViewController {

  //MARK: - Lifecycle
  override func viewDidLoad() {
    super.viewDidLoad()

    addKeyboardObservers()
  }

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

    removeKeyboardObservers()
  }

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

  //MARK: - Help
  func addKeyboardObservers() {
    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)
  }

  func removeKeyboardObservers() {
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: self.view.window)
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: self.view.window)
  }

  func keyboardWillShow(notification: NSNotification) {
    let keyboardHeight = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.height
    UIView.animate(withDuration: 0.1, animations: { () -> Void in
      self.view.window?.frame.Origin.y = -1 * keyboardHeight!
      self.view.layoutIfNeeded()
    })
  }

  func keyboardWillHide(notification: NSNotification) {
    UIView.animate(withDuration: 0.1, animations: { () -> Void in
      self.view.window?.frame.Origin.y = 0
      self.view.layoutIfNeeded()
    })
  }

  func resignTextFieldFirstResponders() {
    for textField in self.view.subviews where textField is UITextField {
      textField.resignFirstResponder()
    }
  }

  func resignAllFirstResponders() {
      view.endEditing(true)
  }
}
6
Pavle Mijatovic

Я заметил, что другие ответы включали вырезание некоторых из верха из поля зрения. Если вы хотите просто изменить размер представления, не обрезая содержимое, попробуйте этот метод :)

func keyboardWillShow(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
        self.view.setTranslatesAutoresizingMaskIntoConstraints(true)
        self.view.frame = CGRectMake(self.view.frame.Origin.x, self.view.frame.Origin.y, self.view.frame.size.width, self.view.frame.height - keyboardSize.height)
    }
}

func keyboardWillHide(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
        self.collectionView.setTranslatesAutoresizingMaskIntoConstraints(false)
        self.view.frame = CGRectMake(self.view.frame.Origin.x, self.view.frame.Origin.y, self.view.frame.size.width, self.view.frame.height + keyboardSize.height)
    }
}
5
Grant Park

Подтвержденный ответ не учитывает учитывает позицию текстового поля и имеет некоторую ошибку (двойное смещение, никогда не возвращаться к основной позиции, смещение, даже если текстовое поле находится над видом ...)

Идея заключается в следующем: 

  • чтобы получить фокус TextField абсолютную позицию Y
  • получить высоту клавиатуры
  • чтобы получить высоту экрана
  • Затем вычислите расстояние между положением клавиатуры и текстовым полем (если <0 -> сдвинуть вид вверх)
  • использовать UIView.transform вместо UIView.frame.Origin.y - = .., потому что легче вернуться к исходной позиции с UIView.transform = .identity

тогда мы сможем перемещать вид только в случае необходимости и определенного смещения в oder, чтобы сфокусированное поле texField над клавиатурой

Вот код: 

Swift 4  

class ViewController: UIViewController, UITextFieldDelegate {

var textFieldRealYPosition: CGFloat = 0.0

override func viewDidLoad() {
    super.viewDidLoad()

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

  // Delegate all textfields

}


@objc func keyboardWillShow(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
        let distanceBetweenTextfielAndKeyboard = self.view.frame.height - textFieldRealYPosition - keyboardSize.height
        if distanceBetweenTextfielAndKeyboard < 0 {
            UIView.animate(withDuration: 0.4) {
                self.view.transform = CGAffineTransform(translationX: 0.0, y: distanceBetweenTextfielAndKeyboard)
            }
        }
    }
}


@objc func keyboardWillHide(notification: NSNotification) {
    UIView.animate(withDuration: 0.4) {
        self.view.transform = .identity
    }
}


func textFieldDidBeginEditing(_ textField: UITextField) {
  textFieldRealYPosition = textField.frame.Origin.y + textField.frame.height
  //take in account all superviews from textfield and potential contentOffset if you are using tableview to calculate the real position
}

}

3
Quentin N

Swift 4:

У меня возникла проблема с наиболее приемлемым ответом, из-за которой скрытие клавиатуры не возвращало представление полностью вниз страницы (только частично). Это сработало для меня (+ обновлено для Swift 4).

override func viewDidLoad() {
    super.viewDidLoad()
    self.hideKeyboardWhenTappedAround()
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}

@objc func keyboardWillShow(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
        if self.view.frame.Origin.y == 0{
            self.view.frame.Origin.y -= keyboardSize.height
        }
    }
}

@objc func keyboardWillHide(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
        if self.view.frame.Origin.y != 0{
            self.view.frame.Origin.y = 0
        }
    }
}
2
Rbar

Мои два цента для начинающих: В приведенных выше примерах кто-то меняет координаты, кто-то использует «маску авторазмера» и другие ограничения:

Как говорит Apple, не смешивайте эти 3 типа логики . Если у вас есть ограничения в раскадровке, не пытайтесь изменить х/у. Это определенно не работает.

2
ingconti

Для Swift 3

func textFieldDidBeginEditing(_ textField: UITextField) { // became first responder

    //move textfields up
    let myScreenRect: CGRect = UIScreen.main.bounds
    let keyboardHeight : CGFloat = 216

    UIView.beginAnimations( "animateView", context: nil)
    var movementDuration:TimeInterval = 0.35
    var needToMove: CGFloat = 0

    var frame : CGRect = self.view.frame
    if (textField.frame.Origin.y + textField.frame.size.height + UIApplication.shared.statusBarFrame.size.height > (myScreenRect.size.height - keyboardHeight - 30)) {
        needToMove = (textField.frame.Origin.y + textField.frame.size.height + UIApplication.shared.statusBarFrame.size.height) - (myScreenRect.size.height - keyboardHeight - 30);
    }

    frame.Origin.y = -needToMove
    self.view.frame = frame
    UIView.commitAnimations()
}

func textFieldDidEndEditing(_ textField: UITextField) {
    //move textfields back down
    UIView.beginAnimations( "animateView", context: nil)
    var movementDuration:TimeInterval = 0.35
    var frame : CGRect = self.view.frame
    frame.Origin.y = 0
    self.view.frame = frame
    UIView.commitAnimations()
}
2
Celil Bozkurt

Таким образом, ни один из других ответов, кажется, не понял это правильно.

Хорошая клавиатура для iOS должна:

  • Изменение размера автоматически при изменении размеров клавиатуры (ДА, ЭТО МОЖЕТ)
  • Анимировать на той же скорости, что и клавиатура
  • Анимировать, используя ту же кривую, что и клавиатура
  • Уважайте безопасные зоны, если это уместно.
  • Работает и на iPad/в режиме разблокировки

Мой код использует NSLayoutConstraint, объявленный как @IBOutlet

@IBOutlet private var bottomLayoutConstraint: NSLayoutConstraint!

Вы также можете использовать преобразования, просматривать смещения, .... Я думаю, что это проще с ограничением tho. Он работает, устанавливая ограничение снизу, вам может потребоваться изменить код, если ваша константа не равна 0/Не снизу.

Вот код:

// In ViewDidLoad
    NotificationCenter.default.addObserver(self, selector: #selector(?MyViewController.keyboardDidChange), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)


@objc func keyboardDidChange(notification: Notification) {
    let userInfo = notification.userInfo! as [AnyHashable: Any]
    let endFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
    let animationDuration = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as! NSNumber
    let animationCurve = userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as! NSNumber
    bottomLayoutConstraint.constant = view.frame.height - endFrame.Origin.y - view.safeAreaInsets.bottom // If your constraint is not defined as a safeArea constraint you might want to skip the last part.
    // Prevents iPad undocked keyboard.
    guard endFrame.height != 0, view.frame.height == endFrame.height + endFrame.Origin.y else {
        bottomLayoutConstraint.constant = 0
        return
    }
    UIView.setAnimationCurve(UIView.AnimationCurve(rawValue: animationCurve.intValue)!)
    UIView.animate(withDuration: animationDuration.doubleValue) {
        self.view.layoutIfNeeded()
        // Do additional tasks such as scrolling in a UICollectionView
    }
}
2
Antzi

его 100% идеальный ответ для всех парней обновления высоты стола при открытой клавиатуре 

    override func viewDidLoad() {
          super.viewDidLoad()

           NotificationCenter.default.addObserver(self, selector: #selector(RecipeVC.keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)

           NotificationCenter.default.addObserver(self, selector: #selector(RecipeVC.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
    }
    func keyboardWillShow(notification: NSNotification) {
         if ((notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue) != nil {
         //self.view.frame.Origin.y -= keyboardSize.height
         var userInfo = notification.userInfo!
         var keyboardFrame:CGRect = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
          keyboardFrame = self.view.convert(keyboardFrame, from: nil)

          var contentInset:UIEdgeInsets = self.tbl.contentInset
          contentInset.bottom = keyboardFrame.size.height
          self.tbl.contentInset = contentInset

       }
    }

    func keyboardWillHide(notification: NSNotification) {
         if ((notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue) != nil {
         let contentInset:UIEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
         self.tbl.contentInset = contentInset
         }
    }
1
Maulik Patel

Вот мое решение (на самом деле этот код предназначен для случая, когда у вас мало текстовых полей в вашем представлении, это работает и для случая, когда у вас есть одно текстовое поле)

class MyViewController: UIViewController, UITextFieldDelegate {

@IBOutlet weak var firstTextField: UITextField!
@IBOutlet weak var secondTextField: UITextField!

var activeTextField: UITextField!
var viewWasMoved: Bool = false


override func viewDidLoad() {
    super.viewDidLoad()
    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(PrintViewController.keyboardWillShow(_:)), name: UIKeyboardWillShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(PrintViewController.keyboardWillHide(_:)), name: UIKeyboardWillHideNotification, object: nil)
}

override func viewDidDisappear(animated: Bool) {
    super.viewWillDisappear(animated)
    NSNotificationCenter.defaultCenter().removeObserver(self)
}

func textFieldDidBeginEditing(textField: UITextField) {
    self.activeTextField = textField
}

func textFieldDidEndEditing(textField: UITextField) {
    self.activeTextField = nil
}

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


func keyboardWillShow(notification: NSNotification) {

    let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue()

    var aRect: CGRect = self.view.frame
    aRect.size.height -= keyboardSize!.height

    let activeTextFieldRect: CGRect? = activeTextField?.frame
    let activeTextFieldOrigin: CGPoint? = activeTextFieldRect?.Origin

    if (!CGRectContainsPoint(aRect, activeTextFieldOrigin!)) {
        self.viewWasMoved = true
        self.view.frame.Origin.y -= keyboardSize!.height
    } else {
        self.viewWasMoved = false
    }
}

func keyboardWillHide(notification: NSNotification) {
    if (self.viewWasMoved) {
        if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
            self.view.frame.Origin.y += keyboardSize.height
        }
    }
}
1
Vah.Sah

Обновлено для Swift 3 ...

Как уже говорили другие, вам нужно добавить наблюдателей уведомлений в методе viewDidLoad () вашего контроллера, вот так:

NotificationCenter.default.addObserver(forName: .UIKeyboardWillShow, object: nil, queue: nil)
    { notification in
    self.keyboardWillShow(notification)
    }

NotificationCenter.default.addObserver(forName: .UIKeyboardWillHide, object: nil, queue: nil)
    { notification in
    self.keyboardWillHide(notification)
    }

NotificationCenter.default.addObserver(forName: .UIKeyboardDidShow, object: nil, queue: nil)
    { _ in
    self.enableUserInteraction()
    }

NotificationCenter.default.addObserver(forName: .UIKeyboardDidHide, object: nil, queue: nil)
    { _ in
    self.enableUserInteraction()
    }

Не забудьте удалить ваших наблюдателей, где это необходимо (я делаю это в методе viewWillDisappear ())

NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillHide, object: nil)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardDidShow, object: nil)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardDidHide, object: nil)

Затем реализуйте свои методы show и hide - обратите внимание на строку, которая сообщает приложению игнорировать события взаимодействия (beginIgnoringInteractionEvents). Это важно, поскольку без него пользователь может нажать на поле или даже на скролл-просмотр и вызвать изменение во второй раз, что приведет к ужасному сбою пользовательского интерфейса. Игнорирование событий взаимодействия до отображения и скрытия клавиатуры предотвратит это:

func keyboardWillShow(notification: Notification)
    {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue
        {
        UIApplication.shared.beginIgnoringInteractionEvents()
        self.view.frame.Origin.y -= keyboardSize.height
        // add this line if you are shifting a scrollView, as in a chat application
        self.timelineCollectionView.contentInset.top += keyboardSize.height
        }
    }

func keyboardWillHide(notification: Notification)
    {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue
        {
        UIApplication.shared.beginIgnoringInteractionEvents()
        self.view.frame.Origin.y += keyboardSize.height
        // add this line if you are shifting a scrollView, as in a chat application
        self.timelineCollectionView.contentInset.top -= keyboardSize.height
        }
    }

Наконец, повторно включите взаимодействие с пользователем (помните, этот метод срабатывает после того, как клавиатура didShow или didHide):

func enableUserInteraction()
    {
    UIApplication.shared.endIgnoringInteractionEvents()
    }
1
Gene Loparco

Если у вас есть 2 или более текстовых поля в одном и том же VC, и пользователь нажимает на одно из них, а затем на другое, не вызывая функцию keyboardWillHide, представление снова идет вверх, что не является необходимым, поскольку у вас будет клавиатура, пустое пространство с высотой клавиатуры и вид, используя код в ответе, который я отредактировал:

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(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
        self.view.frame.Origin.y -= keyboardSize.height
    }
}

func keyboardWillHide(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
        self.view.frame.Origin.y += keyboardSize.height
    }
}

Чтобы решить эту проблему, замените две функции «KeyboardWillShow/Hide» на эти:

func keyboardWillShow(notification: NSNotification) {
 if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
    if view.frame.Origin.y == 0{
        self.view.frame.Origin.y -= keyboardSize.height
        }
    }
}

func keyboardWillHide(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
        if view.frame.Origin.y != 0 {
            self.view.frame.Origin.y += keyboardSize.height
        }
    }
}
1
Don't be a x-triple dot

Решение Бориса ОЧЕНЬ хорошее, но иногда вид может быть искажен.

Для идеального выравнивания используйте код ниже

override func viewDidLoad() {
super.viewDidLoad()            
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)}

Функции:

@objc func keyboardWillShow(notification: NSNotification) {        
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
    if self.view.frame.Origin.y == 0{
        self.view.frame.Origin.y -= keyboardSize.height
    }
}}    

А также,

@objc func keyboardWillHide(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
    if self.view.frame.Origin.y != 0{
        self.view.frame.Origin.y = 0 
    }
} }
1
Eray Alparslan

Я знаю, что на этот вопрос есть почти 30 ответов, и я настолько потрясен, что никто даже не упомянул однажды о этом прекрасном проекте GitHub , который делает все это для вас и даже лучше. Все ответы просто перемещают представление вверх, но что, если высота клавиатуры не закрывает UITextField? Я только что решил все свои проблемы с этим IQKeyboardManager. У него 13000+ звезд.
Просто добавьте это в свой подфайл, если вы используете Swift

pod 'IQKeyboardManagerSwift'

а затем внутри вашего AppDelegate.Swift импортируйте IQKeyboardManagerSwift и

import IQKeyboardManagerSwift

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

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

      IQKeyboardManager.shared.enable = true // just add this line

      return true
    }
}

Добавьте строку IQKeyboardManager.shared.enable = true, чтобы включить ее
Это решение обязательно, если вы собираетесь на производство. Это решает каждую проблему и является обязательным для каждого приложения, которое имеет некоторый вклад.

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

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

 }

 // MARK: - keyboard
 func keyboardWillShow(notification: NSNotification) 
{

if let userInfo = notification.userInfo {
if let keyboardSize = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
let contentInsets = self.tblView.contentInset as UIEdgeInsets
self.tblView.contentInset = UIEdgeInsets(top: contentInsets.top, left: contentInsets.left, bottom: keyboardSize.height, right:contentInsets.right)
                    // ...
                } else {
                    // no UIKeyboardFrameBeginUserInfoKey entry in userInfo
                }
            } else {
                // no userInfo dictionary in notification
            }
        }

func keyboardWillHide(notification: NSNotification) 
{
let contentInsets = self.tblView.contentInset as UIEdgeInsets
self.tblView.contentInset = UIEdgeInsets(top: contentInsets.top, left: contentInsets.left, bottom: 0, right:contentInsets.right)
 }
0
Himali Shah
func keyboardWillHide(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
        if self.view.frame.Origin.y != 0{
           // self.view.frame.Origin.y += keyboardSize.height
            self.view.frame.Origin.y = 0
        }
    }
}
0
Puji Wahono

Мне нужно переместить UIView в Swift 4 , когда клавиатура открывается и закрывается. и все ответы не могли мне помочь. потому что высота клавиатуры меняется, когда emojis открыт. так что мой код:

@objc func keyboardWillShow(sender: NSNotification) {

    if let keyboardFrame: NSValue = sender.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue {

        let keyboardRectangle = keyboardFrame.cgRectValue
        let keyboardHeight = keyboardRectangle.height

        if(self.oldHeight == keyboardHeight){
            self.sendingView.frame.Origin.y -= keyboardHeight
            self.oldHeight = keyboardHeight
        }
        else{
            self.sendingView.frame.Origin.y += self.oldHeight
            self.sendingView.frame.Origin.y -= keyboardHeight
            self.oldHeight = keyboardHeight
        }
    }
}

@objc func keyboardWillHide(sender: NSNotification) {

    if let keyboardFrame: NSValue = sender.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue {

        let keyboardRectangle = keyboardFrame.cgRectValue
        let keyboardHeight = keyboardRectangle.height

        self.sendingView.frame.Origin.y += keyboardHeight

    }
}

и вviewDidLoad():

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

self.oldHeight = CGFloat() и определяет как поле вверху класса.

0
MHSFisher
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

    }
0
Kamalkumar.E

Swift 4.1  

 override func viewDidLoad() {
    super.viewDidLoad()            
    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)    
}

@objc func keyboardWillShow(notification: NSNotification) {        
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
        if self.view.frame.Origin.y == 0 {
            self.view.frame.Origin.y -= keyboardSize.height   //can adjust as keyboardSize.height-(any number 30 or 40)
        }
    }        
}

@objc func keyboardWillHide(notification: NSNotification) {
    if self.view.frame.Origin.y != 0 {
        self.view.frame.Origin.y = 0
    }
}
0
Tlzdeveloper786

Код Swift 3

var activeField: UITextField?

override func viewDidLoad() {
    super.viewDidLoad()

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

func textFieldDidBeginEditing(_ textField: UITextField){
    activeField = textField
}

func textFieldDidEndEditing(_ textField: UITextField){
    activeField = nil
}

func keyboardWillShow(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
        if (self.activeField?.frame.Origin.y)! >= keyboardSize.height {
            self.view.frame.Origin.y = keyboardSize.height - (self.activeField?.frame.Origin.y)!
        } else {
            self.view.frame.Origin.y = 0
        }
    }
}

func keyboardWillHide(notification: NSNotification) {
    self.view.frame.Origin.y = 0
}
0
Rohit Sharma

этот видеоурок лучший. 7 минут, и это будет иметь смысл. Такое простое решение для случаев, когда у вас есть несколько текстовых полей и вы хотите, чтобы представление прокрутки перемещало количество пикселей на «x» при касании этого конкретного текстового поля.

https://youtu.be/VuiPGJOEBH4

Просто эти шаги:

Поместите все ваши текстовые поля в скроллвью, который ограничен краями вида. 

-Соедините все текстовые поля и прокрутите представление как делегаты к контроллеру представления.

-Соедините все текстовые поля и прокрутите представление с помощью IBOutlet.

class ViewController: UIViewController, UITextFieldDelegate {

-Добавить протокол UITextFieldDelegate в ваш класс

@IBOutlet var stateAddress: UITextField!
@IBOutlet var zipAddress: UITextField!
@IBOutlet var phoneNumber: UITextField!
@IBOutlet var vetEmailAddress: UITextField!    
@IBOutlet weak var scrollView: UIScrollView!

-Добавьте методы UITextFieldDelegate в ваш файл Swift:

func textFieldShouldReturn(textField: UITextField) -> Bool {

    textField.resignFirstResponder()
    return true
}


func textFieldDidBeginEditing(textField: UITextField) {

    if (textField == self.stateAddress) {
        scrollView.setContentOffset(CGPointMake(0, 25), animated: true)
    }
    else if (textField == self.zipAddress) {
        scrollView.setContentOffset(CGPointMake(0, 57), animated: true)
    }
    else if (textField == self.phoneNumber) {
        scrollView.setContentOffset(CGPointMake(0, 112), animated: true)
    }
    else if (textField == self.vetEmailAddress) {
        scrollView.setContentOffset(CGPointMake(0, 142), animated: true)
    }
}

func textFieldDidEndEditing(textField: UITextField) {

    scrollView.setContentOffset(CGPointMake(0, 0), animated: true)
}

Первый метод просто активирует кнопку возврата на клавиатуре, чтобы убрать клавиатуру. Во-вторых, когда вы нажимаете на любое конкретное текстовое поле, а затем устанавливаете смещение y того, как далеко прокручивается ваше представление прокрутки (мое основано на местоположении y на моих контроллерах 25, 57, 112, 142). Последний говорит, что когда вы нажимаете в сторону от клавиатуры, просмотр прокрутки возвращается в исходное положение.

Таким образом я сделал свой пиксель зрения идеальным!

0
bme003

Эта реализация (Swift 4) даст вам поведение, наиболее близкое к поведению Android по умолчанию. То есть: перемещает вид вверх, когда активное текстовое поле находится под клавиатурой, и соответственно перемещается, когда пользователь переключается на другой вид без закрытия клавиатуры. Не забудьте вызвать setTextFieldDelegates ().

public class DelegateProxy: NSObject, UITextFieldDelegate {

  private static let instance = DelegateProxies()

  weak var activeTextField: UITextField?
  var offset: CGFloat = 0
  weak var vc: UIViewController?
  var keyboardHeight: CGFloat = 0

  public static func getDelegate(root: UIViewController) -> DelegateProxies {
    instance.vc = root
    return instance
  }

  public static func getDelegate() -> DelegateProxies {
    return instance
  }

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


  public func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {

    self.activeTextField = textField

    let globalPointY: CGFloat = (textField.superview?.convert(textField.frame.Origin, to: nil).y ?? CGFloat(0)) + textField.frame.height


    offset = UIScreen.main.bounds.height - globalPointY

    if keyboardHeight > 0 {
        vc?.moveViewUp(offsetFromKeyboard: keyboardHeight - offset)
    }

    return true
  }
}


extension UIViewController {

  private func setTextFieldDelegates(parentView: UIView) {
    for child in parentView.subviews {
        setTextFieldDelegates(parentView: child)
        (child as? UITextField)?.delegate = DelegateProxies.getDelegate(root: self)
    }
  }

  func registerAutoResizeOnKeyboardAppear(){
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
  }

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

  @objc func keyboardWillShow(notification: NSNotification) {

    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
        let offsetFromKeyboard = keyboardSize.height - DelegateProxies.getDelegate().offset
        DelegateProxies.getDelegate().keyboardHeight = keyboardSize.height

        moveViewUp(offsetFromKeyboard: offsetFromKeyboard)
    }
  }

  func moveViewUp(offsetFromKeyboard: CGFloat){
    print("offset from keyboard: \(offsetFromKeyboard)")

    let moveOffset = offsetFromKeyboard + 8

    if offsetFromKeyboard > 0 {
        self.view.frame.Origin.y = -moveOffset
    }

    if offsetFromKeyboard < 0 && view.frame.Origin.y < 0 {
        self.view.frame.Origin.y += -moveOffset
        if self.view.frame.Origin.y > 0{
            self.view.frame.Origin.y = 0
        }
    }
  }

  @objc func keyboardWillHide(notification: NSNotification) {
    self.view.frame.Origin.y = 0
  }
}
0
ravindu1024

если вы похожи на меня, который перепробовал все вышеперечисленные решения, и все же ваша проблема не решена, у меня есть отличное решение для вас, которое работает как шарм. Сначала я хочу уточнить кое-что о некоторых решениях, упомянутых выше.

  1. В моем случае IQkeyboardmanager работал только тогда, когда к элементам не применен автоматический макет, если он применяется, то менеджер IQkeyboard не будет работать так, как мы думаем.
  2. То же самое с движением вверх self.view.
  3. я написал заголовок Objective C с поддержкой Swift для перемещения UITexfield вверх, когда пользователь нажимает на него, решая проблему клавиатуры, закрывающей поле UIText: https://github.com/coolvasanth/smart_keyboard
  4. Тот, кто имеет средний или более высокий уровень в разработке приложений для iOS, может легко понять хранилище и реализовать его. Всего наилучшего
0
Vasanth

Метод Симпельста в Swift 4 enter image description here

import UIKit

class ViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet var myTextField: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: .UIKeyboardWillShow, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        myTextField.resignFirstResponder()
    }

    func keyboardWillShow(notification: NSNotification) {
        // let duration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey]
        // print("duration",duration)
        if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
            let keyboardHeight : Int = Int(keyboardSize.height)
            print("keyboardWillShow",keyboardHeight)
            if let height = UserDefaults.standard.value(forKey: "keyboardHeight") as? (Int) {
                moveTextField(myTextField, moveDistance: -height as Int, moveDuration: 0.43, up: true)
            }else{
                UserDefaults.standard.set(keyboardHeight, forKey: "keyboardHeight")
                moveTextField(myTextField, moveDistance: -keyboardHeight, moveDuration: 0.43, up: true)
            }
        }
    }

    func keyboardWillHide(notification: NSNotification){
        if let height = UserDefaults.standard.value(forKey: "keyboardHeight") as? (Int) {
            moveTextField(myTextField, moveDistance: -height as Int, moveDuration: 0.25, up: false)
        }
    }

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

    func moveTextField(_ textField: UITextField, moveDistance: Int, moveDuration: Double, up: Bool) {
        let movement: CGFloat = CGFloat(up ? moveDistance : -moveDistance)
        UIView.beginAnimations("animateTextField", context: nil)
        UIView.setAnimationBeginsFromCurrentState(true)
        UIView.setAnimationDuration(moveDuration)
        self.view.frame = self.view.frame.offsetBy(dx: 0, dy: movement)
        UIView.commitAnimations()
    }

}

Вы также можете перемещаться только вверх и вниз UITextFiled Не весь экран (UIView).
С использованием этого метода.

NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChange), name: .UIKeyboardWillChangeFrame, object: nil)

А также 

   @objc func keyboardWillChange(notification: NSNotification) {

        let duration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double
        let curve = notification.userInfo![UIKeyboardAnimationCurveUserInfoKey] as! UInt
        let curFrame = (notification.userInfo![UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
        let targetFrame = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
        let deltaY = targetFrame.Origin.y - curFrame.Origin.y

        UIView.animateKeyframes(withDuration: duration, delay: 0.0, options: UIViewKeyframeAnimationOptions(rawValue: curve), animations: {
            self.textField.frame.Origin.y+=deltaY

        },completion: nil)
    }
0
ZAFAR007

я прочитал ответы и решил мою проблему с помощью следующих строк кода:

class ViewController: UIViewController, UITextFieldDelegate {

  @IBOutlet weak var titleField: UITextField!
  @IBOutlet weak var priceField: UITextField!
  @IBOutlet weak var detailsField: UTtextField!

  override func viewDidLoad() {
   super.viewDidLoad()
// Do not to forget to set the delegate otherwise the textFieldShouldReturn(_:)
// won't work and the keyboard will never be hidden.
   priceField.delegate = self
   titleField.delegate = self
   detailsField.delegate = self

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

   NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide),
 name: NSNotification.Name.UIKeyboardWillHide, object: nil)
  }

   func textFieldShouldReturn(_ textField: UITextField) -> Bool {
      self.view.endEditing(true)
      return false
   }

 func keyboardWillShow(notification: NSNotification) {
   var translation:CGFloat = 0
   if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
     if detailsField.isEditing{
       translation = CGFloat(-keyboardSize.height)
     }else if priceField.isEditing{
       translation = CGFloat(-keyboardSize.height / 3.8)
     }
   }
    UIView.animate(withDuration: 0.2) {
   self.view.transform = CGAffineTransform(translationX: 0, y: translation)
    }
  }


 func keyboardWillHide(notification: NSNotification) {
    UIView.animate(withDuration: 0.2) {
     self.view.transform = CGAffineTransform(translationX: 0, y: 0)
    } 
  }
}

У меня есть несколько UITextFields, и я хочу, чтобы представление перемещалось вверх по-разному в зависимости от того, какой текстовый элемент используется.

0
Fedya Grab

Эта функция должна быть встроена в Ios, однако мы должны сделать это извне.
Вставьте следующий код 
* Чтобы переместить вид, когда textField находится под клавиатурой,
* Не перемещать вид, когда textField находится над клавиатурой
* Для перемещения просмотра на основе высоты клавиатуры при необходимости.
Это работает и проверено во всех случаях.

import UIKit

class NamVcc: UIViewController, UITextFieldDelegate
{
    @IBOutlet weak var NamTxtBoxVid: UITextField!

    var VydTxtBoxVar: UITextField!
    var ChkKeyPadDspVar: Bool = false
    var KeyPadHytVal: CGFloat!

    override func viewDidLoad()
    {
        super.viewDidLoad()

        NamTxtBoxVid.delegate = self
    }

    override func viewWillAppear(animated: Bool)
    {
        NSNotificationCenter.defaultCenter().addObserver(self,
            selector: #selector(TdoWenKeyPadVyd(_:)),
            name:UIKeyboardWillShowNotification,
            object: nil);
        NSNotificationCenter.defaultCenter().addObserver(self,
            selector: #selector(TdoWenKeyPadHyd(_:)),
            name:UIKeyboardWillHideNotification,
            object: nil);
    }

    func textFieldDidBeginEditing(TxtBoxPsgVar: UITextField)
    {
        self.VydTxtBoxVar = TxtBoxPsgVar
    }

    func textFieldDidEndEditing(TxtBoxPsgVar: UITextField)
    {
        self.VydTxtBoxVar = nil
    }

    func textFieldShouldReturn(TxtBoxPsgVar: UITextField) -> Bool
    {
        self.VydTxtBoxVar.resignFirstResponder()
        return true
    }

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

    func TdoWenKeyPadVyd(NfnPsgVar: NSNotification)
    {
        if(!self.ChkKeyPadDspVar)
        {
            self.KeyPadHytVal = (NfnPsgVar.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue().height

            var NonKeyPadAraVar: CGRect = self.view.frame
            NonKeyPadAraVar.size.height -= self.KeyPadHytVal

            let VydTxtBoxCenVal: CGPoint? = VydTxtBoxVar?.frame.Origin

            if (!CGRectContainsPoint(NonKeyPadAraVar, VydTxtBoxCenVal!))
            {
                self.ChkKeyPadDspVar = true
                UIView.animateWithDuration(1.0,
                    animations:
                    { self.view.frame.Origin.y -= (self.KeyPadHytVal)},
                    completion: nil)
            }
            else
            {
                self.ChkKeyPadDspVar = false
            }
        }

    }

    func TdoWenKeyPadHyd(NfnPsgVar: NSNotification)
    {
        if (self.ChkKeyPadDspVar)
        {
            self.ChkKeyPadDspVar = false
            UIView.animateWithDuration(1.0,
                animations:
                { self.view.frame.Origin.y += (self.KeyPadHytVal)},
                completion: nil)
        }
    }

    override func viewDidDisappear(animated: Bool)
    {
        super.viewWillDisappear(animated)
        NSNotificationCenter.defaultCenter().removeObserver(self)
        view.endEditing(true)
        ChkKeyPadDspVar = false
    }
}

| :: | Иногда View будет внизу, в этом случае используйте высоту +/- 150:

    NonKeyPadAraVar.size.height -= self.KeyPadHytVal + 150

    { self.view.frame.Origin.y -= self.KeyPadHytVal  - 150},
                    completion: nil)

    { self.view.frame.Origin.y += self.KeyPadHytVal  - 150},
                completion: nil)
0
Sujay U N

Swift 3.0 вставить в viewDidLoad (), это->

{

view.addSubview (Your_messageInputConteinerView)

    view.addConstraintWithFormat(format: "H:|[v0]|", views:Your_messageInputConteinerView)

    view.addConstraintWithFormat(format: "V:[v0(48)]", views:Your_messageInputConteinerView)

NotificationCenter.default.addObserver (self, селектор: #selector (handleKeyboardNotification (messages :)), имя: NSNotification.Name.UIKeyboardWillShow, объект: ноль)

NotificationCenter.default.addObserver (self, селектор: #selector (handleKeyboardNotification (tification :)), имя: .UIKeyboardWillHide, объект: ноль)

bottomConstraint = NSLayoutConstraint(item: Your_messageInputConteinerView, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1, constant: 0)

view.addConstraint(bottomConstraint!)

}

func handleKeyboardNotification (уведомление: Уведомление) {

if let userInfo = notification.userInfo {

    if let keyBoardFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue{

        print(keyBoardFrame)

        if bottomConstraint?.constant != CGFloat(0) {
                bottomConstraint?.constant = 0
                return
            }
     bottomConstraint?.constant = -keyBoardFrame.height
                           or
        self.view.frame.Origin.y = -keyBoardFrame.height
    }
}

}

0
Anton Russia
func keyboardWillShow(notification: NSNotification) {

    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {
        self.view.frame.Origin.y = self.view.frame.height - (self.view.frame.height + keyboardSize.height)
    }

}

func keyboardWillHide(notification: NSNotification) {
        self.view.frame.Origin.y = 0
}

оно должно быть более стабильным

0
Hadevs Play

Используйте следующий код для просмотра вверх на UITextField нажал 

func textFieldDidBeginEditing(textField: UITextField) {
    ViewUpanimateMoving(true, upValue: 100)
}
func textFieldDidEndEditing(textField: UITextField) {
    ViewUpanimateMoving(false, upValue: 100)
}
func ViewUpanimateMoving (up:Bool, upValue :CGFloat){
    var durationMovement:NSTimeInterval = 0.3
    var movement:CGFloat = ( up ? -upValue : upValue)
    UIView.beginAnimations( "animateView", context: nil)
    UIView.setAnimationBeginsFromCurrentState(true)
    UIView.setAnimationDuration(durationMovement)
    self.view.frame = CGRectOffset(self.view.frame, 0,  movement)
    UIView.commitAnimations()
}
0
Jugal K Balara

Я сделал Cocoapod, чтобы упростить вопрос:

https://github.com/xtrinch/KeyboardLayoutHelper

Как это использовать: 

Создайте нижнее ограничение автоматической разметки, присвойте ему класс KeyboardLayoutConstraint в модуле KeyboardLayoutHelper, и модуль выполнит всю работу, необходимую для его увеличения, чтобы он соответствовал появляющейся и исчезающей клавиатуре. Смотрите пример проекта на примерах, как его использовать (я сделал два: textFields внутри scrollView и вертикально центрированные textFields с двумя основными представлениями - login & register).

Ограничением нижнего макета может быть представление контейнера, само текстовое поле, что угодно, как вы его называете.

0
xtrinch