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];
Dans le contrôleur de vue présenté sous forme modale, remplacez simplement disablesAutomaticKeyboardDismissal
pour renvoyer NO
:
- (BOOL)disablesAutomaticKeyboardDismissal {
return NO;
}
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.
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.
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];
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
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
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)];
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 :)
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
peut-être ne retourne pas NON, mais OUI. Alors ça peut partir.
Et vous avez un textFieldShouldEndEditing
retournant également OUI?
Et pourquoi tirez-vous désolé je vois maintenant[nextResponder becomeFirstResponder]
?!
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.
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?
Swift 4.1:
extension UINavigationController {
override open var disablesAutomaticKeyboardDismissal: Bool {
return false
}
}
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.