web-dev-qa-db-fra.com

Le clavier iPad ne sera pas ignoré si le style de présentation ViewController modal est UIModalPresentationFormSheet

Note:

Voir la réponse acceptée (et non la plus votée) pour la solution à partir de iOS 4.3.

Cette question concerne un comportement découvert sur le clavier iPad, dans lequel il refuse d'être ignoré s'il est affiché dans une boîte de dialogue modale avec un contrôleur de navigation.

Fondamentalement, si je présente le contrôleur de navigation avec la ligne suivante comme ci-dessous:

navigationController.modalPresentationStyle = UIModalPresentationFormSheet;

Le clavier refuse d’être licencié. Si je commente cette ligne, le clavier s'en va bien.

...

J'ai deux textFields, nom d'utilisateur et mot de passe; nom d'utilisateur a un bouton Suivant et mot de passe a un bouton Terminé. Le clavier ne disparaîtra pas si je présente ceci dans un contrôleur de navigation modal.

FONCTIONNE

broken *b = [[broken alloc] initWithNibName:@"broken" bundle:nil];
[self.view addSubview:b.view];

NE FONCTIONNE PAS

broken *b = [[broken alloc] initWithNibName:@"broken" bundle:nil];
UINavigationController *navigationController = 
[[UINavigationController alloc]
 initWithRootViewController:b];
navigationController.modalPresentationStyle = UIModalPresentationFormSheet;
navigationController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:navigationController animated:YES];
[navigationController release];
[b release];

Si je supprime la partie du contrôleur de navigation et présente "b" en tant que contrôleur de vue modale, cela fonctionne. Le contrôleur de navigation est le problème?

FONCTIONNE

broken *b = [[broken alloc] initWithNibName:@"broken" bundle:nil];
b.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:b animated:YES];
[b release];

FONCTIONNE

broken *b = [[broken alloc] initWithNibName:@"broken" bundle:nil];
UINavigationController *navigationController = 
    [[UINavigationController alloc]
         initWithRootViewController:b];
[self presentModalViewController:navigationController animated:YES];
[navigationController release];
[b release];
214
Kalle

Dans le contrôleur de vue présenté sous forme modale, remplacez simplement disablesAutomaticKeyboardDismissal pour renvoyer NO:

- (BOOL)disablesAutomaticKeyboardDismissal {
    return NO;
}
115
Sebastian H

Cela a été classé comme "fonctionne comme prévu" par Apple ingénieurs. J'ai écrit un bogue pour cela il y a quelque temps. Leur raisonnement est que l'utilisateur va souvent entrer des données sous une forme modale ils essaient donc d'être "utiles" et de garder le clavier visible là où, normalement, différentes transitions au sein de la vue modale peuvent amener le clavier à s'afficher/se masquer à plusieurs reprises.

edit: voici la réponse d'un ingénieur Apple sur les forums de développement):

Votre vision at-elle été présentée par hasard avec le style UIModalPresentationFormSheet? Pour éviter les animations entrantes et sortantes fréquentes, le clavier reste parfois à l'écran, même en l'absence de premier répondant. Ce n'est pas un bug.

Cela pose beaucoup de problèmes aux gens (moi-même), mais pour le moment, il ne semble pas y avoir de moyen de contourner le problème.

UPDATE:

Dans iOS 4.3 et versions ultérieures, vous pouvez maintenant implémenter `-disablesAutomaticKeyboardDismissal 'sur votre contrôleur de vue pour renvoyer NO:

- (BOOL)disablesAutomaticKeyboardDismissal {
    return NO;
}

Cela corrige le problème.

172
Mike Weller

Faites attention si vous affichez le modal avec un UINavigationController. Vous devez ensuite définir le disablesAutomaticKeyboardDismissal sur le contrôleur de navigation et non sur le contrôleur de vue. Vous pouvez facilement le faire avec des catégories.

Fichier: UINavigationController + KeyboardDismiss.h

#import <Foundation/Foundation.h>

@interface UINavigationController (KeyboardDismiss)

- (BOOL)disablesAutomaticKeyboardDismissal;

@end

Fichier: UINavigationController + KeyboardDismiss.m

#import "UINavigationController+KeyboardDismiss.h"

@implementation UINavigationController(KeyboardDismiss)

- (BOOL)disablesAutomaticKeyboardDismissal
{
    return NO;
}

@end

N'oubliez pas d'importer la catégorie dans le fichier où vous utilisez UINavigationController.

149
Miha Hribar

J'ai résolu ce problème en utilisant le style de présentation UIModalPresentationPageSheet et en le redimensionnant immédiatement après. Ainsi:

viewController.modalPresentationStyle = UIModalPresentationPageSheet;
viewController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:viewController animated:YES];
viewController.view.superview.autoresizingMask = 
    UIViewAutoresizingFlexibleTopMargin | 
    UIViewAutoresizingFlexibleBottomMargin;    
viewController.view.superview.frame = CGRectMake(
    viewController.view.superview.frame.Origin.x,
    viewController.view.superview.frame.Origin.y,
    540.0f,
    529.0f
);
viewController.view.superview.center = self.view.center;
[viewController release];
51
azdev

Pour ceux qui ont des problèmes avec UINavigationController, voir ma réponse à une question similaire ici: https://stackoverflow.com/a/10507689/321785

Edit: Je considère cela comme une amélioration de la solution de Miha Hribar (puisque la décision est prise comme il se doit), et par opposition au commentaire de Pascal concernant une catégorie sur UIViewController

1
Chris Trahey

Si vous changez d’affichage modal, vous pouvez faire disparaître le clavier. Ce n'est pas joli et ça ne s'anime pas, mais vous pouvez le faire partir.

Ce serait bien s'il y avait un correctif, mais pour l'instant cela fonctionne. Vous pouvez le caler dans une catégorie sur UIViewController et l'appeler quand vous voulez que le clavier disparaisse:

@interface _TempUIVC : UIViewController
@end

@implementation _TempUIVC
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    return YES;
}
@end

@implementation UIViewController (Helpers)

- (void)_dismissModalViewController {
    [self dismissModalViewControllerAnimated:NO];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidHideNotification object:nil];
    [self release];
}

- (void)forceKeyboardDismissUsingModalToggle:(BOOL)animated {
    [self retain];
    _TempUIVC *tuivc = [[_TempUIVC alloc] init];
    tuivc.modalPresentationStyle = UIModalPresentationCurrentContext;
    [self presentModalViewController:tuivc animated:animated];
    if (animated) {
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_dismissModalViewController) name:UIKeyboardDidHideNotification object:nil];
    } else
        [self _dismissModalViewController];
    [tuivc release];
}

@end

Soyez prudent avec ceci cependant lorsque vous visualisezIDidappear/viewDidDisappear et que toutes ces méthodes sont appelées. Comme je l'ai dit, ce n'est pas joli, mais ça marche.

-Adam

1
Adam

Mettez ce code dans votre viewWillDisappear: la méthode du contrôleur actuel est un autre moyen de résoudre ce problème:

Class UIKeyboardImpl = NSClassFromString(@"UIKeyboardImpl");
id activeInstance = [UIKeyboardImpl performSelector:@selector(activeInstance)];
[activeInstance performSelector:@selector(dismissKeyboard)];
1
Story

Vous pouvez également contourner ce problème dans une application universelle en vérifiant simplement l'idiome. S'il s'agit d'un iPad, n'ouvrez pas le clavier automatiquement et laissez l'utilisateur appuyer sur ce qu'il souhaite modifier.

Ce n’est peut-être pas la solution la plus agréable, mais c’est très simple et ne nécessite aucun piratage sophistiqué qui rompt avec la prochaine version majeure d’iOS :)

1
Maciej Swic

peut ne pas être une solution parfaite, mais fonctionne
[auto.view finEdit: OUI];
de l'endroit où votre bouton ou votre geste est mis en œuvre pour présenter

0
Tanuj Jagoori

peut-être ne retourne pas NON, mais OUI. Alors ça peut partir.

Et vous avez un textFieldShouldEndEditing retournant également OUI?

Et pourquoi tirez-vous [nextResponder becomeFirstResponder] ?! désolé je vois maintenant

J'ai également un certain nombre de UITextViews qui ont tous leur propriété "editable" définie sur FALSE.

Pouvons-nous supposer qu’aucun d’eux, par hasard, n’a une valeur tag de secondField.tag+1? Si tel est le cas, vous leur demandez de devenir le premier intervenant au lieu de le démissionner. Peut-être mettre un peu NSLog () dans cette structure.

0
mvds

Je suis sûr que vous avez examiné la question, mais vous êtes certain que votre classe de contrôleurs est correctement connectée en tant que délégué UITextField, n'est-ce pas?

0
Neal L
Swift 4.1:
extension UINavigationController {
   override open var disablesAutomaticKeyboardDismissal: Bool {
      return false
   }
}
0
fivewood

J'ai trouvé que disablesAutomaticKeyboardDismissal et l'ajout d'une fonction disablesAutomaticKeyboardDismissal ne fonctionnait pas pour mon UITextField dans une boîte de dialogue modale.

Le clavier à l'écran ne partirait tout simplement pas.

Ma solution consistait à désactiver tous les contrôles de saisie de texte dans ma boîte de dialogue, puis à réactiver les contrôles pertinents une fraction de seconde plus tard.

Il semble que lorsque iOS voit qu'aucun des contrôles UITextField n'est activé, il ne se débarrasse du clavier.

0
Mike Gledhill