J'utilisais ce code pour déterminer quelle était la taille du clavier:
- (void)keyboardWillChange:(NSNotification *)notification {
NSDictionary* keyboardInfo = [notification userInfo];
NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameBeginUserInfoKey];
CGRect keyboardFrameBeginRect = [keyboardFrameBegin CGRectValue];
}
J'exécute ceci dans le simulateur.
Le problème est que depuis iOS 8 cela ne donnera pas la valeur correcte, si les suggestions de clavier sont en hausse ou si je les pousse vers le bas, j'obtiens des valeurs différentes (non correctes).
Comment puis-je obtenir la taille exacte du clavier, y compris les suggestions de clavier?
Utilisation
NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameEndUserInfoKey];
Avec l'introduction de claviers personnalisés dans iOS, ce problème devient un peu plus complexe.
En bref, le UIKeyboardWillShowNotification peut être appelé plusieurs fois par des implémentations de clavier personnalisées:
Afin de gérer correctement ces scénarios dans une ligne de code, vous devez:
Inscrivez les observateurs contre les notifications UIKeyboardWillShowNotification et UIKeyboardWillHideNotification :
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:nil];
Créez une variable globale pour suivre la hauteur actuelle du clavier:
CGFloat _currentKeyboardHeight = 0.0f;
Implémentez keyboardWillShow pour réagir au changement actuel de la hauteur du clavier:
- (void)keyboardWillShow:(NSNotification*)notification {
NSDictionary *info = [notification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
CGFloat deltaHeight = kbSize.height - _currentKeyboardHeight;
// Write code to adjust views accordingly using deltaHeight
_currentKeyboardHeight = kbSize.height;
}
REMARQUE: vous souhaiterez peut-être animer le décalage des vues. Le dictionnaire info contient une valeur saisie par UIKeyboardAnimationDurationUserInfoKey . Cette valeur peut être utilisée pour animer vos modifications à la même vitesse que le clavier affiché.
Implémentez keyboardWillHide dans la réinitialisation _currentKeyboardHeight et réagissez à la suppression du clavier:
- (void)keyboardWillHide:(NSNotification*)notification {
NSDictionary *info = [notification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
// Write code to adjust views accordingly using kbSize.height
_currentKeyboardHeight = 0.0f;
}
J'ai également eu ce problème, jusqu'à ce que je tombe sur ce StackOverflow article:
Convertir UIKeyboardFrameEndUserInfoKey
Cela vous montre comment utiliser la fonction convertRect
pour convertir la taille du clavier en quelque chose d’utilisable, mais dans l’orientation de l’écran.
NSDictionary* d = [notification userInfo];
CGRect r = [d[UIKeyboardFrameEndUserInfoKey] CGRectValue];
r = [myView convertRect:r fromView:nil];
Auparavant, j'avais une application pour iPad qui utilisait UIKeyboardFrameEndUserInfoKey
mais ne utilisait pas convertRect
, et cela fonctionnait bien.
Mais avec iOS 8, cela ne fonctionnait plus correctement. Soudain, mon clavier fonctionnant sur un iPad en mode paysage aurait 1024 pixels de haut.
Alors maintenant, avec iOS 8, il est essentiel que vous utilisiez cette fonction convertRect
.
La solution similaire à dgangsta's écrite en Swift 2.0:
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name: UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name: UIKeyboardWillHideNotification, object: nil)
}
deinit {
NSNotificationCenter.defaultCenter().removeObserver(self)
}
func keyboardWillShow(notification: NSNotification) {
guard let kbSizeValue = notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue else { return }
guard let kbDurationNumber = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber else { return }
animateToKeyboardHeight(kbSizeValue.CGRectValue().height, duration: kbDurationNumber.doubleValue)
}
func keyboardWillHide(notification: NSNotification) {
guard let kbDurationNumber = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber else { return }
animateToKeyboardHeight(0, duration: kbDurationNumber.doubleValue)
}
func animateToKeyboardHeight(kbHeight: CGFloat, duration: Double) {
// your custom code here
}
Je fais extension
pour UIViewController
extension UIViewController {
func keyboardWillChangeFrameNotification(notification: NSNotification, scrollBottomConstant: NSLayoutConstraint) {
let duration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber
let curve = notification.userInfo?[UIKeyboardAnimationCurveUserInfoKey] as! NSNumber
let keyboardBeginFrame = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as! NSValue).CGRectValue()
let keyboardEndFrame = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue()
let screenHeight = UIScreen.mainScreen().bounds.height
let isBeginOrEnd = keyboardBeginFrame.Origin.y == screenHeight || keyboardEndFrame.Origin.y == screenHeight
let heightOffset = keyboardBeginFrame.Origin.y - keyboardEndFrame.Origin.y - (isBeginOrEnd ? bottomLayoutGuide.length : 0)
UIView.animateWithDuration(duration.doubleValue,
delay: 0,
options: UIViewAnimationOptions(rawValue: UInt(curve.integerValue << 16)),
animations: { () in
scrollBottomConstant.constant = scrollBottomConstant.constant + heightOffset
self.view.layoutIfNeeded()
},
completion: nil
)
}
}
Vous pouvez utiliser comme ceci:
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillChangeFrameNotification:", name: UIKeyboardWillChangeFrameNotification, object: nil)
}
...
deinit {
NSNotificationCenter.defaultCenter().removeObserver(self)
}
func keyboardWillChangeFrameNotification(notification: NSNotification) {
self.keyboardWillChangeFrameNotification(notification, scrollBottomConstant: inputContainerBottom)
// Write more to here if you want.
}
Il arrive parfois que les développeurs aient besoin de connaître la hauteur du clavier avant de l'afficher, ce qui leur permet de pré-agencer l'interface de manière appropriée.
Si tel est le cas, voici une spécification inclusive:
Cela inclut la barre de type rapide en haut, car elle est activée par défaut dans toutes les versions actuelles d’iOS.
Voici la Swift 3 que j'ai utilisée pour tester ceci, si quelqu'un en avait besoin:
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWillShow), name: .UIKeyboardWillShow, object: nil)
}
func keyboardWillShow(notification: NSNotification) {
guard let keyboardSize = notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue else { return }
print("\(keyboardSize)")
}
[notificationCenter addObserverForName:UIKeyboardWillChangeFrameNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification * _Nonnull note) {
float keyboardHeight = [[note.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height;
}];
En Swift, pas en une seule ligne ...
self.keyboardDidShowObserver = NSNotificationCenter.defaultCenter().addObserverForName(UIKeyboardDidShowNotification, object: nil, queue: NSOperationQueue.mainQueue(), usingBlock: { (notification) in
if let userInfo = notification.userInfo, let keyboardFrameValue = userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue {
let keyboardRect = keyboardFrameValue.CGRectValue()
// keyboardRect.height gives the height of the keyboard
// your additional code here...
}
})
Une seule corde pour Swift:
let keyboardSize = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue().size
UIKeyboardFrameEndUserInfoKey
stocke toujours NSValue
, donc inutile de le vérifier.
J'ai remarqué un problème lors de la commutation entre le clavier par défaut et un clavier personnalisé (UIPickerView
) - le clavier personnalisé afficherait une hauteur de 253 au lieu de 162, après la commutation du clavier par défaut.
Ce qui a bien fonctionné dans ce cas a été de mettre autocorrectionType = UITextAutocorrectionTypeNo;
pour le champ de saisie avec le clavier personnalisé.
Le problème ne s'est produit que dans iOS 8 (testé sur simulateur uniquement). Cela ne se produit pas dans iOS 9 (simulateur ou appareil).