web-dev-qa-db-fra.com

ne peut pas obtenir la valeur correcte de la hauteur du clavier dans iOS8

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?

81
Eli Braginskiy

Utilisation

NSValue* keyboardFrameBegin = [keyboardInfo valueForKey:UIKeyboardFrameEndUserInfoKey];
95
souvickcse

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:

  1. Lorsque le clavier système Apple est ouvert (en portrait)
    • UIKeyboardWillShowNotification est envoyé avec une hauteur de clavier de 224
  2. Lorsque le clavier Swype est ouvert (en portrait):
    • UIKeyboardWillShowNotification est envoyé avec une hauteur de clavier de
    • UIKeyboardWillShowNotification est envoyé avec une hauteur de clavier de 216
    • UIKeyboardWillShowNotification est envoyé avec une hauteur de clavier de 256
  3. Lorsque le clavier SwiftKey est ouvert (en portrait):
    • UIKeyboardWillShowNotification est envoyé avec une hauteur de clavier de
    • UIKeyboardWillShowNotification est envoyé avec une hauteur de clavier de 216
    • UIKeyboardWillShowNotification est envoyé avec une hauteur de clavier de 259

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;
}
120
dgangsta

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.

18
Mike Gledhill

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

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.
}
5
Wanbok Choi

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:

enter image description here

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)")
}
4
Travis M.
[notificationCenter addObserverForName:UIKeyboardWillChangeFrameNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:^(NSNotification * _Nonnull note) {

    float keyboardHeight = [[note.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height;

}];
0
Leo Cavalcante

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...
        }
    })
0
Murray Sagal

Une seule corde pour Swift:

let keyboardSize = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue().size

UIKeyboardFrameEndUserInfoKey stocke toujours NSValue, donc inutile de le vérifier.

0
Petr Syrov

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

0
alex-i