web-dev-qa-db-fra.com

Comment puis-je faire monter un UITextField quand le clavier est présent - au début de l'édition?

Avec le SDK iOS:

J'ai une UIView avec UITextFields qui fait apparaître un clavier. J'en ai besoin pour pouvoir:

  1. Autoriser le défilement du contenu de la UIScrollView pour voir les autres champs de texte une fois le clavier affiché

  2. "Sauter" automatiquement (en faisant défiler vers le haut) ou raccourcir

Je sais que j'ai besoin d'une UIScrollView. J'ai essayé de changer la classe de ma UIView en UIScrollView mais je ne parviens toujours pas à faire défiler les zones de texte vers le haut ou le bas. 

Ai-je besoin à la fois d'une UIView et d'une UIScrollView? Est-ce que l'un va dans l'autre?

Que faut-il implémenter pour faire défiler automatiquement jusqu'au champ de texte actif?

Dans l'idéal, autant de configurations de composants que possible seront effectuées dans Interface Builder. Je voudrais écrire uniquement du code pour ce qui en a besoin.

Remarque: la UIView (ou UIScrollView) avec laquelle je travaille est affichée par un onglet (UITabBar), qui doit fonctionner normalement.


Edit: J'ajoute la barre de défilement uniquement lorsque le clavier apparaît. Même si ce n’est pas nécessaire, j’ai l’impression que cette interface offre une meilleure interface, car elle permet à l’utilisateur de faire défiler et de modifier les zones de texte, par exemple. 

Je le fais fonctionner où je change la taille de la UIScrollView quand le clavier monte et descend. J'utilise simplement: 

-(void)textFieldDidBeginEditing:(UITextField *)textField { 
    //Keyboard becomes visible
    scrollView.frame = CGRectMake(scrollView.frame.Origin.x, 
                     scrollView.frame.Origin.y, 
scrollView.frame.size.width,
scrollView.frame.size.height - 215 + 50);   //resize
}

-(void)textFieldDidEndEditing:(UITextField *)textField {
   //keyboard will hide
    scrollView.frame = CGRectMake(scrollView.frame.Origin.x, 
       scrollView.frame.Origin.y, 
     scrollView.frame.size.width,
      scrollView.frame.size.height + 215 - 50); //resize
}

Cependant, cela ne "remonte" pas automatiquement ni ne centre les champs de texte inférieurs dans la zone visible, ce que j'aimerais vraiment.

1609
philfreo
  1. Vous aurez seulement besoin d'un ScrollView si le contenu que vous avez maintenant ne correspond pas à l'écran de l'iPhone. (Si vous ajoutez le ScrollView comme vue d'ensemble des composants. Juste pour que le TextField défile vers le haut lorsque le clavier apparaît, alors ce n'est pas nécessaire.)

  2. Pour afficher le textfields sans être masqué par le clavier, la méthode standard consiste à déplacer la vue vers le haut/le bas avec des champs de texte chaque fois que le clavier est affiché.

Voici un exemple de code:

#define kOFFSET_FOR_KEYBOARD 80.0

-(void)keyboardWillShow {
    // Animate the current view out of the way
    if (self.view.frame.Origin.y >= 0)
    {
        [self setViewMovedUp:YES];
    }
    else if (self.view.frame.Origin.y < 0)
    {
        [self setViewMovedUp:NO];
    }
}

-(void)keyboardWillHide {
    if (self.view.frame.Origin.y >= 0)
    {
        [self setViewMovedUp:YES];
    }
    else if (self.view.frame.Origin.y < 0)
    {
        [self setViewMovedUp:NO];
    }
}

-(void)textFieldDidBeginEditing:(UITextField *)sender
{
    if ([sender isEqual:mailTf])
    {
        //move the main view, so that the keyboard does not hide it.
        if  (self.view.frame.Origin.y >= 0)
        {
            [self setViewMovedUp:YES];
        }
    }
}

//method to move the view up/down whenever the keyboard is shown/dismissed
-(void)setViewMovedUp:(BOOL)movedUp
{
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.3]; // if you want to slide up the view

    CGRect rect = self.view.frame;
    if (movedUp)
    {
        // 1. move the view's Origin up so that the text field that will be hidden come above the keyboard 
        // 2. increase the size of the view so that the area behind the keyboard is covered up.
        rect.Origin.y -= kOFFSET_FOR_KEYBOARD;
        rect.size.height += kOFFSET_FOR_KEYBOARD;
    }
    else
    {
        // revert back to the normal state.
        rect.Origin.y += kOFFSET_FOR_KEYBOARD;
        rect.size.height -= kOFFSET_FOR_KEYBOARD;
    }
    self.view.frame = rect;

    [UIView commitAnimations];
}


- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    // register for keyboard notifications
    [[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardWillShow)
                                             name:UIKeyboardWillShowNotification
                                           object:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardWillHide)
                                             name:UIKeyboardWillHideNotification
                                           object:nil];
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    // unregister for keyboard notifications while not visible.
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                             name:UIKeyboardWillShowNotification
                                           object:nil];

    [[NSNotificationCenter defaultCenter] removeObserver:self
                                             name:UIKeyboardWillHideNotification
                                           object:nil];
}
1020
RPDP

Je rencontrais également de nombreux problèmes avec une composition UIScrollView composée de plusieurs UITextFields, dont une ou plusieurs seraient masquées par le clavier lors de leur modification. 

Voici quelques éléments à prendre en compte si votre UIScrollView ne défile pas correctement. 

1) Assurez-vous que votre contentSize est supérieur à la taille du cadre UIScrollView. La façon de comprendre UIScrollViews est que UIScrollView est comme une fenêtre d'affichage sur le contenu défini dans le contentSize. Donc, pour que UIScrollview puisse défiler n'importe où, contentSize doit être supérieur à UIScrollView. Sinon, aucun défilement n'est requis car tout ce qui est défini dans contentSize est déjà visible. BTW, par défaut contentSize = CGSizeZero.

2) Maintenant que vous comprenez que UIScrollView est vraiment une fenêtre sur votre "contenu", le moyen de s’assurer que le clavier n’obscurcit pas votre "fenêtre" de UIScrollView's consiste à redimensionner le UIScrollView de sorte que lorsque le clavier est présent, avoir la fenêtre UIScrollView dimensionnée uniquement à l'original UIScrollView frame.size.height moins la hauteur du clavier. Cela garantira que votre fenêtre est seulement cette petite zone visible.

3) Voici le piège: Quand j'ai implémenté ceci pour la première fois, j'ai pensé que je devrais obtenir le CGRect du champ de texte édité et appeler la méthode UIScrollView's scrollRecToVisible. J'ai implémenté la méthode UITextFieldDelegatetextFieldDidBeginEditing avec l'appel de la méthode scrollRecToVisible. Cela fonctionnait réellement avec un effet secondaire étrange que le défilement serait enclenché le UITextField en position. Pendant longtemps, je ne pouvais pas comprendre ce que c'était. Ensuite, j'ai commenté la méthode textFieldDidBeginEditing Delegate et tout fonctionne !! (???). En fin de compte, je crois que UIScrollView amène implicitement implicitement le UITextField actuellement édité dans la fenêtre visualisable. Mon implémentation de la méthode UITextFieldDelegate et l'appel suivant à scrollRecToVisible étaient redondants et étaient à l'origine de cet effet secondaire étrange.

Voici donc les étapes à suivre pour faire défiler correctement votre UITextField dans un UIScrollView lorsque le clavier apparaît.

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.

- (void)viewDidLoad 
{
    [super viewDidLoad];

    // register for keyboard notifications
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(keyboardWillShow:) 
                                                 name:UIKeyboardWillShowNotification 
                                               object:self.view.window];
    // register for keyboard notifications
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(keyboardWillHide:) 
                                                 name:UIKeyboardWillHideNotification 
                                               object:self.view.window];
    keyboardIsShown = NO;
    //make contentSize bigger than your scrollSize (you will need to figure out for your own use case)
    CGSize scrollContentSize = CGSizeMake(320, 345);
    self.scrollView.contentSize = scrollContentSize;
}

- (void)keyboardWillHide:(NSNotification *)n
{
    NSDictionary* userInfo = [n userInfo];

    // get the size of the keyboard
    CGSize keyboardSize = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;


    // resize the scrollview
    CGRect viewFrame = self.scrollView.frame;
    // I'm also subtracting a constant kTabBarHeight because my UIScrollView was offset by the UITabBar so really only the portion of the keyboard that is leftover pass the UITabBar is obscuring my UIScrollView.
    viewFrame.size.height += (keyboardSize.height - kTabBarHeight);

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [self.scrollView setFrame:viewFrame];
    [UIView commitAnimations];

    keyboardIsShown = NO;
}

- (void)keyboardWillShow:(NSNotification *)n
{
    // This is an ivar I'm using to ensure that we do not do the frame size adjustment on the `UIScrollView` if the keyboard is already shown.  This can happen if the user, after fixing editing a `UITextField`, scrolls the resized `UIScrollView` to another `UITextField` and attempts to edit the next `UITextField`.  If we were to resize the `UIScrollView` again, it would be disastrous.  NOTE: The keyboard notification will fire even when the keyboard is already shown.
    if (keyboardIsShown) {
        return;
    }

    NSDictionary* userInfo = [n userInfo];

    // get the size of the keyboard
    CGSize keyboardSize = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;

    // resize the noteView
    CGRect viewFrame = self.scrollView.frame;
    // I'm also subtracting a constant kTabBarHeight because my UIScrollView was offset by the UITabBar so really only the portion of the keyboard that is leftover pass the UITabBar is obscuring my UIScrollView.
    viewFrame.size.height -= (keyboardSize.height - kTabBarHeight);

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [self.scrollView setFrame:viewFrame];
    [UIView commitAnimations];
    keyboardIsShown = YES;
}
  1. Inscrivez-vous pour recevoir les notifications du clavier sur viewDidLoad
  2. Désinscription des notifications de clavier à viewDidUnload
  3. Assurez-vous que contentSize est défini et supérieur à UIScrollView à viewDidLoad.
  4. Shrink the UIScrollView quand le clavier est présent
  5. Revenir en arrière le UIScrollView lorsque le clavier s’éloigne.
  6. Utilisez un ivar pour détecter si le clavier est déjà affiché à l'écran puisque les notifications du clavier sont envoyées chaque fois qu'un UITextField est mis en onglet, même si le clavier est déjà présent pour éviter rétrécir le UIScrollView quand il est déjà rétréci

Une chose à noter est que le UIKeyboardWillShowNotification se déclenche même lorsque le clavier est déjà à l'écran lorsque vous utilisez un autre UITextField. Je me suis occupé de cela en utilisant un ivar pour éviter de redimensionner le UIScrollView quand le clavier est déjà à l'écran. Redimensionner par inadvertance le UIScrollView quand le clavier est déjà là serait désastreux!

J'espère que ce code évite à certains d'entre vous beaucoup de maux de tête. 

439
Shiun

En fait, il est préférable d'utiliser l'implémentation d'Apple, comme indiqué dans docs . Cependant, le code qu'ils fournissent est défectueux. Remplacez la partie trouvée dans keyboardWasShown: juste en dessous des commentaires comme suit:

NSDictionary* info = [aNotification userInfo];
CGRect keyPadFrame=[[UIApplication sharedApplication].keyWindow convertRect:[[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue] fromView:self.view];
CGSize kbSize =keyPadFrame.size;
CGRect activeRect=[self.view convertRect:activeField.frame fromView:activeField.superview];
CGRect aRect = self.view.bounds;
aRect.size.height -= (kbSize.height);

CGPoint Origin =  activeRect.Origin;
Origin.y -= backScrollView.contentOffset.y;
if (!CGRectContainsPoint(aRect, Origin)) {
    CGPoint scrollPoint = CGPointMake(0.0,CGRectGetMaxY(activeRect)-(aRect.size.height));
    [backScrollView setContentOffset:scrollPoint animated:YES];
}

Les problèmes avec le code Apple sont les suivants: (1) Ils calculent toujours si le point est dans le cadre de la vue, mais il s'agit d'une ScrollView, de sorte qu'il a peut-être déjà défilé et que vous devez tenir compte de ce décalage:

Origin.y -= scrollView.contentOffset.y

(2) Ils décalent le contentOffset de la hauteur du clavier, mais nous voulons l’inverse (nous voulons décaler la contentOffset de la hauteur visible à l’écran, pas de ce qui ne l’est pas):

activeField.frame.Origin.y-(aRect.size.height)
265
DK_

Dans textFieldDidBeginEditting et dans textFieldDidEndEditing, appelez la fonction [self animateTextField:textField up:YES] comme suit: 

-(void)textFieldDidBeginEditing:(UITextField *)textField 
{ 
    [self animateTextField:textField up:YES]; 
}

- (void)textFieldDidEndEditing:(UITextField *)textField
{
    [self animateTextField:textField up:NO];
}

-(void)animateTextField:(UITextField*)textField up:(BOOL)up
{
    const int movementDistance = -130; // Tweak as needed
    const float movementDuration = 0.3f; // Tweak as needed

    int movement = (up ? movementDistance : -movementDistance); 

    [UIView beginAnimations: @"animateTextField" context: nil];
    [UIView setAnimationBeginsFromCurrentState: YES];
    [UIView setAnimationDuration: movementDuration];
    self.view.frame = CGRectOffset(self.view.frame, 0, movement);
    [UIView commitAnimations];
}

J'espère que ce code vous aidera. 

Dans Swift 2

func animateTextField(textField: UITextField, up: Bool) 
{
     let movementDistance:CGFloat = -130
     let movementDuration: Double = 0.3

     var movement:CGFloat = 0
     if up 
     {
         movement = movementDistance
     }
     else 
     {
         movement = -movementDistance
     }
     UIView.beginAnimations("animateTextField", context: nil)
     UIView.setAnimationBeginsFromCurrentState(true)
     UIView.setAnimationDuration(movementDuration)
     self.view.frame = CGRectOffset(self.view.frame, 0, movement)
     UIView.commitAnimations()
}


func textFieldDidBeginEditing(textField: UITextField) 
{
    self.animateTextField(textField, up:true)
}

func textFieldDidEndEditing(textField: UITextField) 
{
    self.animateTextField(textField, up:false)
}

Swift 3

 func animateTextField(textField: UITextField, up: Bool)
    {
        let movementDistance:CGFloat = -130
        let movementDuration: Double = 0.3

        var movement:CGFloat = 0
        if up
        {
            movement = movementDistance
        }
        else
        {
            movement = -movementDistance
        }
        UIView.beginAnimations("animateTextField", context: nil)
        UIView.setAnimationBeginsFromCurrentState(true)
        UIView.setAnimationDuration(movementDuration)
        self.view.frame = self.view.frame.offsetBy(dx: 0, dy: movement)
        UIView.commitAnimations()
    }


    func textFieldDidBeginEditing(textField: UITextField)
    {
        self.animateTextField(textField: textField, up:true)
    }

    func textFieldDidEndEditing(textField: UITextField)
    {
        self.animateTextField(textField: textField, up:false)
    }
242
sumanthkodi

Juste en utilisant TextFields:

1a) Utilisation de Interface Builder: Sélectionnez All TextFields => Edit => Embed In => ScrollView

1b) Intégrez manuellement les TextField dans UIScrollView appelé scrollView

2) Définir UITextFieldDelegate

3) Définissez chaque textField.delegate = self; (ou établissez des connexions dans Interface Builder)

4) Copier/coller:

- (void)textFieldDidBeginEditing:(UITextField *)textField {
    CGPoint scrollPoint = CGPointMake(0, textField.frame.Origin.y);
    [scrollView setContentOffset:scrollPoint animated:YES];
}

- (void)textFieldDidEndEditing:(UITextField *)textField {
    [scrollView setContentOffset:CGPointZero animated:YES];
}
133
DAS

Pour Universal Solution, voici mon approche pour implémenter IQKeyboardManager .

enter image description here

Step1: - J'ai ajouté les notifications globales de UITextField, UITextView et UIKeyboard dans une classe singleton. Je l’appelle IQKeyboardManager .

Step2: - Si on trouve des notifications UIKeyboardWillShowNotification, UITextFieldTextDidBeginEditingNotification ou UITextViewTextDidBeginEditingNotification, j'essaie d'obtenir l'instance topMostViewController à partir de la hiérarchie UIWindow.rootViewController. Afin de découvrir correctement la variable UITextFieldUITextView, le cadre de topMostViewController.view doit être ajusté.

_/Étape 3: - J'ai calculé la distance de déplacement attendue de topMostViewController.view par rapport à la première réponse UITextFieldUITextView.

_/Step4: - J'ai déplacé topMostViewController.view.frame haut/bas en fonction de la distance de déplacement attendue.

Step5: - Si on trouve la notification UIKeyboardWillHideNotification, UITextFieldTextDidEndEditingNotification ou UITextViewTextDidEndEditingNotification, j'essaie à nouveau d'obtenir l'instance topMostViewController de la hiérarchie UIWindow.rootViewController.

Step6: - J'ai calculé la distance perturbée de topMostViewController.view qui doit être restaurée à sa position d'origine.

Step7: - J'ai restauré topMostViewController.view.frame en fonction de la distance perturbée.

Step8: - J'ai instancié singleton IQKeyboardManager instance de classe lors du chargement de l'application, ainsi chaque UITextFieldUITextView dans l'application s'ajuste automatiquement en fonction de la distance de déplacement attendue.

C'est tout IQKeyboardManager fait pour vous avec _/NO LINE OF CODE vraiment !! seulement besoin de glisser-déposer le fichier source lié au projet. IQKeyboardManager prend également en charge Orientation du périphérique, Gestion automatique UIToolbar, KeybkeyboardDistanceFromTextField et bien plus que vous ne le pensez.

110

J'ai mis en place une sous-classe universelle UIScrollView, UITableView et même UICollectionView qui se charge de déplacer tous les champs de texte qu'elle contient hors du chemin du clavier.

Lorsque le clavier est sur le point d'apparaître, la sous-classe trouve la sous-vue sur le point d'être modifiée et ajuste son cadre et son contenu afin de s'assurer que cette vue est visible, avec une animation correspondant à la fenêtre contextuelle du clavier. Lorsque le clavier disparaît, il rétablit sa taille précédente.

Cela devrait fonctionner avec pratiquement n'importe quelle configuration, soit une interface basée sur UITableView, soit une interface composée de vues placées manuellement.

Voici la solution: pour déplacer les champs de texte hors du chemin du clavier

101
Michael Tyson

Pour Swift Programmeurs:

Cela fera tout pour vous, il suffit de les mettre dans votre classe de contrôleur de vue et d'implémenter la variable UITextFieldDelegate dans votre contrôleur de vue et de définir le délégué de textField sur self 

textField.delegate = self // Setting delegate of your UITextField to self

Implémentez les méthodes de rappel du délégué:

func textFieldDidBeginEditing(textField: UITextField) {
    animateViewMoving(true, moveValue: 100)
}

func textFieldDidEndEditing(textField: UITextField) {
    animateViewMoving(false, moveValue: 100)
}

// Lifting the view up
func animateViewMoving (up:Bool, moveValue :CGFloat){
    let movementDuration:NSTimeInterval = 0.3
    let movement:CGFloat = ( up ? -moveValue : moveValue)
    UIView.beginAnimations( "animateView", context: nil)
    UIView.setAnimationBeginsFromCurrentState(true)
    UIView.setAnimationDuration(movementDuration )
    self.view.frame = CGRectOffset(self.view.frame, 0,  movement)
    UIView.commitAnimations()
}
85
Satnam Sync

Il y a déjà beaucoup de réponses, mais aucune des solutions ci-dessus ne contenait toutes les astuces de positionnement sophistiquées requises pour une animation "parfaite", sans bug, avec compatibilité ascendante et sans scintillement. (bug lors de l'animation d'images/bornes et de contentOffset ensemble, différentes orientations d'interface, clavier partagé iPad, ...)
Laissez-moi partager ma solution: 
(en supposant que vous ayez configuré UIKeyboardWill(Show|Hide)Notification)

// Called when UIKeyboardWillShowNotification is sent
- (void)keyboardWillShow:(NSNotification*)notification
{
    // if we have no view or are not visible in any window, we don't care
    if (!self.isViewLoaded || !self.view.window) {
        return;
    }

    NSDictionary *userInfo = [notification userInfo];

    CGRect keyboardFrameInWindow;
    [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardFrameInWindow];

    // the keyboard frame is specified in window-level coordinates. this calculates the frame as if it were a subview of our view, making it a sibling of the scroll view
    CGRect keyboardFrameInView = [self.view convertRect:keyboardFrameInWindow fromView:nil];

    CGRect scrollViewKeyboardIntersection = CGRectIntersection(_scrollView.frame, keyboardFrameInView);
    UIEdgeInsets newContentInsets = UIEdgeInsetsMake(0, 0, scrollViewKeyboardIntersection.size.height, 0);

    // this is an old animation method, but the only one that retains compaitiblity between parameters (duration, curve) and the values contained in the userInfo-Dictionary.
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
    [UIView setAnimationCurve:[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];

    _scrollView.contentInset = newContentInsets;
    _scrollView.scrollIndicatorInsets = newContentInsets;

    /*
     * Depending on visual layout, _focusedControl should either be the input field (UITextField,..) or another element
     * that should be visible, e.g. a purchase button below an amount text field
     * it makes sense to set _focusedControl in delegates like -textFieldShouldBeginEditing: if you have multiple input fields
     */
    if (_focusedControl) {
        CGRect controlFrameInScrollView = [_scrollView convertRect:_focusedControl.bounds fromView:_focusedControl]; // if the control is a deep in the hierarchy below the scroll view, this will calculate the frame as if it were a direct subview
        controlFrameInScrollView = CGRectInset(controlFrameInScrollView, 0, -10); // replace 10 with any Nice visual offset between control and keyboard or control and top of the scroll view.

        CGFloat controlVisualOffsetToTopOfScrollview = controlFrameInScrollView.Origin.y - _scrollView.contentOffset.y;
        CGFloat controlVisualBottom = controlVisualOffsetToTopOfScrollview + controlFrameInScrollView.size.height;

        // this is the visible part of the scroll view that is not hidden by the keyboard
        CGFloat scrollViewVisibleHeight = _scrollView.frame.size.height - scrollViewKeyboardIntersection.size.height;

        if (controlVisualBottom > scrollViewVisibleHeight) { // check if the keyboard will hide the control in question
            // scroll up until the control is in place
            CGPoint newContentOffset = _scrollView.contentOffset;
            newContentOffset.y += (controlVisualBottom - scrollViewVisibleHeight);

            // make sure we don't set an impossible offset caused by the "Nice visual offset"
            // if a control is at the bottom of the scroll view, it will end up just above the keyboard to eliminate scrolling inconsistencies
            newContentOffset.y = MIN(newContentOffset.y, _scrollView.contentSize.height - scrollViewVisibleHeight);

            [_scrollView setContentOffset:newContentOffset animated:NO]; // animated:NO because we have created our own animation context around this code
        } else if (controlFrameInScrollView.Origin.y < _scrollView.contentOffset.y) {
            // if the control is not fully visible, make it so (useful if the user taps on a partially visible input field
            CGPoint newContentOffset = _scrollView.contentOffset;
            newContentOffset.y = controlFrameInScrollView.Origin.y;

            [_scrollView setContentOffset:newContentOffset animated:NO]; // animated:NO because we have created our own animation context around this code
        }
    }

    [UIView commitAnimations];
}


// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillHide:(NSNotification*)notification
{
    // if we have no view or are not visible in any window, we don't care
    if (!self.isViewLoaded || !self.view.window) {
        return;
    }

    NSDictionary *userInfo = notification.userInfo;

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:[[userInfo valueForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
    [UIView setAnimationCurve:[[userInfo valueForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];

    // undo all that keyboardWillShow-magic
    // the scroll view will adjust its contentOffset apropriately
    _scrollView.contentInset = UIEdgeInsetsZero;
    _scrollView.scrollIndicatorInsets = UIEdgeInsetsZero;

    [UIView commitAnimations];
}
63
Martin Ullrich

Shiun a déclaré: "En fait, je pense qu'UIScrollView introduit implicitement implicitement le UITextField actuellement édité dans la fenêtre visible" Cela semble être vrai pour iOS 3.1.3, mais pas pour 3.2, 4.0 ou 4.1. J'ai dû ajouter un scrollRectToVisible explicite afin de rendre UITextField visible sur iOS> = 3.2.

61
cbranch

Une chose à considérer est de savoir si vous voulez jamais utiliser une UITextField seule. Je n’ai rencontré aucune application iPhone bien conçue qui utilise réellement UITextFields en dehors de UITableViewCells.

Ce sera un travail supplémentaire, mais je vous recommande de mettre en œuvre toutes les vues de saisie de données sous forme de vues de table. Ajoutez une UITextView à votre UITableViewCells.

46
Jonathan Sterling

This document détaille une solution à ce problème. Consultez le code source sous "Déplacer le contenu situé sous le clavier". C'est assez simple.

EDIT: Remarqué il y a un petit problème dans l'exemple. Vous voudrez probablement écouter UIKeyboardWillHideNotification au lieu de UIKeyboardDidHideNotification. Sinon, la vue de défilement derrière le clavier sera tronquée pendant toute la durée de l'animation de fermeture du clavier.

45
Mihai Damian

La solution la plus simple trouvée  

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
    [self animateTextField: textField up: YES];
}


- (void)textFieldDidEndEditing:(UITextField *)textField
{
    [self animateTextField: textField up: NO];
}

- (void) animateTextField: (UITextField*) textField up: (BOOL) up
{
    const int movementDistance = 80; // Tweak as needed
    const float movementDuration = 0.3f; // Tweak as needed

    int movement = (up ? -movementDistance : movementDistance);

    [UIView beginAnimations: @"anim" context: nil];
    [UIView setAnimationBeginsFromCurrentState: YES];
    [UIView setAnimationDuration: movementDuration];
    self.view.frame = CGRectOffset(self.view.frame, 0, movement);
    [UIView commitAnimations];
}
32
Xar E Ahmer

Petit correctif qui fonctionne pour de nombreux UITextFields

#pragma mark UIKeyboard handling

#define kMin 150

-(void)textFieldDidBeginEditing:(UITextField *)sender
{
   if (currTextField) {
      [currTextField release];
   }
   currTextField = [sender retain];
   //move the main view, so that the keyboard does not hide it.
   if (self.view.frame.Origin.y + currTextField.frame.Origin. y >= kMin) {
        [self setViewMovedUp:YES]; 
   }
}



//method to move the view up/down whenever the keyboard is shown/dismissed
-(void)setViewMovedUp:(BOOL)movedUp
{
   [UIView beginAnimations:nil context:NULL];
   [UIView setAnimationDuration:0.3]; // if you want to slide up the view

   CGRect rect = self.view.frame;
   if (movedUp)
   {
      // 1. move the view's Origin up so that the text field that will be hidden come above the keyboard 
      // 2. increase the size of the view so that the area behind the keyboard is covered up.
      rect.Origin.y = kMin - currTextField.frame.Origin.y ;
   }
   else
   {
      // revert back to the normal state.
      rect.Origin.y = 0;
   }
   self.view.frame = rect;

   [UIView commitAnimations];
}


- (void)keyboardWillShow:(NSNotification *)notif
{
   //keyboard will be shown now. depending for which textfield is active, move up or move down the view appropriately

   if ([currTextField isFirstResponder] && currTextField.frame.Origin.y + self.view.frame.Origin.y >= kMin)
   {
      [self setViewMovedUp:YES];
   }
   else if (![currTextField isFirstResponder] && currTextField.frame.Origin.y  + self.view.frame.Origin.y < kMin)
   {
      [self setViewMovedUp:NO];
   }
}

- (void)keyboardWillHide:(NSNotification *)notif
{
   //keyboard will be shown now. depending for which textfield is active, move up or move down the view appropriately
   if (self.view.frame.Origin.y < 0 ) {
      [self setViewMovedUp:NO];
   }

}


- (void)viewWillAppear:(BOOL)animated
{
   // register for keyboard notifications
   [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) 
                                                name:UIKeyboardWillShowNotification object:self.view.window]; 
   [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) 
                                                name:UIKeyboardWillHideNotification object:self.view.window]; 
}

- (void)viewWillDisappear:(BOOL)animated
{
   // unregister for keyboard notifications while not visible.
   [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil]; 
}
31
tt.Kilew

Le code de RPDP déplace avec succès le champ de texte hors du chemin du clavier. Mais lorsque vous faites défiler vers le haut après avoir utilisé et supprimé le clavier, le haut a été défilé vers le haut. Cela est vrai pour le simulateur et le périphérique. Pour lire le contenu en haut de cette vue, il faut recharger la vue.

Son code suivant n'est-il pas censé ramener la vue?

else
{
    // revert back to the normal state.
    rect.Origin.y += kOFFSET_FOR_KEYBOARD;
    rect.size.height -= kOFFSET_FOR_KEYBOARD;
}
29
Steve

Je ne suis pas sûr que le déplacement de la vue soit la bonne approche, je l'ai fait différemment, en redimensionnant UIScrollView Je l'ai expliqué en détail sur un petit article

23
Jose Muanis

Pour rétablir l'état de visualisation d'origine, ajoutez:

-(void)textFieldDidEndEditing:(UITextField *)sender

{
    //move the main view, so that the keyboard does not hide it.
    if  (self.view.frame.Origin.y < 0)
    {
        [self setViewMovedUp:NO];
    }
}
21
Nicolas Marchand

Il y a tellement de solutions, mais j'ai passé quelques heures avant que ça commence à fonctionner. Donc, je mets ce code ici (il suffit de coller dans le projet, aucune modification nécessaire):

@interface RegistrationViewController : UIViewController <UITextFieldDelegate>{
    UITextField* activeField;
    UIScrollView *scrollView;
}
@end

- (void)viewDidLoad
{
    [super viewDidLoad];

    scrollView = [[UIScrollView alloc] initWithFrame:self.view.frame];

    //scrool view must be under main view - swap it
    UIView* natView = self.view;
    [self setView:scrollView];
    [self.view addSubview:natView];

    CGSize scrollViewContentSize = self.view.frame.size;
    [scrollView setContentSize:scrollViewContentSize];

    [self registerForKeyboardNotifications];
}

- (void)viewDidUnload {
    activeField = nil;
    scrollView = nil;
    [self unregisterForKeyboardNotifications];
    [super viewDidUnload];
}

- (void)registerForKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillShown:)
                                                 name:UIKeyboardWillShowNotification object:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillBeHidden:)
                                                 name:UIKeyboardWillHideNotification object:nil];

}

-(void)unregisterForKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:UIKeyboardWillShowNotification
                                                  object:nil];
    // unregister for keyboard notifications while not visible.
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:UIKeyboardWillHideNotification
                                                  object:nil];
}

- (void)keyboardWillShown:(NSNotification*)aNotification
{
    NSDictionary* info = [aNotification userInfo];
    CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    CGRect frame = self.view.frame;
    frame.size.height -= kbSize.height;
    CGPoint fOrigin = activeField.frame.Origin;
    fOrigin.y -= scrollView.contentOffset.y;
    fOrigin.y += activeField.frame.size.height;
    if (!CGRectContainsPoint(frame, fOrigin) ) {
        CGPoint scrollPoint = CGPointMake(0.0, activeField.frame.Origin.y + activeField.frame.size.height - frame.size.height);
        [scrollView setContentOffset:scrollPoint animated:YES];
    }
}

- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
     [scrollView setContentOffset:CGPointZero animated:YES];
}

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
    activeField = textField;
}

- (void)textFieldDidEndEditing:(UITextField *)textField
{
    activeField = nil;
}

-(BOOL) textFieldShouldReturn:(UITextField *)textField
{
    [textField resignFirstResponder];
    return YES;
}

P.S: J'espère que le code aidera quelqu'un à produire l'effet désiré rapidement. (Xcode 4.5)

19
HotJard

@ user271753

Pour que votre vue redevienne comme avant, ajoutez:

-(BOOL)textFieldShouldReturn:(UITextField *)textField{
   [textField resignFirstResponder];
   [self setViewMovedUp:NO];
   return YES;
}
18
user436179

Essayez ce petit truc.

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
    [self animateTextField: textField up: YES];
}

- (void)textFieldDidEndEditing:(UITextField *)textField
{
    [self animateTextField: textField up: NO];
}

- (void) animateTextField: (UITextField*) textField up: (BOOL) up
{
    const int movementDistance = textField.frame.Origin.y / 2; // Tweak as needed
    const float movementDuration = 0.3f; // Tweak as needed

    int movement = (up ? -movementDistance : movementDistance);

    [UIView beginAnimations: @"anim" context: nil];
    [UIView setAnimationBeginsFromCurrentState: YES];
    [UIView setAnimationDuration: movementDuration];
    self.view.frame = CGRectOffset(self.view.frame, 0, movement);
    [UIView commitAnimations];
}
18
Sourabh Sharma

Il n’est pas nécessaire de faire défiler la vue pour pouvoir déplacer le cadre de la vue. Vous pouvez modifier le cadre d'une vue viewcontroller's de sorte que la vue entière monte juste assez pour que le champ de texte du premier répondant soit placé au-dessus du clavier. Quand j'ai rencontré ce problème, j'ai créé une sous-classe de UIViewController qui fait cela. Il observe que le clavier va apparaître une notification et trouve la sous-vue du premier intervenant et (si nécessaire) il anime la vue principale vers le haut, suffisamment pour que le premier intervenant se trouve au-dessus du clavier. Lorsque le clavier se cache, la vue est animée.

Pour utiliser cette sous-classe, faites de votre contrôleur de vue personnalisé une sous-classe de GMKeyboardVC et il hérite de cette fonctionnalité (assurez-vous simplement que si vous implémentez viewWillAppear et viewWillDisappear, ils doivent appeler super). La classe est sur github .

16
progrmr

Conformément à the docs , à partir d’iOS 3.0, la classe UITableViewController redimensionne et repositionne automatiquement sa vue sous forme de tableau lorsqu’il y a une modification en ligne des champs de texte. Je pense qu'il n'est pas suffisant de placer le champ de texte dans une UITableViewCell comme certains l'ont indiqué.

De les docs :

Un contrôleur de vue de tableau prend en charge la modification en ligne des lignes de vue de tableau; si, par exemple, les lignes comportent des champs de texte incorporés en mode édition, spécifiez fait défiler la ligne en cours d'édition au-dessus du clavier virtuel qui est affiché.

12
Dheeraj V.S.

Voici la solution de hack que j'ai proposée pour une mise en page spécifique. Cette solution est similaire à celle de Matt Gallagher dans la mesure où elle fait défiler une section. Je suis encore nouveau dans le développement iPhone et je ne connais pas bien le fonctionnement des mises en page. Ainsi, ce hack.

Mon implémentation devait prendre en charge le défilement lorsque vous cliquez dans un champ, ainsi que le défilement lorsque l'utilisateur sélectionne ensuite le clavier.

J'ai eu un UIView avec une hauteur de 775. Les contrôles sont répartis essentiellement par groupes de 3 sur un grand espace. Je me suis retrouvé avec la mise en page suivante IB.

UIView -> UIScrollView -> [UI Components]

Voici le hack

Je règle la hauteur UIScrollView sur 500 unités plus grandes que la disposition réelle (1250). J'ai ensuite créé un tableau avec les positions absolues vers lesquelles je dois faire défiler et une fonction simple pour les obtenir en fonction du numéro d'étiquette IB.

static NSInteger stepRange[] = {
    0, 0, 0, 0, 0, 0, 0, 0, 0, 140, 140, 140, 140, 140, 410
};

NSInteger getScrollPos(NSInteger i) {
    if (i < TXT_FIELD_INDEX_MIN || i > TXT_FIELD_INDEX_MAX) {
        return 0 ;
    return stepRange[i] ;
}

Il ne vous reste plus qu'à utiliser les deux lignes de code suivantes dans textFieldDidBeginEditing et textFieldShouldReturn (le dernier si vous créez un champ de navigation suivant)

CGPoint point = CGPointMake(0, getScrollPos(textField.tag)) ;
[self.scrollView setContentOffset:point animated:YES] ;

Un exemple.

- (void) textFieldDidBeginEditing:(UITextField *)textField
{
    CGPoint point = CGPointMake(0, getScrollPos(textField.tag)) ;
    [self.scrollView setContentOffset:point animated:YES] ;
}


- (BOOL)textFieldShouldReturn:(UITextField *)textField {

    NSInteger nextTag = textField.tag + 1;
    UIResponder* nextResponder = [textField.superview viewWithTag:nextTag];

    if (nextResponder) {
        [nextResponder becomeFirstResponder];
        CGPoint point = CGPointMake(0, getScrollPos(nextTag)) ;
        [self.scrollView setContentOffset:point animated:YES] ;
    }
    else{
        [textField resignFirstResponder];
    }

    return YES ;
}

Cette méthode ne "retourne" pas comme les autres méthodes. Ce n'était pas une exigence. Encore une fois, c’était pour un UIView assez «grand», et je n’ai pas eu les jours pour apprendre les moteurs de disposition internes.

12
Steve McFarlin

Ici j'ai trouvé la solution la plus simple pour gérer le clavier.

Vous devez simplement copier-coller ci-dessous le code exemple et modifier votre champ de texte ou toute vue que vous souhaitez déplacer.

Étape 1 

Il suffit de copier-coller ci-dessous deux méthodes dans votre contrôleur

- (void)registerForKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWasShown:)
                                                 name:UIKeyboardDidShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillBeHidden:)
                                                 name:UIKeyboardWillHideNotification object:nil];
}

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

Étape 2 

enregistrer et désenregistrer les notifications du clavier dans viewWillAppear et viewWillDisappear méthodes, respectivement.

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [self registerForKeyboardNotifications];
}

- (void)viewWillDisappear:(BOOL)animated
{
    [self deregisterFromKeyboardNotifications];
    [super viewWillDisappear:animated];
}

Étape 3 

Voici la partie âme, remplacez simplement votre champ de texte et changez hauteur combien vous voulez bouger à la hausse.

- (void)keyboardWasShown:(NSNotification *)notification
{
    NSDictionary* info = [notification userInfo];
    CGSize currentKeyboardSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    //you need replace your textfield instance here
    CGPoint textFieldOrigin = self.tokenForPlaceField.frame.Origin;
    CGFloat textFieldHeight = self.tokenForPlaceField.frame.size.height;

    CGRect visibleRect = self.view.frame;
    visibleRect.size.height -= currentKeyboardSize.height;

    if (!CGRectContainsPoint(visibleRect, textFieldOrigin))
    {
        //you can add yor desired height how much you want move keypad up, by replacing "textFieldHeight" below

        CGPoint scrollPoint = CGPointMake(0.0, textFieldOrigin.y - visibleRect.size.height  + textFieldHeight); //replace textFieldHeight to currentKeyboardSize.height, if you want to move up with more height
        [self.scrollView setContentOffset:scrollPoint animated:YES];
    }
}

- (void)keyboardWillBeHidden:(NSNotification *)notification
{
    [self.scrollView setContentOffset:CGPointZero animated:YES];
}

Référence: Eh bien, Merci d'apprécier ce gars , qui a partagé cette belle solution de code snip, clean.

J'espère que cela serait sûrement utile, quelqu'un là-bas.

11
swiftBoy

Swift 4

Vous pouvez facilement monter et descendre UITextField ou UIView avec UIKeyBoard avec Animationenter image description here

import UIKit

class ViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet var textField: UITextField!
    @IBOutlet var chatView: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChange), name: .UIKeyboardWillChangeFrame, object: nil)
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        textField.resignFirstResponder()
    }

    @objc func keyboardWillChange(notification: NSNotification) {

        let duration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double
        let curve = notification.userInfo![UIKeyboardAnimationCurveUserInfoKey] as! UInt
        let curFrame = (notification.userInfo![UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
        let targetFrame = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
        let deltaY = targetFrame.Origin.y - curFrame.Origin.y
        print("deltaY",deltaY)

        UIView.animateKeyframes(withDuration: duration, delay: 0.0, options: UIViewKeyframeAnimationOptions(rawValue: curve), animations: {
            self.chatView.frame.Origin.y+=deltaY // Here You Can Change UIView To UITextField
        },completion: nil)
    }

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        return true
    }

}
11
ZAFAR007

Je cherchais un bon tutoriel pour les débutants sur le sujet, j'ai trouvé le meilleur tutoriel ici .

Dans l'exemple MIScrollView.h au bas du didacticiel, veillez à laisser un espace à

@property (nonatomic, retain) id backgroundTapDelegate;

comme tu vois.

10
savagenoob

Lorsque UITextField est dans une UITableViewCell, le défilement doit être configuré automatiquement.

Si ce n'est pas le cas, c'est probablement à cause d'un code incorrect/de la configuration de la table.

Par exemple, lorsque j'ai rechargé ma longue table avec un UITextField au bas de la manière suivante, 

-(void) viewWillAppear:(BOOL)animated
{
   [self.tableview reloadData];
}

puis mon champ de texte au bas a été masqué par le clavier qui est apparu lorsque j'ai cliqué à l'intérieur du champ de texte.

Pour résoudre ce problème, je devais le faire -

-(void) viewWillAppear:(BOOL)animated
{
    //add the following line to fix issue
    [super viewWillAppear:animated];
    [self.tableview reloadData];
}
10
lakersgonna3peat

Utilisez cette troisième partie, vous n'avez pas besoin d'écrire même une ligne

https://github.com/hackiftekhar/IQKeyboardManager

téléchargez le projet et faites glisser IQKeyboardManager dans votre projet . Si vous rencontrez un problème, veuillez lire le document README.

Les gars vraiment son enlever la migraine pour gérer le clavier ..

Merci et bonne chance!

9
Arvind Kumar

Note : cette réponse suppose que votre textField est dans un scrollView.

Je préfère traiter cela avec scrollContentInset et scrollContentOffset au lieu de jouer avec les cadres de ma vue.

D'abord écoutons les notifications du clavier 

//call this from viewWillAppear
-(void)addKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillShow:)
                                                 name:UIKeyboardWillShowNotification
                                               object:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillHide:)
                                                 name:UIKeyboardWillHideNotification
                                               object:nil];
}
//call this from viewWillDisappear
-(void)removeKeyboardNotifications{
    [[NSNotificationCenter default
    Center] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}

La prochaine étape consiste à conserver une propriété représentant le premier répondant actuel (UITextfield/UITextVIew contenant le clavier).

Nous utilisons les méthodes déléguées pour définir cette propriété. Si vous utilisez un autre composant, vous aurez besoin de quelque chose de similaire.

Notez que pour textfield, nous l'avons défini dans didBeginEditing et pour textView dans shouldBeginEditing. Ceci est dû au fait que textViewDidBeginEditing est appelé après UIKeyboardWillShowNotification pour une raison quelconque. 

-(BOOL)textViewShouldBeginEditing:(UITextView * )textView{
    self.currentFirstResponder = textView;
    return YES;
}

-(void)textFieldDidBeginEditing:(UITextField *)textField{
    self.currentFirstResponder = textField;
}

Enfin, voici la magie

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


    /*if currentFirstResponder is overlayed by the keyboard, move it so it bottom ends where the keyboard begins*/
    if(self.currentFirstResponder){

        //keyboard Origin in currentFirstResponderFrame
        CGPoint keyboardOrigin = [self.currentFirstResponder convertPoint:kbFrame.Origin fromView:nil];

        float spaceBetweenFirstResponderAndKeyboard = abs(self.currentFirstResponder.frame.size.height-keyboardOrigin.y);

        //only scroll the scrollview if keyboard overlays the first responder
        if(spaceBetweenFirstResponderAndKeyboard>0){
            //if i call setContentOffset:animate:YES it behaves differently, not sure why
            [UIView animateWithDuration:0.25 animations:^{
                [self.scrollView setContentOffset:CGPointMake(0,self.scrollView.contentOffset.y+spaceBetweenFirstResponderAndKeyboard)];
            }];
        }
    }

    //set bottom inset to the keyboard height so you can still scroll the whole content

    UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbFrame.size.height, 0.0);
    _scrollView.contentInset = contentInsets;
    _scrollView.scrollIndicatorInsets = contentInsets;

}

- (void)keyboardWillHide:(NSNotification*)aNotification{
    UIEdgeInsets contentInsets = UIEdgeInsetsZero;
    _scrollView.contentInset = contentInsets;
    _scrollView.scrollIndicatorInsets = contentInsets;
}
8
Juraj Petrik

C'est la solution utilisant Swift.

import UIKit

class ExampleViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet var scrollView: UIScrollView!

    @IBOutlet var textField1: UITextField!
    @IBOutlet var textField2: UITextField!
    @IBOutlet var textField3: UITextField!
    @IBOutlet var textField4: UITextField!
    @IBOutlet var textField5: UITextField!

    var activeTextField: UITextField!

    // MARK: - View
    override func viewDidLoad() {
        super.viewDidLoad()
        self.textField1.delegate = self
        self.textField2.delegate = self
        self.textField3.delegate = self
        self.textField4.delegate = self
        self.textField5.delegate = self
    }

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        self.registerForKeyboardNotifications()
    }

    override func viewWillDisappear(animated: Bool) {
        super.viewWillDisappear(animated)
        self.unregisterFromKeyboardNotifications()
    }

    // MARK: - Keyboard

    // Call this method somewhere in your view controller setup code.
    func registerForKeyboardNotifications() {
        let center:  NSNotificationCenter = NSNotificationCenter.defaultCenter()
        center.addObserver(self, selector: "keyboardWasShown:", name: UIKeyboardDidShowNotification, object: nil)
        center.addObserver(self, selector: "keyboardWillBeHidden:", name: UIKeyboardWillHideNotification, object: nil)
    }

    func unregisterFromKeyboardNotifications () {
        let center:  NSNotificationCenter = NSNotificationCenter.defaultCenter()
        center.removeObserver(self, name: UIKeyboardDidShowNotification, object: nil)
        center.removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
    }

    // Called when the UIKeyboardDidShowNotification is sent.
    func keyboardWasShown (notification: NSNotification) {
        let info : NSDictionary = notification.userInfo!
        let kbSize = (info.objectForKey(UIKeyboardFrameBeginUserInfoKey)?.CGRectValue() as CGRect!).size

        let contentInsets: UIEdgeInsets = 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.
        var aRect = self.view.frame
        aRect.size.height -= kbSize.height;
        if (!CGRectContainsPoint(aRect, self.activeTextField.frame.Origin) ) {
            self.scrollView.scrollRectToVisible(self.activeTextField.frame, animated: true)
        }
    }

    // Called when the UIKeyboardWillHideNotification is sent
    func keyboardWillBeHidden (notification: NSNotification) {
        let contentInsets = UIEdgeInsetsZero;
        scrollView.contentInset = contentInsets;
        scrollView.scrollIndicatorInsets = contentInsets;
    }

    // MARK: -  Text Field

    func textFieldDidBeginEditing(textField: UITextField) {
        self.activeTextField = textField
    }

    func textFieldDidEndEditing(textField: UITextField) {
        self.activeTextField = nil
    }

}
8
Homam

Vous devez ajouter scrollview par programme avec une taille d'image spécifique. Vous devez ajouter UIScrollViewDelegate dans un fichier .h. Vous devez activer scrollview pour que vous deviez écrire ensuite dans viewDidLoad ().

scrollview.scrollEnabled=YES;
scrollview.delegate=self;

scrollview.frame = CGRectMake(x,y,width,height);
//---set the content size of the scroll view--- 

[scrollview setContentSize:CGSizeMake(height,width)];

De cette façon, vous pouvez ajouter vos valeurs x, y, largeur et hauteur ... Je pense que cela vous aidera.

7
deepti

Essaye ça:

-(void)textFieldDidBeginEditing:(UITextField *)sender
{
    if ([sender isEqual:self.m_Sp_Contact])
    {
        [self.m_Scroller setContentOffset:CGPointMake(0, 105)animated:YES];          
    }
}
7
user1105624

Swift 2.0:

Ajoutez un UIScrollView et ajoutez textFields au-dessus. Faites des références de storyboard à VC.

@IBOutlet weak var username: UITextField!
@IBOutlet weak var password: UITextField!
@IBOutlet weak var scrollView: UIScrollView!

Ajoutez ces méthodes: UITextFieldDelegate & UIScrollViewDelegate.

//MARK:- TEXTFIELD METHODS
    func textFieldShouldReturn(textField: UITextField) -> Bool {

        if(username.returnKeyType == UIReturnKeyType.Default) {
            password.becomeFirstResponder()
        }
        textField.resignFirstResponder()
        return true
    }
    func textFieldDidBeginEditing(textField: UITextField) {

        dispatch_async(dispatch_get_main_queue()) {

            let scrollPoint:CGPoint = CGPointMake(0,textField.frame.Origin.y/4)
            self.scrollView!.setContentOffset(scrollPoint, animated: true);
        }
    }
    func textFieldShouldEndEditing(textField: UITextField) -> Bool {

        dispatch_async(dispatch_get_main_queue()) {
          UIView.animateWithDuration(0, animations: { self.scrollView!.setContentOffset(CGPointZero,animated: true) })
        }
        return true
    }
    override func touchesBegan(touches: Set<UITouch>,
        withEvent event: UIEvent?) {
            self.view.endEditing(true)
    }
    func scrollViewWillBeginDragging(scrollView: UIScrollView) {
        self.scrollView.scrollEnabled =  true

        dispatch_async(dispatch_get_main_queue()) {
            UIView.animateWithDuration(0, animations: { self.scrollView!.setContentOffset(CGPointZero,animated: true)

            })
        }
    }
7
A.G

Voici une bibliothèque gratuite pour la manipulation du clavier Keyboard-Handling-in-iPhone-Applications . Vous devez écrire une seule ligne de code:

[AutoScroller addAutoScrollTo:scrollView];

C'est génial pour gérer le clavier dans les formulaires

6
user966931

Je pense que la meilleure approche consiste à utiliser la programmation orientée protocole si vous utilisez Swift.

Tout d'abord, vous devez créer un protocole KeyboardCapable, qui donne à tout UIViewController qui le respecte la possibilité d'enregistrer et de désenregistrer les observateurs au clavier:

import Foundation
import UIKit

protocol KeyboardCapable: KeyboardAnimatable {
    func keyboardWillShow(notification: NSNotification)
    func keyboardWillHide(notification: NSNotification)
}

extension KeyboardCapable where Self: UIViewController {
    func registerKeyboardNotifications() {
        NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillShow:"), name:UIKeyboardWillShowNotification, object: nil)
        NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillHide:"), name:UIKeyboardWillHideNotification, object: nil)
    }

    func unregisterKeyboardNotifications() {
        NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
        NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
    }
}

Vous avez remarqué le mot clé KeyboardAnimatable superflu dans le code ci-dessus. C'est juste le nom du prochain protocole que nous devons créer:

import Foundation
import UIKit

protocol KeyboardAnimatable {

}

extension KeyboardAnimatable where Self: UIViewController {
    func performKeyboardShowFullViewAnimation(withKeyboardHeight height: CGFloat, andDuration duration: NSTimeInterval) {
        UIView.animateWithDuration(duration, animations: { () -> Void in
            self.view.frame = CGRectMake(view.frame.Origin.x, -height, view.bounds.width, view.bounds.height)
            }, completion: nil)
    }

    func performKeyboardHideFullViewAnimation(withDuration duration: NSTimeInterval) {
        UIView.animateWithDuration(duration, animations: { () -> Void in
            self.view.frame = CGRectMake(view.frame.Origin.x, 0.0, view.bounds.width, view.bounds.height)
            }, completion: nil)
    }
}

Ce protocole KeyboardAnimatable donne à tout UIViewController le conformant deux méthodes qui animeront la vue entière de haut en bas, respectivement.

Très bien, si KeyboardCapable est conforme à KeyboardAnimatable, tous les UIViewController conformes à KeyboardCapable sont également conformes à KeyboardAnimatable. C'est super.

Voyons une UIViewController conforme KeyboardCapable et réagissant aux événements de clavier:

import Foundation
import UIKit

class TransferConfirmViewController: UIViewController, KeyboardCapable {
    //MARK: - LIFE CYCLE       
    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)

        registerKeyboardNotifications()
    }

    override func viewWillDisappear(animated: Bool) {
        super.viewWillDisappear(animated)

        unregisterKeyboardNotifications()
    }

    //MARK: - NOTIFICATIONS
    //MARK: Keyboard
    func keyboardWillShow(notification: NSNotification) {
        let keyboardHeight = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue().height
        let animationDuration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double
        performKeyboardShowFullViewAnimation(withKeyboardHeight: keyboardHeight, andDuration: animationDuration)
    }

    func keyboardWillHide(notification: NSNotification) {
        let animationDuration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double
        performKeyboardHideFullViewAnimation(withDuration: animationDuration)
    }
}

Maintenant, votre UIViewController répondra aux événements de clavier et s'animera en conséquence.

Remarque: Si vous souhaitez une animation personnalisée plutôt que Push ou extraire la vue, vous devez définir des méthodes personnalisées sur le protocole KeyboardAnimatable ou les exécuter sur des fonctions KeyboardCapable. C'est à vous.

6
Jorge Ramos

Une solution beaucoup plus élégante consiste à utiliser une sous-classe UIView (bien que cela ne soit pas toujours approprié) et à recalculer toutes vos sous-vues lors de la modification de la trame d'un parent (et soyez intelligent: recalculez-les uniquement si la nouvelle taille de la trame a changé, c'est-à-dire CGRectEqualToRect pour comparer la nouvelle image lorsque vous remplacez setFrame et AVANT d'appeler [super setFrame:frame_]). Le seul problème avec ceci est que la UIViewController que vous avez l'intention d'utiliser devrait probablement écouter les événements de clavier (ou vous pouvez le faire dans la UIView elle-même, pour une encapsulation pratique). Mais seulement les UIKeyboardWillShowNotification et UIKeyboardWillHideNotification. C'est juste pour que tout se passe bien (si vous attendez que CG l'appelle, vous aurez un moment de chaos).

Cela a l’avantage de construire une sous-classe UIView qui fait ce qu’il faut faire, de toute façon.

L’implémentation naïve consisterait à écraser drawRect: (ne pas), une meilleure serait simplement d’utiliser layoutSubviews (puis dans UIViewController, ou ce que vous ne pouvez pas appeler [view setNeedsLayout] dans une méthode SINGLE qui est appelée pour show ou cacher).

Cette solution évite de coder en dur un décalage de clavier (ce qui changera s’ils ne sont pas fractionnés, etc.) et signifie également que votre vue pourrait être une sous-vue de beaucoup d’autres vues tout en répondant correctement.

Ne codifiez pas quelque chose comme ça à moins qu'il n'y ait pas d'autre solution. Le système d'exploitation vous donne suffisamment d'informations, si vous avez bien fait les choses, qu'il vous suffit de redessiner intelligemment (en fonction de votre nouvelle taille frame). Ceci est beaucoup plus propre et la façon dont vous devrait faire des choses. (Il peut y avoir une approche encore meilleure, cependant.)

À votre santé.

5
Matt Weaver

C'est très simple, il suffit de mettre le code suivant dans votre classe et de le personnaliser si vous en avez besoin.

-(void)textFieldDidBeginEditing:(UITextField *)textField {
     //Show Keyboard
     self.view.frame = CGRectMake(self.view.frame.Origin.x,
                              self.view.frame.Origin.y-50,
                              self.view.frame.size.width,
                              self.view.frame.size.height);   
}

-(void)textFieldDidEndEditing:(UITextField *)textField {
     // Hide keyboard
     self.view.frame = CGRectMake(self.view.frame.Origin.x,
                              self.view.frame.Origin.y+50,
                              self.view.frame.size.width,
                              self.view.frame.size.height); 
}
5

Vous pouvez également utiliser des méthodes de délégation textfield. Vérifiez ci-dessous le code. Cela fonctionne pour moi quand textfield est placé sur la vue de défilement.

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
     if(textField == answer)
    {   
         CGPoint cPoint = textField.frame.Origin;
         [scrollView setContentOffset:CGPointMake(0, cPoint.y - 100) animated:YES];
    }
}

Remarque: Vous devez modifier la valeur cPoint.y - 100 en fonction de votre vue.

4
Ganesh Guturi

Voici ma version utilisant autolayout:

L'idée est simplement d'intégrer votre vue contenant des champs de texte/vue de texte dans un UIScrollView, de définir une contrainte du bas vers son supérieur, de créer un point de vente et de la mettre à jour en fonction de la hauteur du clavier à l'aide de notifications . Ceci est basé sur un exemple Apple here et note technique Apple sur UIScrollView utilisant AutoLayout here .

1) Intégrez votre vue V dans un fichier UIScrollView S: Si vous avez déjà défini vos constantes et sous-vues, vous pouvez copier/coller votre vue et vos sous-vues dans la vue du ViewController, puis l’intégrer à l’aide du menu Edit -> embed et enfin supprimer les vues copiées.)

2) Définissez les contraintes suivantes:

  • S to top guide de mise en page: 0
  • S vers le bas: 0
  • S menant à superview: 0
  • S suivi de la vue d'ensemble: 0

  • V haut espace pour superview: 0

  • V bas espace à superview: 0
  • V espace de fuite à la vue d'ensemble: 0
  • V menant espace à superview: 0

  • V égale largeur à S

  • Dernière sous-vue V inférieure à la vue d'ensemble: 20

3) Créez un point de vente à partir de la dernière contrainte sur votre contrôleur de vue

4) Utilisez le code suivant:

@property (weak, nonatomic) IBOutlet NSLayoutConstraint *bottomSpaceToContentView;

// ...

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    // ...

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWasShown:)
                                                 name:UIKeyboardDidShowNotification object:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillBeHidden:)
                                                 name:UIKeyboardWillHideNotification object:nil];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark - Handle keyboard

// Called when the UIKeyboardDidShowNotification is sent.
- (void)keyboardWasShown:(NSNotification*)aNotification
{
    NSDictionary* info = [aNotification userInfo];
    CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    self.bottomSpaceToContentView.constant = kBottomMargin + kbSize.height;
    [self.view layoutIfNeeded];
}

// Called when the UIKeyboardWillHideNotification is sent
- (void)keyboardWillBeHidden:(NSNotification*)aNotification
{
    self.bottomSpaceToContentView.constant = kBottomMargin;
    [self.view layoutIfNeeded];
}

Et tadaaaaa, ça marche!

4
dulgan

Il existe de nombreuses réponses disponibles indiquant l'approche. J'ai adopté la même approche mais la mise en œuvre n'est pas bonne.

Voici la idée de base . J'ai apporté des modifications à la méthode keyboardWasShown.

{
// Obtain keyboard Info
NSDictionary* info = [notification userInfo];
CGRect keyboardRect = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
keyboardRect = [self.view convertRect:keyboardRect fromView:nil];

// Obtain ScrollView Info w.r.t. top View
CGRect scrollViewRect = [self.view convertRect:self.scrollView.frame fromView:nil];

// Depending upon your screen Ui, Scroll View's bottom Edge might be at some offset from screen's bottom
// Calculate the exact offset
int scrollViewBottomOffset = self.view.frame.size.height - (scrollViewRect.Origin.y + scrollViewRect.size.height);
int heightToBeAdjusted = keyboardRect.size.height - scrollViewBottomOffset;


// We may also need to consider the Insets if already present with ScrollView. Let's keep it simple for now
// But we should store these, so that we can restore the Insets when Keyboard is gone
// origInsets = self.scrollView.contentInset;

// Set the new Insets for ScrollView
UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, heightToBeAdjusted, 0.0);
self.scrollView.contentInset = contentInsets;
self.scrollView.scrollIndicatorInsets = contentInsets;

// Visible frame (not overlapped by Keyboard)
CGRect visibleFrame = self.view.frame;
visibleFrame.size.height -= keyboardRect.size.height;

// Get the Rect for Textfield w.r.t self.view
CGRect activeFieldFrame = self.activeField.frame;
activeFieldFrame = [self.view convertRect:activeFieldFrame fromView:self.scrollView];

// Check if the TextField is Visible or not
if (!CGRectContainsRect(visibleFrame, activeFieldFrame) ) {
    // Scroll to make it visible but for scrolling use the activeField frame w.r.t. to scroll View
    [self.scrollView scrollRectToVisible:self.activeField.frame animated:YES];
}

}

Et ajoutez cette méthode pour initialiser l’activeField

- (IBAction)textFieldDidBeginEditing:(UITextField *)sender
{
self.activeField = sender;
}
4
vinksharma

Ceci est un calcul de décalage indépendant de l'appareil. Obtient la hauteur de chevauchement entre le clavier et le champ de texte:

func keyboardShown(notification: NSNotification) {
    let info  = notification.userInfo!
    let value: AnyObject = info[UIKeyboardFrameEndUserInfoKey]!

    let rawFrame = value.CGRectValue
    let keyboardFrame = view.convertRect(rawFrame, fromView: nil)

    let screenHeight = UIScreen.mainScreen().bounds.size.height;
    let Ylimit = screenHeight - keyboardFrame.size.height
    let textboxOriginInSuperview:CGPoint = self.view.convertPoint(CGPointZero, fromCoordinateSpace: lastTextField!)

    self.keyboardHeight = (textboxOriginInSuperview.y+self.lastTextField!.frame.size.height) - Ylimit

    if(self.keyboardHeight>0){
        self.animateViewMoving(true, moveValue: keyboardHeight!)
    }else{
        keyboardHeight=0
    }
}

keyBoardHeight est l'offset.

https://github.com/michaeltyson/TPKeyboardAvoiding téléchargez ce fichier et ajoutez une classe personnalisée comme ceci dans votre vue tableau, il gérera tout ce que vous n'avez pas besoin de faire. éviter le clavier

4
anand madhav

voici une catégorie UITextfield (et d’autres champs similaires) que j’ai créée pour que le champ de texte évite le clavier, vous devriez pouvoir le déposer dans votre contrôleur de vue tel quel et cela devrait fonctionner. Il déplace la totalité de l'écran vers le haut de sorte que le champ de texte actuel soit au-dessus du clavier avec des animations

#import "UIView+avoidKeyboard.h"
#import "AppDelegate.h"

@implementation UIView (avoidKeyboard)

- (void) becomeFirstResponder {

if(self.isFirstResponder)
    return;

[super becomeFirstResponder];

if ([self isKindOfClass:[UISearchBar class]] ||
    [self isKindOfClass:[UITextField class]] ||
    [self isKindOfClass:[UITextView class]])
{
    AppDelegate *appDelegate    = [UIApplication sharedApplication].delegate;

    CGRect screenBounds         = appDelegate.window.frame;

    CGFloat keyboardHeight;
    CGFloat keyboardY;
    CGFloat viewsLowestY;
    CGPoint Origin              = [self.superview convertPoint:self.frame.Origin toView:appDelegate.window]; //get this views Origin in terms of the main screens bounds

    if(UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation])){ //the window.frame doesnt take its orientation into account so if its sideways we must use the x value of the Origin instead of the y
        keyboardHeight          = 216;
        keyboardY               = screenBounds.size.height  - keyboardHeight; //find the keyboards y coord relative to how much the main window has moved up
        viewsLowestY            = Origin.y + self.frame.size.height; //find the lowest point of this view
    }
    else {
        keyboardHeight          = 162;
        keyboardY               = screenBounds.size.width  - keyboardHeight;
        viewsLowestY            = Origin.x + self.frame.size.height;
    }

    CGFloat difference          = viewsLowestY - keyboardY + 20; //find if this view overlaps with the keyboard with some padding

    if (difference > 0){ //move screen up if there is an overlap

        [UIView animateWithDuration:0.3 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{

            CGRect frame = appDelegate.window.frame;

            if(UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation])){
                frame.Origin.y -= difference;
            }
            else {
                frame.Origin.x -= difference;
            }
            appDelegate.window.frame = frame;
        }
        completion:nil];
    }
}
}

//look at appDelegate to see when the keyboard is hidden

@end

Dans votre appDéléguer, ajoutez cette fonction

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardHides:) name:UIKeyboardWillHideNotification object:nil]; //add in didFinishLaunchingWithOptions

...

- (void)keyboardHides:(NSNotification *)notification
{
    [UIView animateWithDuration:0.3 animations:^{
        [window setFrame: CGRectMake(0, 0, window.frame.size.width, window.frame.size.height)];
    } completion:nil];
}
4
Fonix

S'il vous plaît suivez ces étapes. 

1) Déclarez la variable suivante dans le fichier .h.

  {      
         CGFloat animatedDistance;
  }

2) Déclarez les constantes suivantes dans le fichier .m.

  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;
  static const CGFloat LANDSCAPE_KEYBOARD_HEIGHT = 162;

3) Utilisez le délégué UITextField pour déplacer le clavier vers le haut ou le bas.

  -(void) textFieldDidBeginEditing:(UITextField *)textField
  { 
         if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
         {
               CGRect textFieldRect = [self.view.window convertRect:textField.bounds fromView:textField];
               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)
               {
                     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) textFieldDidEndEditing:(UITextField *)textField
  {
       if(UI_USER_INTERFACE_IDIOM()==UIUserInterfaceIdiomPhone)
       {
             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];
       }
 }
3
Himanshu Mahajan

J'emballe tout dans une classe. Appelez simplement ces lignes de code lorsque votre contrôleur de vue est chargé:

- (void)viewDidLoad {
    [super viewDidLoad];
    KeyboardInsetScrollView *injectView = [[KeyboardInsetScrollView alloc] init];
    [injectView injectToView:self.view withRootView:self.view];
}

Voici le lien du projet exemple:
https://github.com/caohuuloc/KeyboardInsetScrollView

3
Cao Huu Loc

Je me suis récemment retrouvé dans un scénario similaire lorsque je travaillais sur une application de messagerie. J'ai créé un UIView personnalisé qui colle au haut du clavier et fait presque tout ce dont vous avez besoin automatiquement

MessageComposerView

http://www.thegameengine.org/wp-content/uploads/2013/11/message_composer_quad_1.jpg

L'idée derrière ce projet était de créer quelque chose qui fonctionne de manière similaire à la vue de composition de iMessage, AKA:

  • se colle en haut du clavier et se déplace en bas de l'écran lorsque le clavier est désactivé
  • gère les modifications de texte
  • gère les rotations

Afin de redimensionner/reconfigurer votre UIScrollView, vous souhaiterez utiliser la méthode de délégation facultative suivante:

- (void)messageComposerFrameDidChange:(CGRect)frame withAnimationDuration:(float)duration;

Il sera appelé chaque fois que le cadre est modifié (redimensionné, repositionné, pivoté) et fournira également la durée de l'animation. Vous pouvez utiliser ces informations pour redimensionner le cadre et les éléments de contenu de votre UIScrollView selon vos besoins.

3
alexgophermix

Ajoutez simplement ceci à votre fichier pod -> pod 'IQKeyboardManager'

Ca y est, gère tout le clavier, les vues de défilement et tout!

Vous n'avez pas besoin de coder quoi que ce soit, vous ne pourriez pas trouver une meilleure solution!

Il possède une extension qui gère l’affichage des champs de texte, le décalage d’écran, les flèches suivante et précédente s'il existe plusieurs champs de texte.

Il a également un bouton fait sur commande, qui peut être supprimé.

Lien -> https://github.com/hackiftekhar/IQKeyboardManager

3
Kakshil Shah

J'ai trouvé que c'était la meilleure solution, suivez le code ci-dessous: 

Joignez ce qui suit à votre contrainte Vertical Space - Bottom Layout Guide - TextField

@property (weak, nonatomic) IBOutlet NSLayoutConstraint *textViewBottomConst;

Deuxièmement, ajoutez des observateurs pour les notifications au clavier.

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

Ajoutez ceci à votre viewDidLoad 

[self observeKeyboard]; 

Enfin, les méthodes qui gèrent les changements de clavier.

- (void)keyboardWillShow:(NSNotification *)notification {
//THIS WILL MAKE SURE KEYBOARD DOESNT JUMP WHEN OPENING QUICKTYPE/EMOJI OR OTHER KEYBOARDS.
kbHeight = 0;
height = 0;
self.textViewBottomConst.constant = height;
self.btnViewBottomConst.constant = height;

    NSDictionary *info = [notification userInfo];
    NSValue *kbFrame = [info objectForKey:UIKeyboardFrameEndUserInfoKey];

    NSTimeInterval animationDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    CGRect keyboardFrame = [kbFrame CGRectValue];

    CGRect finalKeyboardFrame = [self.view convertRect:keyboardFrame fromView:self.view.window];

    int kbHeight = finalKeyboardFrame.size.height;

    int height = kbHeight + self.textViewBottomConst.constant;

    self.textViewBottomConst.constant = height;

    [UIView animateWithDuration:animationDuration animations:^{
        [self.view layoutIfNeeded];
    }];
}

- (void)keyboardWillHide:(NSNotification *)notification {
    NSDictionary *info = [notification userInfo];

    NSTimeInterval animationDuration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];

    self.textViewBottomConst.constant = 10;

    [UIView animateWithDuration:animationDuration animations:^{
        [self.view layoutIfNeeded];
    }];
}
3
Manesh

Je sais que c'est trop tard, mais je voulais surtout partager avec les futurs visiteurs ma façon de le faire. Beaucoup de bonnes méthodes ont été partagées mais je n’ai pas aimé la façon dont l’interface utilisateur devient totalement mauvaise. Il existe une méthode simple qui implique deux parties: -

  1. Ajoutez le TextField et tout ce que vous voulez qu'il flotte au-dessus du clavier lors de l'édition, dans une vue afin qu'ils deviennent des enfants de la vue. Et ensuite, il sera facile de conserver le look et de ne pas affecter l'interface utilisateur.
  2. Utilisez l'outil génialCGAffineTransform(TranslationX: x, TranslationY: y)pour déplacer la vue créée au-dessus du clavier. 

Je sais que cela semble très simple, mais c’est vraiment efficace et soigné .  enter image description here

3
Badr

Une solution simple pour étendre UIViewController

https://github.com/damienromito/VisibleFormViewController

enter image description here

3
Damien Romito

Solution simple et avec dernière api d'animation. Si vous modifiez le fichier Origin.y par 215, vous pouvez le personnaliser selon la valeur qui vous convient.

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
    if (self.view.frame.Origin.y >= 0) {

        [UIView animateWithDuration:0.5 animations:^{
           self.view.frame = CGRectMake(self.view.frame.Origin.x, self.view.frame.Origin.y-215, self.view.frame.size.width, self.view.frame.size.height);
       }];
   }
}

- (void)textFieldDidEndEditing:(UITextField *)textField
{
    if (self.view.frame.Origin.y < 0) {
        [UIView animateWithDuration:0.5 animations:^{
           self.view.frame = CGRectMake(self.view.frame.Origin.x, self.view.frame.Origin.y+215, self.view.frame.size.width, self.view.frame.size.height);
        }];

    }
}
2
Vidhur

Je voudrais prolonger la réponse de @sumanthkodi.

Comme certaines personnes l'ont indiqué, son approche ne fonctionne pas dans les nouvelles implémentations, car UIView ne se déplace pas lorsque vous utilisez contraintes .

J'ai édité le code comme suit (et porté à Swift 2.0) et j'espère que cela aidera certaines personnes:


1) Référencez la contrainte verticale de la vue que vous souhaitez déplacer vers le haut:

@IBOutlet var viewConstraint: NSLayoutConstraint!

Assurez-vous de référencer cette variable dans votre scénario avec la contrainte.

2) Ajoutez le délégué et implémentez les écouteurs. C'est la même implémentation que précédemment:

class YourViewController: UIViewController, UITextFieldDelegate {

    ...

    func textFieldDidBeginEditing(textField: UITextField) {
        animateTextField(textField, up: true)
    }

    func textFieldDidEndEditing(textField: UITextField) {
        animateTextField(textField, up: false)
    }

    ...

}

3) Ajoutez votre méthode d’animation animateTextField à la classe YourViewController. Définissez la valeur de contrainte temporaire selon vos besoins.

func animateTextField(textfield: UITextField, up: Bool) {

    let originalConstraint = 50
    let temporaryConstraint = 0
    let movementDuration = 0.3

    let constraint = CGFloat(up ? temporaryConstraint : originalConstraint)

    containerViewConstraint.constant = constraint
    UIView.animateWithDuration(movementDuration) {
        self.view.layoutIfNeeded()
    }

}
2
andreas

Cela fonctionnera parfaitement. La vue de défilement s'ajustera automatiquement par la position du champ de texte.Je suis sûr que vous vous sentirez bien

static const CGFloat KEYBOARD_ANIMATION_DURATION = 0.25;
static const CGFloat MINIMUM_SCROLL_FRACTION = 0.2;
static const CGFloat MAXIMUM_SCROLL_FRACTION = 0.8;
static const CGFloat PORTRAIT_KEYBOARD_HEIGHT = 216;
static const CGFloat LANDSCAPE_KEYBOARD_HEIGHT = 162;
@interface LoginVC ()
{
  CGFloat animatedDistance;
   CGRect viewFrameKey;
}

 //In ViewDidLoad
   viewFrameKey=self.view.frame;



- (void)textFieldDidBeginEditing:(UITextField *)textField
{
CGRect textFieldRect =
[self.view.window convertRect:textField.bounds fromView:textField];
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)textFieldDidEndEditing:(UITextField *)textField
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];
[self.view setFrame:viewFrameKey];
[UIView commitAnimations];
}
2
Mahesh reddy

Je viens de trouver cette classe:

https://github.com/OliverLetterer/SLScrollViewKeyboardSupport

Et jusqu'à présent, cela fonctionne très bien sur iPhone, y compris les animations et le décalage correct.

Pour l'utiliser, ajoutez simplement à viewDidLoad:

self.support = [[SLScrollViewKeyboardSupport alloc] initWithScrollView:self.scrollView];
2
Sebastian Roth

Une solution très légère pourrait utiliser KeyboardAnimator

le projet a reçu l'exemple de mise en oeuvre, la documentation est toujours en cours ...

Utilisation appropriée :: Il a une implémentation spécifique pour UITextField et UITextView.

Limitation :: Il est entièrement sur objective-c, la version Swift sera bientôt disponible.

2
Ratul Sharker

Ce morceau de code calculera le besoin de déplacement en fonction de la hauteur du clavier et de la profondeur du champ de texte. N'oubliez pas d'ajouter un délégué et d'hériter UITextFieldDelegate à votre en-tête.

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [_tbxUsername resignFirstResponder];
    [_tbxPassword resignFirstResponder];
}

- (void)textFieldDidBeginEditing:(UITextField *) textField
{
    [self animateTextField:textField up:YES];
}

- (void)textFieldDidEndEditing:(UITextField *) textField
{
    [self animateTextField:textField up:NO];
}

- (void) animateTextField: (UITextField*) textField up: (BOOL) up
{
    int animatedDistance;
    int moveUpValue = textField.frame.Origin.y+ textField.frame.size.height;
    UIInterfaceOrientation orientation =
    [[UIApplication sharedApplication] statusBarOrientation];
    if (orientation == UIInterfaceOrientationPortrait ||
        orientation == UIInterfaceOrientationPortraitUpsideDown)
    {

        animatedDistance = 236-(460-moveUpValue-5);
    }
    else
    {
        animatedDistance = 182-(320-moveUpValue-5);
    }

    if(animatedDistance>0)
    {
        const int movementDistance = animatedDistance;
        const float movementDuration = 0.3f;
        int movement = (up ? -movementDistance : movementDistance);
        [UIView beginAnimations: nil context: nil];
        [UIView setAnimationBeginsFromCurrentState: YES];
        [UIView setAnimationDuration: movementDuration];
        self.view.frame = CGRectOffset(self.view.frame, 0, movement);
        [UIView commitAnimations];
    }
}

Délégué à ajouter à ViewDidLoad

_tbxUsername.delegate = self;
_tbxPassword.delegate = self;
2
teapeng
  1. Téléchargez TPKeyBoardAvoiding À partir de ce lien: https://github.com/michaeltyson/TPKeyboardAvoiding
  2. Développez le dossier compressé et recherchez le dossier TPKeyboardAvoiding.
  3. Sélectionnez tous les fichiers .h et .m et déposez-les dans votre projet. Assurez-vous que les éléments à copier sont cochés, le cas échéant.
  4. Glissez et déposez un UIScrollView dans StoryBoard et associez-le à TPKeyboardAvoidingScrollView.
  5. Vous pouvez maintenant ajouter des éléments d'interface utilisateur en haut de la vue de défilement. Notez que cette classe détecte les éléments tactiles même après avoir fait glisser le scrollView.

Sur votre ViewController:

@IBOutlet weak var usernameTextfield: UITextField!
@IBOutlet weak var passwordTextfield: UITextField!
@IBOutlet weak var loginScrollView: UIScrollView!


override func viewWillAppear(animated: Bool) {
        loginScrollView.scrollEnabled =  false
    }

Ajouter des délégués TextField.

//MARK:- TEXTFIELD METHODS
func textFieldShouldReturn(textField: UITextField) -> Bool
{
    if (usernameTextfield.resignFirstResponder())
    {
        passwordTextfield.becomeFirstResponder()
    }
    textField.resignFirstResponder();
    loginScrollView!.setContentOffset(CGPoint.zero, animated: true);
    loginScrollView.scrollEnabled =  false
    return true
}
func textFieldDidBeginEditing(textField: UITextField)
{
    loginScrollView.scrollEnabled =  true

    if (textField.tag  == 1 && (device == "iPhone" || device == "iPhone Simulator" || device == "iPod touch"))
    {
        let scrollPoint:CGPoint = CGPointMake(0, passwordTextfield.frame.Origin.y/6.4);
        loginScrollView!.setContentOffset(scrollPoint, animated: true);

    }
    else if (textField.tag  == 2 && (device == "iPhone" || device == "iPhone Simulator" || device == "iPod touch"))
    {
        let scrollPoint:CGPoint = CGPointMake(0, passwordTextfield.frame.Origin.y/6.0);
        loginScrollView!.setContentOffset(scrollPoint, animated: true);
    }
}
func textFieldDidEndEditing(textField: UITextField)
{
    loginScrollView!.setContentOffset(CGPointZero,animated: true);
}
2
A.G

Afficher la vue de défilement en vue  

  - (void)textFieldDidBeginEditing:(UITextField *)textField
    {
     CGPoint point;
    if(textField == txtEmail){
      // -90 is for my you can change as per your postion
      point = CGPointMake(0, textField.frame.Origin.y - 90);
    }
    else if (textField == txtContact){
      point = CGPointMake(0, textField.frame.Origin.y - 90);
    }
      [scrollV setContentOffset:point animated:YES];
    }
2
seggy

Veuillez ajouter ces lignes dans la méthode de délégation de champ de texte pour faire défiler vers le haut dans iPad. 

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
    activeTextfield = textField;

    CGPoint pt;
    CGRect rc = [textField bounds];
    rc = [textField convertRect:rc toView:scrlView];
    pt = rc.Origin;
    pt.x = 0;
    pt.y -= 100;

    [scrlView setContentOffset:pt animated:YES];

    scrlView.contentSize = CGSizeMake(scrlView.frame.size.width, button.frame.Origin.y+button.frame.size.height + 8 + 370);
}
2
jayesh mardiya

Essayez la bibliothèque IQKeyboard.

Cela déplacera automatiquement le champ de texte vers le haut.

2
User511

Ceci peut être simplement réalisé avec les lignes de code ci-dessous en utilisant des contraintes

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

- (void)keyboardWillShow:(NSNotification *)notification {
    [self adjustTextViewByKeyboardState:YES keyboardInfo:[notification userInfo]];
}

- (void)keyboardWillHide:(NSNotification *)notification {
    [self adjustTextViewByKeyboardState:NO keyboardInfo:[notification userInfo]];
}

- (void)viewDidDisappear:(BOOL)animated {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [super viewDidDisappear:animated];
}

- (void)adjustTextViewByKeyboardState:(BOOL)showKeyboard keyboardInfo:(NSDictionary *)info {
    CGRect keyboardFrame = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
    CGFloat height = keyboardFrame.size.height;
    self.constraintToAdjust.constant = height;        UIViewAnimationCurve animationCurve = [info[UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue];
    UIViewAnimationOptions animationOptions = UIViewAnimationOptionBeginFromCurrentState;
    if (animationCurve == UIViewAnimationCurveEaseIn) {
        animationOptions |= UIViewAnimationOptionCurveEaseIn;
    }
    else if (animationCurve == UIViewAnimationCurveEaseInOut) {
        animationOptions |= UIViewAnimationOptionCurveEaseInOut;
    }
    else if (animationCurve == UIViewAnimationCurveEaseOut) {
        animationOptions |= UIViewAnimationOptionCurveEaseOut;
    }
    else if (animationCurve == UIViewAnimationCurveLinear) {
        animationOptions |= UIViewAnimationOptionCurveLinear;
    }
    [UIView animateWithDuration:[[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue] delay:0 options:animationOptions animations:^{
        [self.view layoutIfNeeded];
    }                completion:nil];
}
2
Rajesh
  • Si le champ de texte n'est pas complètement ou partiellement masqué, nous ne devrions rien changer.
  • Nous devrions calculer la zone d'intersection exacte (le cadre du clavier et celui du champ de texte) qui est masquée, puis nous devrions changer le cadre de la vue.

  • Ici, je donne un exemple complet.

    Déclarant 3 varible

#define PADDING 10

@interface PKViewController ()
      @property (nonatomic, assign) CGRect originalViewFrame; //original view's frame
      @property (nonatomic, strong) UITextField *activeTextField; // current text field
      @property (nonatomic, assign) CGRect keyBoardRect; // covered area by keaboard
     @end

Stocker le cadre d'origine

- (void)viewDidLoad {
    [super viewDidLoad];
    _originalViewFrame = self.view.frame;
}

Ajoutez votre contrôleur de vue en tant qu'observateur pour la notification au clavier

- (void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWasShown:)
                                                 name:UIKeyboardDidShowNotification
                                               object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillHide:)
                                                 name:UIKeyboardWillHideNotification
                                               object:nil];
}

Supprimer l'observateur

- (void)viewWillDisappear:(BOOL)animated{
    [super viewWillDisappear:animated];
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

Stocker la zone couverte par le clavier quand il apparaît et le définir sur CGRectZero quand il disparaît 

- (void)keyboardWasShown:(NSNotification *)notification{
    CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
    _keyBoardRect = CGRectMake(0, _originalViewFrame.size.height - keyboardSize.height, keyboardSize.width, keyboardSize.height);
    [self moveTextFieldUP];

}
- (void) keyboardWillHide:(NSNotification *)notification{
    _keyBoardRect = CGRectZero;
    [self setDefaultFrame];
}

Stocker le champ de texte actif 

- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
    _activeTextField = textField;
//When keyboard is already present but the textfield is hidden. Case:When return key of  keyboard makes the next textfield as first responder
    if (!CGRectIsEmpty(_keyBoardRect)) { 
        [self moveTextFieldUP];
    }
    return YES;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
    [textField resignFirstResponder];
    return YES;
}

Maintenant, nous devrions changer le cadre de la vue

- (void)moveTextFieldUP{
    CGRect virtualTextFieldRect = CGRectMake(0, self.view.frame.Origin.y, _activeTextField.frame.size.width, _activeTextField.frame.Origin.y+_activeTextField.frame.size.height);
    if (CGRectIntersectsRect(_keyBoardRect, virtualTextFieldRect)) {
        CGRect intersectRect = CGRectIntersection(_keyBoardRect, virtualTextFieldRect);
        CGFloat newY = _originalViewFrame.Origin.y - intersectRect.size.height;
        CGFloat newHeight = _originalViewFrame.size.height + intersectRect.size.height;
        CGRect newFrame = CGRectMake(0, newY-PADDING, _originalViewFrame.size.width, newHeight+PADDING);
        [UIView animateWithDuration:0.3 animations:^{
            [self.view setFrame:newFrame];
        }];

        NSLog(@"Intersect");
    }
}
- (void)setDefaultFrame {
    [UIView animateWithDuration:0.3 animations:^{
        [self.view setFrame:_originalViewFrame];
    }];
}
2
PKN

Beaucoup de réponses ici, mais cela fonctionne et est beaucoup plus court que la plupart:

- (void)textFieldDidBeginEditing:(UITextField *)sender
{
    UIScrollView *scrollView = (UIScrollView *)self.view; // assuming this method is pasted into the UIScrollView's controller
    const double dontHardcodeTheKeyboardHeight = 162;
    double textY = [sender convertPoint:CGPointMake(0, 0) toView:scrollView].y;
    if (textY - scrollView.contentOffset.y + sender.frame.size.height > self.view.frame.size.height - dontHardcodeTheKeyboardHeight)
        [scrollView setContentOffset:CGPointMake(0.0, textY - 10) animated:YES];
}
2
Nestor

Cela peut être fait facilement et automatiquement si ce champ de texte est dans la cellule d'un tableau (même lorsque la table.scrollable = NO).

  • NOTEque: la position et la taille de la table doivent être raisonnables . par exemple:
    • si la position y de la table est comptée à partir du bas de la vue, le clavier à une hauteur de 300 cm chevauchera toute la table.
    • si la hauteur de la table = 10 et que le champ de texte qu'il contient doit faire l'objet d'un défilement 100 lorsque le clavier apparaît pour qu'il soit visible, ce champ de texte sera hors des limites de la table. 
2
samthui7
-(BOOL) textFieldShouldBeginEditing:(UITextField *)textField {

  [self slideUp];
   return YES;
}

-(BOOL) textFieldShouldEndEditing:(UITextField *)textField {

    [self slideDown];
   return YES;
}

#pragma mark - Slide Up and Down animation

- (void) slideUp {
    [UIView beginAnimations:nil context:nil];
    layoutView.frame = CGRectMake(0.0, -70.0, layoutView.frame.size.width, layoutView.frame.size.height);

    [UIView commitAnimations];
}


- (void) slideDown {
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDelay: 0.01]; 
    layoutView.frame = CGRectMake(0.0, 0.0, layoutView.frame.size.width, layoutView.frame.size.height);
    [UIView commitAnimations];
}

Bien que ce fil ait suffisamment de réponses, je voudrais suggérer une manière beaucoup plus simple mais généralisée, tout comme Apple le prend en tenant compte de la hauteur du pavé numérique, ce qui est très utile lorsque nous utilisons une barre d’outils personnalisée au-dessus du clavier ici a quelques problèmes.

Voici mon approche (façon légèrement modifiée par Apple) - 

// 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);
    self.scrollView.contentInset = contentInsets;
    self.scrollView.scrollIndicatorInsets = contentInsets;
}

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

c'est simple:-

Dans TextFieldDidBeginEditing: -

self.view.frame=CGRectMake(self.view.frame.Origin.x, self.view.frame.Origin.y-150, self.view.frame.size.width, self.view.frame.size.height);

Dans TextFieldShouldEndEditing: -

self.view.frame=CGRectMake(self.view.frame.Origin.x, self.view.frame.Origin.y+150, self.view.frame.size.width, self.view.frame.size.height);
1
dreamBegin

Avec IQKeyboardManager, UITextField et UITextView défilent automatiquement lorsque le clavier apparaît. Lien Git: https://github.com/hackiftekhar/IQKeyboardManager .

pod: pod 'IQKeyboardManager' # iOS8 et versions ultérieures

pod 'IQKeyboardManager', '3.3.7' # iOS7

1
naresh kolindala

Solution simple pour Scrollview avec TextFields est ci-dessous, pas besoin de contraintes ou champ de texte actif, etc. 

 override func viewWillAppear(_ animated: Bool){
        super.viewWillAppear(animated)
        registerForKeyboardNotifications();


    }
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        deregisterFromKeyboardNotifications();
    }
    //MARK:- KEYBOARD DELEGATE METHODS
        func registerForKeyboardNotifications(){
            //Adding notifies on keyboard appearing
            NotificationCenter.default.addObserver(self, selector: #selector(keyboardWasShown(notification:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
            NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillBeHidden(notification:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
        }
        func deregisterFromKeyboardNotifications(){
            //Removing notifies on keyboard appearing
            NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil)
            NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)
        }
        func keyboardWasShown(notification: NSNotification){

            var info = notification.userInfo!
            let keyboardSize = (info[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.size
            var contentInset:UIEdgeInsets = self.scrRegister.contentInset
            contentInset.bottom = (keyboardSize?.height)!
            scrRegister.contentInset = contentInset


        }
        func keyboardWillBeHidden(notification: NSNotification)
        {
            var contentInset:UIEdgeInsets = self.scrRegister.contentInset
            contentInset.bottom = 0
            scrRegister.contentInset = contentInset

        }
1
Jaydeep Vyas

Veuillez suivre ces étapes, cela pourrait être utile . Placez une vue puis placez votre champ de texte sur cette vue et détectez l’événement par délégué lorsque votre clavier arrive, à cet instant, animez la vue vers le haut (vous pouvez attribuer une position pour cette vue également), votre vue irait jusqu’à cette position. Faites la même chose pour animer la vue.

Merci

1
user1240409

Cela a fonctionné pour moi:

func setupKeyboardNotifications() {
    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWasShown:"), name: UIKeyboardDidShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("keyboardWillBeHidden:"), name: UIKeyboardWillHideNotification, object: nil)
}

func keyboardWasShown(aNotification:NSNotification) {
    let info = aNotification.userInfo
    let infoNSValue = info![UIKeyboardFrameBeginUserInfoKey] as NSValue
    let kbSize = infoNSValue.CGRectValue().size
    UIView.beginAnimations(nil, context: nil)
    UIView.setAnimationDuration(0.3)
    var rect : CGRect = self.view.frame
    rect.size.height -= kbSize.height

    self.view.frame = rect
    UIView.commitAnimations()
}

func keyboardWillBeHidden(aNotification:NSNotification) {
    let info = aNotification.userInfo
    let infoNSValue = info![UIKeyboardFrameBeginUserInfoKey] as NSValue
    let kbSize = infoNSValue.CGRectValue().size
    UIView.beginAnimations(nil, context: nil)
    UIView.setAnimationDuration(0.3)
    var rect : CGRect = self.view.frame
    rect.size.height += kbSize.height
    self.view.frame = rect
    UIView.commitAnimations()
}
0
fede1608

Si le champ de texte doit se trouver au bas de l'écran, la solution la plus magique est le remplacement suivant sur votre contrôleur de vue:

override var inputAccessoryView: UIView? {
    return <yourTextField>
}
0
Sergiu Todirascu

Nous pouvons utiliser le code donné pour Swift 4.1

    let keyBoardSize = 80.0

    func keyboardWillShow() {

    if view.frame.Origin.y >= 0 {
    viewMovedUp = true
     }
     else if view.frame.Origin.y < 0 {
    viewMovedUp = false
   }
  }

func keyboardWillHide() {
 if view.frame.Origin.y >= 0 {
    viewMovedUp = true
 }
 else if view.frame.Origin.y < 0 {
    viewMovedUp = false
 }

}

func textFieldDidBeginEditing(_ textField: UITextField) {
   if sender.isEqual(mailTf) {
    //move the main view, so that the keyboard does not hide it.
    if view.frame.Origin.y >= 0 {
        viewMovedUp = true
    }
  }
}

func setViewMovedUp(_ movedUp: Bool) {
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(0.3)
    // if you want to slide up the view
let rect: CGRect = view.frame
if movedUp {

    rect.Origin.y -= keyBoardSize
    rect.size.height += keyBoardSize
}
else {
    // revert back to the normal state.
    rect.Origin.y += keyBoardSize
    rect.size.height -= keyBoardSize
 }
 view.frame = rect
 UIView.commitAnimations()
}

func viewWillAppear(_ animated: Bool)  {
super.viewWillAppear(animated)

NotificationCenter.default.addObserver(self, selector:#selector(self.keyboardWillShow), name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector:#selector(self.keyboardWillHide), name: .UIKeyboardWillHide, object: nil)
}

func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)

NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillHide, object: nil)
}
0
Pankaj Jangid

dans (BOOL) textFieldShouldBeginEditing: (UITextField *) textField

if (textField.frame.Origin.y > self.view.frame.size.height - 216)
    {
        if (screenHeight>500)
            scrollView.contentSize = CGSizeMake(0.0, scrollView.contentSize.height + 100);
        else
            scrollView.contentSize = CGSizeMake(0.0, scrollView.contentSize.height + 216);
        CGPoint scrollPoint = CGPointMake(0.0,(textField.frame.Origin.y - (self.view.frame.size.height - 216 - textField.frame.size.height - 20)));
        [scrollView setContentOffset:scrollPoint animated:YES];
    }
    [scrollView setScrollEnabled:YES];

lors de la démission de KeyBoard, vous devez écrire du code ci-dessous.

scrollView.contentSize = CGSizeMake(0.0, 640);
CGPoint scrollPoint = CGPointMake(0.0,0.0);
[scrollView setContentOffset:scrollPoint animated:YES]; 
0
PVCS

Pour Swift Developer, à l'aide de Swift 3, voici le rapport https://github.com/jamesrochabrun/KeyboardWillShow

import UIKit

class ViewController: UIViewController {

    //1 Create a view that will hold your TEXTFIELD
    let textField: UITextField = {
        let tf = UITextField()
        tf.translatesAutoresizingMaskIntoConstraints = false
        tf.layer.borderColor = UIColor.darkGray.cgColor
        tf.layer.borderWidth = 3.0
        return tf
    }()
    //2 global variable that will hold the bottom constraint on changes
    var textfieldBottomAnchor: NSLayoutConstraint?

    override func viewDidLoad() {
        super.viewDidLoad()
        //3 add the view to your controller
        view.addSubview(textField)
        textField.heightAnchor.constraint(equalToConstant: 80).isActive = true
        textField.widthAnchor.constraint(equalToConstant: view.frame.width).isActive = true
        textField.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
        textfieldBottomAnchor = textField.bottomAnchor.constraint(equalTo: view.bottomAnchor)
        textfieldBottomAnchor?.isActive = true

        setUpKeyBoardObservers()
    }
    //4 Use NSnotificationCenter to monitor the keyboard updates
    func setUpKeyBoardObservers() {
        NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)
    }

    //5 toggle the bottom layout global variable based on the keyboard's height
    func handleKeyboardWillShow(notification: NSNotification) {

        let keyboardFrame = notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? CGRect
        if let keyboardFrame = keyboardFrame {
            textfieldBottomAnchor?.constant = -keyboardFrame.height
        }
        let keyboardDuration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? Double
        if let keyboardDuration = keyboardDuration {
            UIView.animate(withDuration: keyboardDuration, animations: {
                self.view.layoutIfNeeded()
            })
        }
    }

    func handleKeyboardWillHide(notification: NSNotification) {

        textfieldBottomAnchor?.constant = 0
        let keyboardDuration = notification.userInfo?[UIKeyboardAnimationDurationUserInfoKey] as? Double
        if let keyboardDuration = keyboardDuration {
            UIView.animate(withDuration: keyboardDuration, animations: {
                self.view.layoutIfNeeded()
            })
        }
    }
    //6 remove the observers
    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)

        NotificationCenter.default.removeObserver(self)
    }
}
0
James Rochabrun

Dans iOS, déplacer le clavier vers le haut et reprendre pour les champs de texte dans l'application est un peu déroutant et nécessite d'implémenter peu de méthodes pour la même chose . chaque classe où les champs de texte existent.

Je préfère utiliser ce contrôle Github. 

IQKeyboard

Dans lequel Nous n'avons rien à faire. - glissez simplement le contrôle de la chute vers votre projet et construisez - Il fera tout pour votre application.

Merci 

Peut-être que cela sera utile.

0
Esha

J'ai trouvé @DK_ comme la solution que j'ai commencé à utiliser. Cependant, on suppose que scrollView couvre la totalité de la vue. Ce n'était pas le cas pour moi. Je voulais seulement une scrollView au cas où le clavier couvrait le champ de texte inférieur de mon écran de connexion. Ainsi, la taille de mon contenu était la même que celle du défilement, qui était plus petite que la vue principale.

Cela ne tenait pas non plus compte des paysages, et c'est là que j'ai eu des problèmes pour commencer. Après avoir joué avec elle pendant plusieurs jours, voici ma méthode keyboardWasShown:.

- (void)keyboardWasShown:(NSNotification*)aNotification
{
    // A lot of the inspiration for this code came from http://stackoverflow.com/a/4837510/594602
    CGFloat height = 0;
    NSDictionary* info = [aNotification userInfo];

    CGRect kbFrameRect = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
    CGRect kbBoundsRect = [self.view convertRect:kbFrameRect fromView:nil]; // Convert frame from window to view coordinates.

    CGRect scrollRect = scrollView.frame;
    CGRect intersect = CGRectIntersection(kbBoundsRect, scrollRect);

    if (!CGRectIsNull(intersect))
    {
        height = intersect.size.height;
        UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, height, 0.0);
        scrollView.contentInset = contentInsets;
        scrollView.scrollIndicatorInsets = contentInsets;
    }

    // Figure out what the view rectangle is for the scrollView
    CGPoint contentOffset = scrollView.contentOffset;
    CGRect visibleRect = CGRectOffset(scrollRect, contentOffset.x, contentOffset.y);    // I'm not 100% sure if this is needed/right. My scrollView was always at the top in testing.
    visibleRect.size.height -= height;
    CGRect activeRect = activeField.frame;

    if (!CGRectContainsRect(visibleRect, activeRect))
    {
        [self.scrollView scrollRectToVisible:activeField.frame animated:YES];
    }
}

J'ai aussi eu quelques difficultés à travailler avec la mise en page automatique. Si les mises en page ne sont pas correctement effectuées, je ne reçois pas le défilement auquel je m'attendais. Une chose qui a rendu la vie beaucoup plus facile a été de placer tous les éléments qui devaient défiler dans une vue unique, et de le placer comme seul élément de la vue de défilement. J'ai appelé cette vue unique la "vue du contenu".

Je pense que l'essentiel était que la vue du contenu ait une largeur et une hauteur définies. Cela permettait à la vue par défilement de savoir exactement combien de contenu elle devait traiter. Cela va un peu en arrière par rapport aux mises en page habituelles. Normalement, les vues essaient de prendre le plus de place possible. Avec le contenu d'une vue de défilement, vous essayez de limiter au maximum la vue. La vue du contenu vous permet de mettre un terme à cela. J'ai donc donné au mien une hauteur de 248 et utilisé la largeur d'écran standard de 320 comme largeur.

Les dispositions qui ont finalement fonctionné pour moi étaient les suivantes:

  • Faites défiler la vue pour obtenir une vue superbe: En gros, j’ai donné des contraintes en haut, à gauche et à droite.
    • Horizontal Space - View - Scroll View (0)
    • Vertical Space - View - Scroll View (0)
    • Horizontal Space - Scroll View - View (0)
  • Hauteur de la vue de défilement: je règle la vue de défilement avec une hauteur constante. Je ne sais pas si cela était vraiment nécessaire, mais cela a eu les mêmes effets que la vue par défilement.
    • Height - (248) - Scroll View
  • La vue du contenu à la vue de défilement: J'ai donné des constantes à tous les côtés, en haut, à gauche, en bas et à droite.
    • Vertical Space - View - Scroll View (0)
    • Vertical Space - Scroll View - View (0)
    • Horizontal Space - View - Scroll View (0)
    • Horizontal Space - Scroll View - View (0)
  • Les dimensions de la vue du contenu.
    • Height - (248) - View
    • Width - (320) - View
0
Erik Allen

Vous pouvez utiliser ce simple référentiel Git: https://github.com/hackiftekhar/IQKeyboardManager

C'est une bibliothèque qui gère automatiquement tous les déplacements de champs.

Selon leur readme, l’intégration est super facile:

sans que vous ayez besoin d'entrer un code et aucune configuration supplémentaire n'est requise. Pour utiliser IQKeyboardManager, vous vous devez simplement ajouter des fichiers source à votre projet} _

Bien que ce soit un très bon contrôle, il provoque parfois des conflits, comme dans les contrôleurs de vue avec vue à défilement. Cela change parfois la taille du contenu. Néanmoins, vous pouvez y aller et l'essayer selon vos besoins, vous pourriez peut-être faire ce que j'ai manqué.

0
Harminder Singh

voir UICatalogView exemples d'iphone live et chargé

0
Ankit Sachan

j'ai eu un problème avec le retour à la vue principale par défaut lors de la modification du champ de texte ou de la modification de son contenu (par exemple, textfield téléphone et ajout du signe '-', et la vue revient à couvrir les champs de texte) modification constante des contraintes, pas de la taille ni de la position du cadre dans les fonctions de délégation de notification, comme ceci:

P.S. Je ne me sers pas de scrollview mais simplement de déplacer la vue vers le haut, mais cela devrait fonctionner

func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
    if !keyboardIsShown{
        self.infoViewTopConstraint.constant -= keyboardSize.height
        self.infoViewBottomConstraint.constant += keyboardSize.height
        self.view.setNeedsLayout()
        self.view.layoutIfNeeded()
        keyboardIsShown = true
    }
}

func keyboardWillHide(notification: NSNotification) {
if keyboardIsShown {
    self.infoViewTopConstraint.constant += keyboardSize.height
    self.infoViewBottomConstraint.constant -= keyboardSize.height
    self.view.setNeedsLayout()
    self.view.layoutIfNeeded()
    keyboardIsShown = false
}
0
Robert Juz

Cette question a déjà beaucoup de réponses, certains ont dit utiliser la vue par défilement, d'autres ont dit utiliser une troisième bibliothèque.

Mais pour moi, la solution devrait être UITableViewController avec des cellules statiques.

Vous séparez votre interface utilisateur en plusieurs parties et vous les insérez une par une dans les tablesViewCells. Plus besoin de vous soucier du clavier, tableViewController le gérera automatiquement. 

Il peut être un peu difficile de calculer le remplissage, la marge, la hauteur de la cellule, mais si votre calcul est bon, c'est simple.

0
JIE WANG

J'utilise Swift et la mise en page automatique (mais je ne peux pas commenter la réponse Swift précédente); voici comment je le fais sans une vue de défilement:

J'organise mon formulaire dans IB avec des contraintes verticales entre les champs pour les séparer. J'ajoute une contrainte verticale du champ le plus haut à la vue Conteneur et crée un point de vente correspondant (topSpaceForFormConstraint dans le code ci-dessous). Il suffit de mettre à jour cette contrainte, ce que je fais dans un bloc d'animation pour un mouvement doux de Nice. La vérification de la hauteur est facultative bien sûr, dans ce cas, je devais le faire uniquement pour la plus petite taille d'écran.

Ceci peut être appelé en utilisant l’une des méthodes textFieldDidBeginEditing ou keyboardWillShow habituelles. 

func setFormHeight(top: CGFloat)
{
    let height = UIScreen.mainScreen().bounds.size.height

    // restore text input fields for iPhone 4/4s
    if (height < 568) {
        UIView.animateWithDuration(0.2, delay: 0.0, options: nil, animations: {
            self.topSpaceForFormConstraint.constant = top
            self.view.layoutIfNeeded()
            }, completion: nil)
    }

}
0
Anthony Scott

Je n'ai pas vu cette possibilité ici, donc je l'ajoute, car j'ai essayé les méthodes dans les réponses mais quelques heures plus tard, j'ai découvert qu'il y avait beaucoup moyen plus simple dans XCode 5 sous iOS6/7: Utilisez NSLayoutConstraints.

Voir: contrainte autolayout - clavier

Voici mon code:

fichier .m:

// Called when the UIKeyboardWillShowNotification is sent.
- (void)keyboardWillBeShown:(NSNotification*)aNotification
{
    NSLog(@"keyboardWillBeShown:");
    [self.PhoneNumberLabelOutlet setHidden:TRUE];
    CGFloat heightOfLabel = self.PhoneNumberLabelOutlet.frame.size.height;
    for( NSLayoutConstraint* thisConstraint in self.topElementsVerticalDistanceFromTopLayoutConstraint ) {
        thisConstraint.constant -= heightOfLabel;
    }

    NSDictionary* info = [aNotification userInfo];
    CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;

    CGFloat oldConstant = [self.SignInYConstraint constant];
    self.SignInYConstraint.constant = oldConstant + kbSize.height;
    [self.view setNeedsUpdateConstraints];

    NSTimeInterval duration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    [UIView animateWithDuration:duration animations:^{
        [self.view layoutIfNeeded];
    }];

}

fichier .h:

#import <UIKit/UIKit.h>

@interface SignInViewController : UIViewController {

    UITextField* _activeField;
}




- (void)signInCallback:(NSObject*)object;


@property (weak, nonatomic) IBOutlet UILabel *PhoneNumberLabelOutlet;

@property (weak, nonatomic) IBOutlet UIActivityIndicatorView *ActivityIndicatorOutlet;

@property (weak, nonatomic) IBOutlet UITextField *UserIDTextfieldOutlet;

@property (weak, nonatomic) IBOutlet UITextField *PasswordTextfieldOutlet;

@property (weak, nonatomic) IBOutlet UIButton *SignInButton;

@property (weak, nonatomic) IBOutlet NSLayoutConstraint *SignInYConstraint;

@property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray *topElementsVerticalDistanceFromTopLayoutConstraint;

@end
0
xaphod

Swift 5

dans viewDidLoad ou viewDidAppear, la méthode add addKeyboardObservers.

fileprivate func addKeyboardObservers(){
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)

    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
}

fileprivate func removeKeyboardObservers(){
    NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
    NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
}


@objc fileprivate func keyboardWillHide(_ notification: Notification){
    if (window == nil) {return}
    guard let duration = (notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double) else {return}

   scrollView.contentInset.bottom = .zero
}


@objc fileprivate func keyboardWillShow(_ notification: Notification){
    if (window == nil) {return}
    if UIApplication.shared.applicationState != .active { return }

    // keyboard height
    guard let height = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect)?.height else {return}
    // keyboard present animation duration
    guard let duration = (notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double) else {return}

   scrollView.contentInset.bottom = height
}

n'oubliez pas de retirer les observateurs de deinit ou de les faire disparaître

    self.removeKeyboardObservers()

je suis un peu en retard. Vous devez ajouter scrollView sur votre viewController. 

Vous devez être implémenté ci-dessous 2 méthode.

Méthode de délégué TextField.

    - (void)textFieldDidBeginEditing:(UIView *)textField {
    [self scrollViewForTextField:reEnterPINTextField];
}

Et ensuite, appelez le methon ci-dessous dans la méthode déléguée.

 - (void)scrollViewForTextField:(UIView *)textField {
    NSInteger keyboardHeight = KEYBOARD_HEIGHT;

    if ([textField UITextField.class]) {
        keyboardHeight += ((UITextField *)textField).keyboardControl.activeField.inputAccessoryView.frame.size.height;
    } 

    CGRect screenFrame = [UIScreen mainScreen].bounds;
    CGRect aRect = (CGRect){0, 0, screenFrame.size.width, screenFrame.size.height - ([UIApplication sharedApplication].statusBarHidden ? 0 : [UIApplication sharedApplication].statusBarFrame.size.height)};
    aRect.size.height -= keyboardHeight;
    CGPoint relativeOrigin = [UIView getOriginRelativeToScreenBounds:textField];
    CGPoint bottomPointOfTextField = CGPointMake(relativeOrigin.x, relativeOrigin.y + textField.frame.size.height);

    if (!CGRectContainsPoint(aRect, bottomPointOfTextField) ) {
        CGPoint scrollPoint = CGPointMake(0.0, bottomPointOfTextField.y -aRect.size.height);
        [contentSlidingView setContentOffset:scrollPoint animated:YES];
    }
}
0
Emre Gürses

Ajouter mes 5 cent :)

Je préfère toujours utiliser tableView pour inputTextField ou scrollView. En combinaison avec Notifications, vous pouvez facilement gérer un tel comportement. (Remarque: si vous utilisez des cellules statiques dans tableView, un tel comportement sera automatiquement géré pour vous.)

// MARK: - Notifications
fileprivate func registerNotificaitions() {
    NotificationCenter.default.addObserver(self, selector: #selector(AddRemoteControlViewController.keyboardWillAppear(_:)),
                                           name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(AddRemoteControlViewController.keyboardWillDisappear),
                                           name: NSNotification.Name.UIKeyboardWillHide, object: nil)
}

fileprivate func unregisterNotifications() {
    NotificationCenter.default.removeObserver(self)
}

@objc fileprivate func keyboardWillAppear(_ notification: Notification) {
    if let keyboardHeight = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.height {
        view.layoutIfNeeded()
        UIView.animate(withDuration: 0.3, animations: {
            let heightInset = keyboardHeight - self.addDeviceButton.frame.height
            self.tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: heightInset, right: 0)
            self.view.layoutIfNeeded()
        }, completion: nil)
    }
}

@objc fileprivate func keyboardWillDisappear() {
    view.layoutIfNeeded()
    UIView.animate(withDuration: 0.3, animations: {
        self.tableView.contentInset = UIEdgeInsets.zero
        self.view.layoutIfNeeded()
    }, completion: nil)
}
0
gbk