J'ai une application qui a un champ de texte dans la moitié inférieure de la vue . Cela signifie que lorsque je vais taper dans le champ de texte, le clavier couvre le champ de texte.
Comment puis-je déplacer la vue vers le haut pendant la frappe pour pouvoir voir ce que je tape et la redescendre ensuite à son emplacement d'origine lorsque le clavier disparaît?
J'ai regardé partout mais toutes les solutions semblent être en Obj-C, que je ne parviens pas à convertir pour le moment.
Toute aide serait grandement appréciée.
Voici une solution, sans gérer le passage d'un textField à un autre:
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
}
Pour résoudre ce problème, remplacez les deux fonctions keyboardWillShow/Hide
par celles-ci:
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
}
}
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
}
}
EDIT FOR 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
}
}
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
}
}
Une des réponses populaires sur ce fil utilise le code suivant:
func keyboardWillShow(sender: NSNotification) {
self.view.frame.Origin.y -= 150
}
func keyboardWillHide(sender: NSNotification) {
self.view.frame.Origin.y += 150
}
Il y a un problème évident à compenser votre vue d'un montant statique. Cela ira bien sur un appareil, mais pas sur toute autre configuration. Vous devrez obtenir la hauteur du clavier et l'utiliser comme valeur de décalage.
Voici une solution qui fonctionne sur tous les périphériques et gère le cas Edge où l'utilisateur masque le champ de texte prédictif lors de la frappe.
Il est important de noter ci-dessous, nous passons self.view.window comme paramètre d'objet. Cela nous fournira des données de notre clavier, telles que sa hauteur!
@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
}
Nous allons le rendre agréable sur tous les appareils et gérer le cas où l'utilisateur ajoute ou supprime le champ de texte prédictif.
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
})
}
}
N'oubliez pas de supprimer vos observateurs avant de quitter la vue pour empêcher la transmission de messages inutiles.
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)
}
Mise à jour basée sur la question des commentaires:
Si vous avez plusieurs champs de texte, vous pouvez vérifier si votre view.frame.Origin.y est à zéro.
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)
}
Le moyen le plus simple qui ne nécessite même pas de code:
L'objet se déplace automatiquement vers le haut avec le clavier, de manière synchronisée.
Ajoutez ceci à votre contrôleur de vue. Fonctionne comme un charme. Il suffit d’ajuster les valeurs.
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
}
J'ai un peu amélioré l'une des réponses pour le faire fonctionner avec différents claviers et différents textviews/champs sur une seule page:
Ajouter des observateurs:
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
}
}
}
Supprimer les observateurs:
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)
}
Pour les erreurs d’écran noir (Swift 4 & 4.2) .
J'ai résolu le problème d'écran noir. Dans la solution vérifiée La hauteur du clavier change après la frappe, ce qui provoque un écran noir.
Doivent utiliser UIKeyboardFrameEndUserInfoKey au lieu de 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
}
}
Je vois toutes les réponses déplacent la vue elle-même par la valeur de la hauteur du clavier. J'ai une réponse élaborée, qui pourrait être utile si vous utilisez des contraintes telles que autolayout
, qui déplace une vue en modifiant sa valeur de contrainte (contraintes du haut ou du bas, par exemple) d'une valeur prédéfinie ou vous pouvez utiliser la valeur de la taille du clavier.
Dans cet exemple, j'utilise la contrainte du bas du champ de texte vers le mode Vue du bas avec la valeur initiale de 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()
}
}
Il y a eu quelques changements dans la façon dont nous définissons la notification KeyboardWillHideNotification.
Cette solution fonctionne avec 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
}
}
Pour Swift 3, j'ai créé une sous-classe UIViewController car j'avais besoin d'un comportement constant dans tous les contrôleurs de vue.
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)
}
}
J'ai remarqué que les autres réponses impliquaient de couper une partie du haut de la vue. Si vous voulez simplement redimensionner la vue sans couper de contenu, essayez cette méthode :)
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)
}
}
La réponse validée n'a pas prend en compte la position du champ de texte et présente un bogue (double déplacement, ne jamais revenir à la position principale, déplacement même si le texfield est au-dessus de la vue ...)
L'idée est:
alors nous ne pourrons déplacer la vue que si nécessaire et du déplacement spécifique afin que le texField concentré soit juste au-dessus du clavier
Voici le code:
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
}
}
Swift 4:
J'avais un problème avec la réponse la plus acceptée, dans laquelle cacher le clavier ne retournait pas la vue jusqu'au bas de la page (seulement partiellement). Cela a fonctionné pour moi (+ mis à jour pour 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
}
}
}
Mes deux cents pour les débutants:
Comme Apple le dit, ne mélangez pas ces 3 types de logique ... Si vous avez des contraintes dans Storyboard, n'essayez pas de changer x/y. Cela ne fonctionne définitivement pas.
Pour 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()
}
Donc, aucune des autres réponses ne semble avoir raison.
Le clavier ayant un bon comportement sur iOS devrait:
Mon code utilise une NSLayoutConstraint
déclarée en tant que @IBOutlet
@IBOutlet private var bottomLayoutConstraint: NSLayoutConstraint!
Vous pouvez également utiliser des transformations, des décalages de vue, ... Je pense que c'est plus facile avec la contrainte tho. Cela fonctionne en fixant une contrainte en bas, vous devrez peut-être modifier le code si votre constante n'est pas 0/pas en bas.
Voici le code:
// 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
}
}
sa réponse parfaite à 100% Pour tous les types de Guy Mise à jour Tableview Hauteur à l'ouverture du clavier
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
}
}
Voici ma solution (en fait, ce code est destiné au cas où vous avez peu de champs de texte dans votre vue, cela fonctionne aussi pour le cas où vous avez un champ de texte)
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
}
}
}
Mis à jour pour Swift 3 ...
Comme d'autres l'ont déjà dit, vous devez ajouter des observateurs de notification dans la méthode viewDidLoad () de votre contrôleur, comme suit:
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()
}
N'oubliez pas de supprimer vos observateurs le cas échéant (je le fais dans la méthode 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)
Ensuite, implémentez vos méthodes show et hide - remarquez la ligne qui indique à l'application d'ignorer les événements d'interaction (beginIgnoringInteractionEvents). Ceci est important car sans cela, l'utilisateur pourrait taper sur un champ ou même une vue à défilement et provoquer le décalage une seconde fois, ce qui entraînerait un terrible problème d'interface utilisateur. Ignorer les événements d'interaction avant l'affichage et le masquage du clavier empêchera ceci:
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
}
}
Enfin, réactivez les interactions utilisateur (rappelez-vous, cette méthode se déclenche après le clavier didShow ou didHide):
func enableUserInteraction()
{
UIApplication.shared.endIgnoringInteractionEvents()
}
Si vous avez 2 ou plusieurs champs de texte sur le même VC, et que l'utilisateur tape sur l'un d'eux, puis sur l'autre, sans appeler la fonction keyboardWillHide, la vue revient une fois de plus, ce qui n'est pas nécessaire, vous aurez le clavier, un espace vide qui a la hauteur du clavier, puis la vue, en utilisant le code de la réponse que j'ai modifiée:
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
}
}
Pour résoudre ce problème, remplacez les deux fonctions "KeyboardWillShow/Hide" par:
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
}
}
}
@ La solution de Boris est TRES bonne mais la vue peut parfois être corrompue.
Pour un alignement parfait, utilisez le code ci-dessous
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)}
Les fonctions:
@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
}
}}
Et,
@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
}
} }
Je sais que cette question a près de 30 réponses et que je suis tellement choquée que personne n'a même mentionné une fois à propos de ce beau projet GitHub qui fait tout pour vous et même mieux. Toutes les réponses déplacent simplement la vue vers le haut, mais que se passe-t-il si la hauteur du clavier ne recouvre pas UITextField? Je viens de résoudre tous mes problèmes avec cet IQKeyboardManager. Il a plus de 13000 étoiles.
Ajoutez simplement ceci dans votre podfile si vous utilisez Swift
pod 'IQKeyboardManagerSwift'
puis dans votre import AppDelegate.Swift IQKeyboardManagerSwift et
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
}
}
Ajoutez la ligne IQKeyboardManager.shared.enable = true
pour l'activer
Cette solution est indispensable si vous souhaitez passer à la production. Il résout tous les problèmes et est indispensable pour toutes les applications qui ont une contribution.
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)
}
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
}
}
}
J'ai besoin de déplacer UIView
dans Swift 4 lorsque le clavier s'ouvre et se ferme. et toutes les réponses ne pouvaient pas m'aider. parce que la hauteur du clavier change lorsque emojis open. donc mon code est:
@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
}
}
et dansviewDidLoad()
:
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()
et définit comme champ en haut de la classe.
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
}
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
}
}
Swift 5.0:
Après 4-5 heures de combat, je suis arrivé avec une simple extension de UIViewController avec un code simple qui fonctionne comme un charme
* La vue ne doit pas bouger lorsque TextField est au-dessus du clavier
* Pas besoin de définir une valeur constante sur NSLayoutConstraint
* Aucune bibliothèque tierce requise
* Aucun code d'animation requis
* Fonctionne aussi sur tableview
* Cela fonctionne sur la mise en page automatique/redimensionnement automatique
extension UIViewController {
func addKeyboardObserver() {
NotificationCenter.default.addObserver(self,
selector: #selector(self.keyboardNotifications(notification:)),
name: UIResponder.keyboardWillChangeFrameNotification,
object: nil)
}
func removeKeyboardObserver(){
NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
}
// This method will notify when keyboard appears/ dissapears
@objc func keyboardNotifications(notification: NSNotification) {
var accurateY = 0.0 //Using this we will calculate the selected textFields Y Position
if let activeTextField = UIResponder.currentFirst() as? UITextField {
// Here we will get accurate frame of which textField is selected if there are multiple textfields
let frame = self.view.convert(activeTextField.frame, from:activeTextField.superview)
accurateY = Double(frame.Origin.y) + Double(frame.size.height)
}
if let userInfo = notification.userInfo {
// here we will get frame of keyBoard (i.e. x, y, width, height)
let keyBoardFrame = (userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue
let keyBoardFrameY = keyBoardFrame!.Origin.y
var newHeight: CGFloat = 0.0
//Check keyboards Y position and according to that move view up and down
if keyBoardFrameY >= UIScreen.main.bounds.size.height {
newHeight = 0.0
} else {
if accurateY >= Double(keyBoardFrameY) { // if textfields y is greater than keyboards y then only move View to up
if #available(iOS 11.0, *) {
newHeight = -CGFloat(accurateY - Double(keyBoardFrameY)) - self.view.safeAreaInsets.bottom
} else {
newHeight = -CGFloat(accurateY - Double(keyBoardFrameY)) - 5
}
}
}
//set the Y position of view
self.view.frame.Origin.y = newHeight
}
}
}
Ajoutez cette extension de UIResponder pour obtenir le champ TextField sélectionné
public extension UIResponder {
private struct Static {
static weak var responder: UIResponder?
}
static func currentFirst() -> UIResponder? {
Static.responder = nil
UIApplication.shared.sendAction(#selector(UIResponder._trap), to: nil, from: nil, for: nil)
return Static.responder
}
@objc private func _trap() {
Static.responder = self
}
}
Ensuite, utilisez ceci dans n'importe quel ViewController
override func viewWillAppear(_ animated: Bool) {
self.addKeyboardObserver()
}
override func viewWillDisappear(_ animated: Bool) {
self.removeKeyboardObserver()
}
Enregistrez cette notification dans func viewWillAppear(_ animated: Bool)
Annuler l'enregistrement de cette notification dans func viewWillDisappear(_ animated:Bool)
Swift 3 code
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
}
ce tutoriel vidéo est le meilleur. 7 minutes de long et ça va avoir tellement de sens. Une solution aussi simple lorsque vous avez plusieurs champs de texte et que vous souhaitez que la vue de défilement déplace "x" le nombre de pixels lorsque ce champ de texte spécifique est exploité.
Juste ces étapes:
-Placez tous vos champs de texte dans une vue de défilement contrainte aux bords de la vue.
-Connectez tous les champs de texte et faites défiler la vue en tant que délégués au contrôleur de vue.
-Connectez tous les champs de texte et faites défiler la vue avec un IBOutlet.
class ViewController: UIViewController, UITextFieldDelegate {
-Ajouter le protocole UITextFieldDelegate à votre classe
@IBOutlet var stateAddress: UITextField!
@IBOutlet var zipAddress: UITextField!
@IBOutlet var phoneNumber: UITextField!
@IBOutlet var vetEmailAddress: UITextField!
@IBOutlet weak var scrollView: UIScrollView!
-Ajouter des méthodes UITextFieldDelegate à votre fichier 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)
}
La première méthode consiste simplement à activer le bouton de retour du clavier pour fermer le clavier. La seconde est lorsque vous appuyez sur un champ de texte spécifique, puis définissez le décalage y de la distance de défilement de votre défilement (le mien est basé sur l'emplacement y de mes contrôleurs de vue 25, 57, 112, 142). Le dernier indique que lorsque vous appuyez loin du clavier, la vue défilement revient à son emplacement d'origine.
J'ai rendu ma vue pixel parfaite de cette façon!
Cette implémentation (Swift 4) vous donnera le comportement qui se rapproche le plus du comportement par défaut d’Android. Par exemple, déplace la vue vers le haut lorsque le champ de texte actif est sous le clavier et se déplace en conséquence lorsque l'utilisateur bascule vers une autre vue sans fermer le clavier. N'oubliez pas d'appeler 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
}
}
si vous êtes comme moi qui a essayé toutes les solutions ci-dessus et que votre problème n’est toujours pas résolu, j’ai une excellente solution pour vous qui fonctionne à merveille. Premièrement, je veux clarifier quelques points concernant certaines des solutions mentionnées ci-dessus.
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()
}
}
Vous pouvez également uniquement monter et descendre UITextFiled
Pas tout à l'écran (UIView).
Avec l’utilisation de cette méthode.
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChange), name: .UIKeyboardWillChangeFrame, object: nil)
Et
@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)
}
j'ai lu les réponses et résolu mon problème par ces lignes de code:
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)
}
}
}
J'ai quelques UITextFields et je souhaite que la vue se déplace différemment selon le textField sélectionné.
Cette fonctionnalité devrait être construite dans Ios, mais nous devons le faire en externe.
Insérer le code ci-dessous
* Pour déplacer la vue lorsque textField est sous le clavier,
* Ne pas déplacer la vue lorsque textField est au-dessus du clavier
* Pour déplacer la vue en fonction de la hauteur du clavier, le cas échéant.
Cela fonctionne et testé dans tous les cas.
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
}
}
| :: | Quelquefois la vue sera en panne, dans ce cas, utilisez la hauteur +/- 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)
Swift 3.0 inséré dans viewDidLoad (), this->
{
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, sélecteur: #selector (handleKeyboardNotification (notification :)), nom: NSNotification.Name.UIKeyboardWillShow, objet: nil)
NotificationCenter.default.addObserver (self, sélecteur: #selector (handleKeyboardNotification (notification :)), nom: .UIKeyboardWillHide, objet: nil)
bottomConstraint = NSLayoutConstraint(item: Your_messageInputConteinerView, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1, constant: 0)
view.addConstraint(bottomConstraint!)
}
func handleKeyboardNotification (notification: Notification) {
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
}
}
}
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
}
ça doit être plus stable
Utilisez le code suivant pour afficher vers le haut sur UITextField Clicked
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()
}
J'ai fabriqué un cocoapod pour simplifier les choses:
https://github.com/xtrinch/KeyboardLayoutHelper
Comment l'utiliser:
Créez une contrainte de mise en page automatique, attribuez-lui une classe de KeyboardLayoutConstraint dans le module KeyboardLayoutHelper et le module effectuera le travail nécessaire pour l'augmenter de manière à tenir compte de l'apparition et de la disparition du clavier. Voir exemple de projet sur les exemples d'utilisation (j'ai créé deux: textFields dans un scrollView et textFields centré verticalement avec deux vues de base - login et register).
La contrainte de présentation inférieure peut être de la vue du conteneur, du champ de texte lui-même, de n'importe quoi, vous le nommez.