web-dev-qa-db-fra.com

Déplacer le clavier vers le haut lors de l'édition de UITextField sur iOS9

Pour que mes claviers puissent découvrir UITextField dans mon application iOS, je mettais en œuvre cette réponse: https://stackoverflow.com/a/6908258/3855618 sur iOS7 et 8 et cela fonctionne parfaitement pour le moment. Cependant sur iOS 9.1, cela ne fonctionne plus.

Pour être plus précis, même si la vue d’arrière-plan se déplace vers le haut, la variable UITextField ne le fait pas.

Avez-vous une idée de ce qui a tant changé depuis iOS9 et iOS 9.1?

14
Gannicus

La réponse que vous avez liée n'est pas recommandée. Vous ne devez pas définir directement le cadre de la vue du contrôleur de vue, surtout si vous utilisez la disposition automatique. Au lieu de changer le cadre de la vue, vous devez ajouter une vue de défilement en tant que sous-vue à la vue et ajuster le contenu de l'encadré lorsque le clavier est affiché ou masqué.

De la pomme officielle doc :

Lorsqu'il est invité à afficher le clavier, le système le glisse depuis le bas de l'écran et le positionne sur le contenu de votre application. Comme il est placé au-dessus de votre contenu, il est possible que le clavier soit placé au-dessus de l'objet texte que l'utilisateur a voulu modifier. Dans ce cas, vous devez ajuster votre contenu pour que l'objet cible reste visible.

Pour ajuster votre contenu, vous devez généralement redimensionner temporairement une ou plusieurs vues et les positionner de manière à ce que l'objet texte reste visible. Le moyen le plus simple de gérer des objets texte avec le clavier est de les incorporer dans un objet UIScrollView (ou l’une de ses sous-classes comme UITableView). Lorsque le clavier est affiché, tout ce que vous avez à faire est de réinitialiser la zone de contenu de la vue de défilement et de faire défiler l'objet texte souhaité en position. Ainsi, en réponse à une UIKeyboardDidShowNotification, votre méthode de gestionnaire ferait ce qui suit:

  1. Obtenez la taille du clavier.
  2. Ajustez le contenu inférieur de votre vue de défilement en fonction de la hauteur du clavier.
  3. Faites défiler le champ de texte cible dans la vue.
 // Called when the UIKeyboardDidShowNotification is sent.
- (void)keyboardWasShown:(NSNotification*)aNotification
{
   NSDictionary* info = [aNotification userInfo];
   CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

   UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);
   scrollView.contentInset = contentInsets;
   scrollView.scrollIndicatorInsets = contentInsets;

   // If active text field is hidden by keyboard, scroll it so it's visible
   // Your app might not need or want this behavior.
   CGRect aRect = self.view.frame;
   aRect.size.height -= kbSize.height;
   if (!CGRectContainsPoint(aRect, activeField.frame.Origin) ) {
     [self.scrollView scrollRectToVisible:activeField.frame animated:YES];
   }
}

// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
   UIEdgeInsets contentInsets = UIEdgeInsetsZero;
   scrollView.contentInset = contentInsets;
   scrollView.scrollIndicatorInsets = contentInsets;
}
36
Istvan

Zéro ligne de code

Dénué de hacks, kludges, contournement et auditeurs.

La question actuelle a été posée maintes et maintes fois depuis l'aube du temps iOS. Aucune réponse sur StackOverflow n'a survécu à plus de 2 itérations iOS. À juste titre, parce que UIKit ne cesse de changer sous vos pieds. Il existe une solution conception par opposition à mise en oeuvre à cet ancien problème. Utilisez une UITableViewController.

Utiliser un UITableViewController

Quand une UITableView est gérée par une UITableViewController, le défilement est géré automatiquement pour vous. Jamais bricoler avec UIKeyboardWillShowNotification, plus jamais. Créez simplement UITableViewCells statique ou dynamique pour mettre en forme votre interface, ajoutez UITextView ou UITextField au besoin; devenir simplement le premier répondant fera défiler le lieu approprié.

@ disponibilité (iOS, introduit = 2.0)

 UITableViewController

Remarques

  1. Fonctionne sur tout iOS depuis la version 2.0.
  2. Citation: «Ne perdez pas de temps à optimiser un algorithme médiocre; choisissez-en un meilleur»
  3. Voir https://stackoverflow.com/a/32390936/218152 .
8
SwiftArchitect

Nous devons prendre le cadre du clavier de la notification. Lorsque vous obtenez la référence de scrollView, tableView, etc. Convertissez le bord inférieur de la vue en coordonnées de la fenêtre. Lorsque vous déterminez combien de clavier couvre notre vue et si la différence est supérieure à 0, vous pouvez ajouter un encadré ci-dessous. Essayez le code suivant:

- (void)subscribeKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillShow:)
                                                 name:UIKeyboardWillShowNotification
                                               object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillHide:)
                                                 name:UIKeyboardWillHideNotification
                                               object:nil];
}

- (void)unsubscribeKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:UIKeyboardWillShowNotification
                                                  object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:UIKeyboardWillHideNotification
                                                  object:nil];
}


- (void)keyboardWillShow:(NSNotification *)aNotification
{
    CGRect keyBoardFrame = [[[aNotification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];

    UIWindow *keyWindow = [[[UIApplication sharedApplication] delegate] window];

    UIScrollView *someScrollView = ......

    CGPoint tableViewBottomPoint = CGPointMake(0, CGRectGetMaxY([someScrollView bounds]));
    CGPoint convertedTableViewBottomPoint = [someScrollView convertPoint:tableViewBottomPoint
                                                                           toView:keyWindow];

    CGFloat keyboardOverlappedSpaceHeight = convertedTableViewBottomPoint.y - keyBoardFrame.Origin.y;

    if (keyboardOverlappedSpaceHeight > 0)
    {
        UIEdgeInsets tableViewInsets = UIEdgeInsetsMake(0, 0, keyboardOverlappedSpaceHeight, 0);
        [someScrollView setContentInset:tableViewInsets];
    }
}

- (void)keyboardWillHide:(NSNotification *)aNotification
{
    UIEdgeInsets tableViewInsets = UIEdgeInsetsZero;
    UIScrollView *someScrollView = ......

    [someScrollView setContentInset:tableViewInsets];
}
3
NixSolutionsMobile

j'ai suivi la doc de @Istvan sur le site Apple et il me manque beaucoup de choses pour que cela fonctionne:
1. Définissez votre document .h sur <UITextFieldDelegate> (pour pouvoir travailler avec "activefield")
2. Dans viewDidLoad, définissez les délégués sur vos champs UIText et définissez la hauteur de votre contenu scrollview avec une hauteur supérieure (dans mon cas, j'en ai défini 500 autres):

CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat screenWidth = screenRect.size.width;
CGFloat screenHeight = screenRect.size.height + 500;
_scrollView.contentSize = CGSizeMake(screenWidth, screenHeight);

Et maintenant tout fonctionne ...

1
Rwakos

Ajoutez tous UITextField sur UIScrollView et utilisez TPKeyboardAvoiding

1
Varun Naharia

J'écoute généralement les notifications du clavier et modifie en fonction des contraintes de présentation. Voir mon autre réponse pour plus de détails et un exemple de projet.

1
NKorotkov

Essayez ce code que j'ai utilisé dans mes projets précédents:

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
    [self didBeginEditingIn:textField];
}

- (void)textFieldDidEndEditing:(UITextField *)textField
{
    [self didEndEditing];
}


static const CGFloat KEYBOARD_ANIMATION_DURATION = 0.3;
static const CGFloat MINIMUM_SCROLL_FRACTION = 0.2;
static const CGFloat MAXIMUM_SCROLL_FRACTION = 0.8;
static const CGFloat PORTRAIT_KEYBOARD_HEIGHT = 216+100;
static const CGFloat LANDSCAPE_KEYBOARD_HEIGHT = 162+100;

- (void)didBeginEditingIn:(UIView *)view
{
    CGRect textFieldRect = [self.view.window convertRect:view.bounds fromView:view];
    CGRect viewRect = [self.view.window convertRect:self.view.bounds fromView:self.view];

    CGFloat midline = textFieldRect.Origin.y + 0.5* textFieldRect.size.height;
    CGFloat numerator = midline - viewRect.Origin.y- MINIMUM_SCROLL_FRACTION * viewRect.size.height;
    CGFloat denominator = (MAXIMUM_SCROLL_FRACTION - MINIMUM_SCROLL_FRACTION)* viewRect.size.height;
    CGFloat heightFraction = numerator / denominator;

    if (heightFraction < 0.0)
    {
        heightFraction = 0.0;
    }
    else if (heightFraction > 1.0)
    {
        heightFraction = 1.0;
    }

    UIInterfaceOrientation orientation =
    [[UIApplication sharedApplication] statusBarOrientation];
    if (orientation == UIInterfaceOrientationPortrait ||
        orientation == UIInterfaceOrientationPortraitUpsideDown)
    {
        _animatedDistance = floor(PORTRAIT_KEYBOARD_HEIGHT * heightFraction);
    }
    else
    {
        _animatedDistance = floor(LANDSCAPE_KEYBOARD_HEIGHT * heightFraction);
    }

    CGRect viewFrame = self.view.frame;
    viewFrame.Origin.y -= _animatedDistance;

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];

    [self.view setFrame:viewFrame];

    [UIView commitAnimations];
}

- (void)didEndEditing
{
    CGRect viewFrame = self.view.frame;
    viewFrame.Origin.y += _animatedDistance;

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];

    [self.view setFrame:viewFrame];

    [UIView commitAnimations];
}
1
Nishant