Comment faire bouger un UITextField lorsque le clavier est présent?

avec le SDK iOS:

j'ai un UIView avec UITextField s qui apportent un clavier. J'en ai besoin pour être en mesure de:

  1. permettre le défilement du contenu du UIScrollView pour voir les autres champs de texte une fois que le clavier est soulevé

  2. " saut "automatique" (par défilement vers le haut) ou raccourcissement

I sais que j'ai besoin d'un UIScrollView . J'ai essayé de changer la classe de mon UIView en UIScrollView mais je suis toujours incapable de faire défiler les boîtes de textes vers le haut ou vers le bas.

ai-je besoin à la fois d'un UIView et d'un UIScrollView ? Peut-on aller dans l'autre?

Que Faut-il mettre en œuvre pour faire défiler automatiquement vers le champ de texte actif?

idéalement, la plus grande partie possible de la configuration des composants se fera en Interface Builder. J'aimerais qu'écrire du code pour quels besoins.

Note: le UIView (ou UIScrollView ) avec lequel je travaille est soulevé par un tabbar ( UITabBar ), qui doit fonctionner comme normal.


Edit: je suis l'ajout de la barre de défilement juste pour quand le clavier est en place. Même si ce n'est pas nécessaire, j'ai l'impression qu'il fournit une meilleure interface parce que l'utilisateur peut alors faire défiler et changer les boîtes de textes, pour exemple.

Je l'ai fait travailler où je change la taille de cadre du 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, ce n'est pas automatiquement "déplacer vers le haut" ou centrer les champs de texte inférieurs dans la zone visible, ce qui est ce que je voudrais vraiment.

1574
demandé sur philfreo 2009-07-14 21:06:07

30 réponses

  1. vous n'aurez besoin d'un ScrollView que si le contenu que vous avez maintenant ne rentre pas dans l'écran de l'iPhone. (Si vous ajoutez le ScrollView comme superview des composants. juste pour faire le TextField défiler vers le haut quand le clavier se lève, alors il n'est pas nécessaire.)

  2. pour afficher le textfields sans être caché par le clavier, la manière standard est de se déplacer de haut en bas de la vue ayant 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];
}
979
répondu RPDP 2018-03-03 18:21:16

j'avais aussi beaucoup de problèmes avec un UIScrollView composé de multiples UITextFields , dont, un ou plusieurs d'entre eux seraient obscurcis par le clavier quand ils sont édités.

Voici certaines choses à considérer si votre UIScrollView ne défile pas correctement.

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

2) Maintenant que vous comprenez que le UIScrollView est vraiment une fenêtre sur votre "contenu", la façon de s'assurer que le clavier n'est pas obscurcir votre UIScrollView's affichage "de la fenêtre" serait pour redimensionner la UIScrollView de sorte que, lorsque le clavier est présent, vous avez le UIScrollView fenêtre de taille juste l'original UIScrollView cadre".taille.hauteur moins la hauteur du clavier. Cela permettra de s'assurer que votre fenêtre est seulement cette petite zone visible.

3) Voici le hic: quand j'ai mis en oeuvre ceci j'ai pensé que je devrais obtenir le CGRect du texte édité et appeler UIScrollView's scrollRecToVisible méthode. J'ai implémenté la méthode UITextFieldDelegate avec l'appel à la méthode scrollRecToVisible . Cela fonctionnait en fait avec un effet secondaire étrange que le défilement serait snap le UITextField en position. Pendant longtemps je ne pouvais pas comprendre ce que c'était. Puis j'ai commenté la méthode des délégués textFieldDidBeginEditing et tout a fonctionné!!(???). Comme il s'est avéré, je crois que le UIScrollView apporte en fait implicitement le actuellement édité"" dans la fenêtre visible implicitement. Ma mise en œuvre de la méthode UITextFieldDelegate et l'appel subséquent au scrollRecToVisible était redondant et a été la cause de l'effet secondaire étrange.

alors voici les étapes pour faire défiler correctement votre UITextField dans un UIScrollView en place 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. S'inscrire pour les notifications clavier à viewDidLoad
  2. se Désinscrire de la notications de clavier à viewDidUnload
  3. assurez-vous que le contentSize est réglé et supérieur à votre UIScrollView à viewDidLoad
  4. Psy le UIScrollView lorsque le clavier est présent dans la
  5. revenir en arrière le UIScrollView lorsque le clavier disparaît.
  6. Utiliser un ivar pour détecter si le clavier est déjà indiqué sur l'écran depuis le les notifications de clavier sont envoyées chaque fois qu'un UITextField est tabbed même si le clavier est déjà présent pour éviter rétrécissement le UIScrollView alors qu'il est déjà rétrécissement 1519570920"

une chose à noter est que le UIKeyboardWillShowNotification se déclenche même lorsque le clavier est déjà sur l'écran lorsque vous appuyez sur un autre UITextField . J'ai pris soin de cela en utilisant un ivar pour éviter de redimensionner le UIScrollView quand le le clavier est déjà sur l'écran. Redimensionner par inadvertance le UIScrollView alors que le clavier est déjà là serait désastreux!

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

437
répondu Shiun 2017-10-31 12:58:42

il est en fait préférable d'utiliser la mise en œuvre D'Apple, comme prévu dans le docs . Toutefois, le code qu'ils fournissent est défectueux. Remplacer la partie qui se trouve dans keyboardWasShown: juste au-dessous des commentaires à ce qui 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 D'Apple sont ces: (1) ils calculent toujours si le point est dans le cadre de la vue, mais c'est un ScrollView , donc il peut déjà avoir défilé et vous devez tenir compte de ce décalage:

origin.y -= scrollView.contentOffset.y

(2) ils déplacent le contentOffset par la hauteur du clavier, mais nous voulons le contraire (nous voulons déplacer le contentOffset par la hauteur qui est visible sur l'écran, pas ce qui ne l'est pas):

activeField.frame.origin.y-(aRect.size.height)
261
répondu DK_ 2018-03-09 18:21:37

Dans textFieldDidBeginEditting et dans textFieldDidEndEditing appeler 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)
    }
238
répondu sumanthkodi 2016-10-04 15:21:45

Juste en utilisant des objets textfield:

1a) en utilisant Interface Builder : sélectionnez Tous les champs = > Edit => Embed In => ScrollView

1b) intégrer manuellement des Champs de texte dans UIScrollView appelé scrollView

2) Définir UITextFieldDelegate

3) régler chaque textField.delegate = self; (ou faire 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
répondu DAS 2012-12-01 14:53:19

pour solution universelle , Voici mon approche pour la mise en œuvre IQKeyboardManager .

enter image description here

etape n ° 1:- j'ai Ajouté mondial des notifications de UITextField , UITextView , et UIKeyboard dans une classe singleton. Je l'appelle IQKeyboardManager .

etape n ° 2:- Si trouvé UIKeyboardWillShowNotification , UITextFieldTextDidBeginEditingNotification ou UITextViewTextDidBeginEditingNotification notifications, j'essaie d'obtenir topMostViewController instance de la hiérarchie UIWindow.rootViewController . Afin de bien découvrir UITextField / UITextView sur elle, topMostViewController.view 'S cadre doit être ajustée.

Step3: - j'ai calculé la distance de déplacement prévue de topMostViewController.view par rapport à la première réponse UITextField / UITextView .

Etape 4:- Je déplacement du topMostViewController.view.frame vers le haut ou le bas selon la distance de déplacement prévue.

Etape 5:- Si trouvé UIKeyboardWillHideNotification , UITextFieldTextDidEndEditingNotification ou UITextViewTextDidEndEditingNotification de notification, j'ai de nouveau essayer d'obtenir topMostViewController , de la UIWindow.rootViewController de la hiérarchie.

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

ETAPE 7: - j'ai restauré topMostViewController.view.frame vers le bas selon la distance perturbée.

Step8:- j'ai instancié singleton IQKeyboardManager instance de classe sur l'application de la charge, de sorte que chaque UITextField / UITextView dans l'app s'ajuste automatiquement en fonction de la distance de déplacement.

C'est tout IQKeyboardManager faire pour vous avec PAS de LIGNE DE CODE vraiment!! il suffit de faire glisser et déposer le fichier source lié au projet. IQKeyboardManager également en charge "1519250920 Dispositif" Orientation , Automatique UIToolbar de Gestion , KeybkeyboardDistanceFromTextField et beaucoup plus que vous le pensez.

106
répondu Mohd Iftekhar Qurashi 2014-12-18 16:24:01

j'ai mis en place une sous-classe universelle UIScrollView , UITableView et même UICollectionView qui s'occupe de déplacer tous les champs de texte à l'intérieur du clavier.

lorsque le clavier est sur le point d'apparaître, la sous-classe trouvera le sous-vue qui est sur le point d'être édité, et ajustera son cadre et son contenu pour s'assurer que la vue est visible, avec une animation pour correspondre à la pop-up du clavier. Lorsque le clavier disparaît, il restaure sa avant la taille.

il devrait fonctionner avec essentiellement n'importe quelle configuration, soit une interface basée sur UITableView , ou une consistant de vues placées manuellement.

Ici, c'est: solution pour le déplacement des champs de texte hors de la voie du clavier

99
répondu Michael Tyson 2014-12-16 07:06:04

Pour Swift Programmeurs:

cela fera tout pour vous, il suffit de mettre ceux-ci dans votre classe de contrôleur de vue et de mettre en œuvre le UITextFieldDelegate à votre contrôleur de vue et de définir le délégué de textField à self

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

mettre en œuvre les méthodes de rappel 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()
}
84
répondu Satnam Sync 2016-02-24 09:07:45

il y a déjà beaucoup de réponses, mais aucune des solutions ci-dessus n'avait toutes les astuces de positionnement nécessaires pour une animation" parfaite", sans bug, compatible à l'envers et sans clignotant. (bug lors de l'animation de frame / bounds et contentOffset ensemble, différentes orientations de l'interface, iPad split keyboard,...)

Permettez-moi de partager ma solution:

(en supposant que vous avez mis en place 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];
}
62
répondu Martin Ullrich 2017-06-24 09:40:19

a dit Shiun "comme il s'est avéré, je crois que L'UIScrollView apporte en fait implicitement L'UITextField actuellement édité dans la fenêtre visualisable implicitement" cela semble être vrai pour iOS 3.1.3, mais pas 3.2, 4.0, ou 4.1. J'ai dû ajouter un scrollRectToVisible explicite pour rendre le champ Uitext visible sur iOS > = 3.2.

60
répondu cbranch 2017-12-17 10:45:04

ce document détaille une solution à ce problème. Regardez le code source sous 'Contenu en mouvement qui se trouve sous le clavier'. C'est assez simple.

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

44
répondu Mihai Damian 2013-05-14 05:58:49

une chose à considérer est de savoir si vous voulez jamais utiliser un UITextField seul. Je n'ai pas rencontré d'applications iPhone bien conçues qui utilisent réellement UITextFields en dehors de UITableViewCells .

ce sera un peu de travail supplémentaire, mais je vous recommande d'implémenter toutes les vues de saisie de données une vue de table. Ajouter un UITextView à votre UITableViewCells .

43
répondu Jonathan Sterling 2013-05-14 05:59:29

solution la plus facile 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];
}
31
répondu Xar E Ahmer 2014-10-25 11:10:22

petit correctif qui fonctionne pour de nombreux champs Uitext

#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]; 
}
30
répondu tt.Kilew 2010-02-11 11:18:14

le code RPDP déplace avec succès le champ de texte hors de la portée du clavier. Mais quand vous faites défiler vers le haut après avoir utilisé et rejeter le clavier, le haut a été scrolled vers le haut de la vue. Cela est vrai pour le Simulateur et l'appareil. Pour lire le contenu en haut de cette vue, il faut recharger la vue.

est-ce que le code suivant n'est pas censé faire redescendre la vue?

else
{
    // revert back to the normal state.
    rect.origin.y += kOFFSET_FOR_KEYBOARD;
    rect.size.height -= kOFFSET_FOR_KEYBOARD;
}
27
répondu Steve 2010-02-05 18:27:10

Je ne suis pas sûr si déplacer la vue vers le haut est la bonne approche, je l'ai fait d'une manière différente, redimensionnant la vue Uiscroll. Je l'ai expliqué en détail sur un petit article

22
répondu Jose Muanis 2012-08-24 10:25:47

pour ramener à l'état d'origine, Ajouter:

-(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];
    }
}
20
répondu Nicolas Marchand 2016-08-03 06:06:56

il y a tellement de solutions, mais j'ai passé quelques heures avant que ça ne marche. Donc, j'ai mis ce code ici (il suffit de coller au projet, n'importe quelles modifications ne sont pas nécessaires):

@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 à faire l'effet désiré rapidement. (Xcode 4.5)

19
répondu HotJard 2012-10-12 09:14:14

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];
    }

codage Heureux :)....

18
répondu Sourabh Sharma 2015-05-28 07:12:24

@user271753

pour revenir à l'original ajouter:

-(BOOL)textFieldShouldReturn:(UITextField *)textField{
   [textField resignFirstResponder];
   [self setViewMovedUp:NO];
   return YES;
}
17
répondu user436179 2016-05-02 12:06:19

il n'est pas nécessaire d'avoir une vue de défilement pour pouvoir déplacer le cadre de la vue. Vous pouvez changer le cadre d'une vue viewcontroller's de sorte que la vue entière se déplace vers le haut juste assez pour mettre le champ de texte du premier répondant au-dessus du clavier. Quand j'ai rencontré ce problème, j'ai créé une sous-classe de UIViewController qui fait cela. Il observe pour le clavier apparaîtra notification et trouve le premier répondant subview et (si nécessaire) il anime la vue principale vers le haut juste assez pour que le premier répondeur est au-dessus du clavier. Quand le clavier se cache, il anime la vue en arrière où elle était.

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

15
répondu progrmr 2013-05-14 06:01:01

selon the docs , à partir de iOS 3.0, la classe UITableViewController redimensionne et repositionne automatiquement sa vue de table lorsqu'il y a édition en ligne des champs de texte. Je pense qu'il n'est pas suffisant de mettre le champ de texte dans un UITableViewCell comme certains l'ont indiqué.

à Partir de les docs :

un contrôleur de vue de table supporte l'édition en ligne des lignes de vue de table; si, par exemple, les lignes ont des champs de texte intégrés dans le mode d'édition, il les parchemins de la ligne en cours d'édition au-dessus du clavier virtuel qui est afficher.

12
répondu Dheeraj V.S. 2012-10-04 02:57:16

Voici la solution de piratage que j'ai trouvé pour une mise en page spécifique. Cette solution est similaire à la solution Matt Gallagher en ce que Est des rouleaux une section en vue. Je suis encore nouveau au développement d'iPhone, et ne suis pas familier avec la façon dont les mises en page fonctionnent. Ainsi, ce hack.

mon implémentation devait prendre en charge le défilement lors d'un clic dans un champ, et aussi le défilement lorsque l'utilisateur sélectionne next sur le clavier.

j'ai eu un uivi avec une hauteur de 775. Les contrôles sont répartis essentiellement dans les groupes de 3 sur un grand espace. J'ai fini avec la mise en page suivante de L'IB.

UIView -> UIScrollView -> [UI Components]

Voici le hack

j'ai réglé la hauteur de L'UIScrollView à 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 basée sur le numéro de balise 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] ;
}

Maintenant, tout ce que vous devez faire est d'utiliser la suivant deux lignes de code dans textFieldDidBeginEditing et textFieldShouldReturn (le dernier si vous créez un prochain champ de navigation)

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 fait pas "défiler en arrière" comme le font les autres méthodes. Ce n'était pas une obligation. Encore une fois, c'était pour un uivi assez "haut", et je n'ai pas eu le temps d'apprendre les moteurs de disposition internes.

11
répondu Steve McFarlin 2010-03-28 22:17:38

ici j'ai trouvé la solution la plus simple pour manipuler le clavier.

vous devez simplement copier-coller ci-dessous le code échantillon et changer votre zone de texte ou n'importe quelle vue que vous voulez déplacer vers le haut.

Étape 1

il suffit de copier-coller ci-dessous deux méthodes dans votre controller

- (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

s'inscrire et se désinscrire Clavier Notifications 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 soul, il suffit de remplacer votre textfield, et de changer hauteur combien vous voulez bouger à l'envers.

- (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, s'il vous plaît apprécier ce gars , qui a partagé ce beau code snip, solution propre.

J'espère que ce sera d'une aide maussade.

11
répondu swiftBoy 2015-08-19 17:45:32

été à la recherche d'un bon tutoriel pour les débutants sur le sujet, a trouvé le meilleur tutoriel ici .

dans l'exemple MIScrollView.h en bas du tutoriel soyez sûr de mettre un espace à

@property (nonatomic, retain) id backgroundTapDelegate;

comme vous voyez.

9
répondu savagenoob 2012-01-02 20:42:17

utilisez ce tiers vous n'avez pas besoin d'écrire même une ligne

https://github.com/hackiftekhar/IQKeyboardManager

télécharger le projet et de le glisser IQKeyboardManager dans votre projet. Si vous trouvez un problème, veuillez lire le document README.

les gars vraiment son supprimer les maux de tête pour gérer le clavier ..

Merci et bonne chance!

9
répondu Arvind Kumar 2015-10-12 09:43:07

quand UITextField est dans un UITableViewCell le défilement doit être configuré automatiquement.

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

Par exemple quand j'ai rechargé ma longue table avec un UITextField en bas comme suit,

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

alors mon champ de texte en bas a été obscurci par le clavier qui est apparu quand j'ai cliqué à l'intérieur du champ de texte.

pour corriger ceci j'ai dû faire ceci -

-(void) viewWillAppear:(BOOL)animated
{
    //add the following line to fix issue
    [super viewWillAppear:animated];
    [self.tableview reloadData];
}
9
répondu lakersgonna3peat 2016-08-03 06:07:49

Swift 4 .

, Vous Pouvez Facilement Déplacer Vers Le Haut Et Vers Le Bas UITextField Ou UIView Avec UIKeyBoard Avec Animation enter 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
    }

}
9
répondu ZAFAR007 2018-04-28 10:37:37

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

je préfère traiter cela en utilisant scrollcontentenset et scrollContentOffset au lieu de toucher aux cadres de ma vue.

écoutons D'abord les notifications au 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 est de conserver une propriété qui représente le premier intervenant actuel (UITextfield/ UITextVIew qui a actuellement le clavier.)

nous utilisons les méthodes delegate 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 le définissons dans didBeginEditing et pour textView dans shouldBeginEditing. C'est parce 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
répondu Juraj Petrik 2014-07-02 20:06:33

C'est la solution qui utilise 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
répondu Homam 2015-01-06 05:08:32