Question Comment puis-je faire évoluer un UITextField lorsque le clavier est présent?


Avec le SDK iOS:

j'ai un UIView avec UITextFields qui amènent un clavier. J'en ai besoin pour pouvoir:

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

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

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

Ai-je besoin d'un UIView et un UIScrollView? Est-ce qu'on va dans l'autre?

Qu'est-ce qui doit être implémenté pour faire défiler automatiquement le champ de texte actif?

Idéalement, une grande partie de l'installation des composants sera effectuée dans Interface Builder. Je voudrais seulement écrire du code pour ce dont il a besoin.

Noter la UIView (ou UIScrollView) avec qui je travaille est élevé par un tabbar (UITabBar), qui doit fonctionner normalement.


Edit: J'ajoute la barre de défilement juste pour quand le clavier se lève. Même si ce n'est pas nécessaire, j'ai l'impression que cela fournit une meilleure interface, car l'utilisateur peut alors faire défiler et modifier des zones de texte, par exemple.

Je l'ai travaillé où je change la taille de l'image 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 «déplace» pas automatiquement ou ne centre pas les champs de texte inférieurs dans la zone visible, ce que je voudrais vraiment.


1556


origine


Réponses:


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

  2. Pour montrer le textfields sans être caché par le clavier, le moyen standard est de monter / descendre 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];
}

970



J'avais aussi beaucoup de problème avec un UIScrollView composition de plusieurs UITextFields, dont un ou plusieurs seraient obscurcis par le clavier lors de leur montage.

Voici quelques points à considérer si votre UIScrollView ne défile pas correctement.

1) Assurez-vous que votre taille de contenu est supérieure à UIScrollView taille du cadre. La façon de comprendre UIScrollViews est-ce le UIScrollView est comme une fenêtre de visualisation sur le contenu défini dans contentSize. Donc, quand pour la UIScrollview Pour faire 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 la propriété contentSize est déjà visible. BTW, valeur par défaut contentSize = CGSizeZero.

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'obscurcit pas votre UIScrollView's regarder "fenêtre" serait de redimensionner le UIScrollView de sorte que lorsque le clavier est présent, vous avez le UIScrollView fenêtre de taille à 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 d'abord mis en œuvre cela, je me suis dit que je devrais obtenir le CGRect du champ de texte édité et appel UIScrollView's Méthode scrollRecToVisible J'ai mis en place le UITextFieldDelegate méthode textFieldDidBeginEditing avec l'appel à la scrollRecToVisible méthode. Cela a effectivement travaillé avec un effet secondaire étrange que le défilement casser la UITextField en position. Pendant longtemps, je n'ai pas compris ce que c'était. Ensuite, j'ai commenté le textFieldDidBeginEditing Déléguez la méthode et tout fonctionne !! (???). Comme il s'est avéré, je crois que le UIScrollView fait implicitement apporte le actuellement édité UITextField dans la fenêtre visible implicitement. Ma mise en œuvre du UITextFieldDelegate méthode et appel ultérieur à la scrollRecToVisible était redondant et était 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. Inscrivez-vous pour les notifications de clavier à viewDidLoad
  2. Désinscrire pour les nofitications de clavier à viewDidUnload
  3. Assurez-vous que contentSize est défini et supérieur à votre UIScrollView à viewDidLoad
  4. Rétrécir la UIScrollView quand le clavier est présent
  5. Revenir en arrière la UIScrollView quand le clavier disparaît.
  6. Utilisez un ivar pour détecter si le clavier est déjà affiché sur l'écran puisque les notifications clavier sont envoyées à chaque fois UITextField est tabulé même si le clavier est déjà présent pour éviter contraction la UIScrollView quand c'est déjà rétréci

Une chose à noter est que le UIKeyboardWillShowNotification se déclenchera 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 lorsque le clavier est déjà sur l'écran. Redimensionner par inadvertance le UIScrollView quand le clavier est déjà là, ça serait désastreux!

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


437



Il est en fait préférable de simplement utiliser la mise en œuvre d'Apple, comme prévu dans le docs. Cependant, le code qu'ils fournissent est défectueux. Remplacer la partie trouvée dans keyboardWasShown: juste en 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 les suivants: (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écalent 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)

260



Dans textFieldDidBeginEditting et en textFieldDidEndEditing appeler la fonction [self animateTextField:textField up:YES] ainsi:

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



Juste en utilisant TextFields:

1a) Utilisation Interface Builder: Sélectionnez tous TextFields => Modifier => Incorporer dans => ScrollView

1b) Incorporer manuellement TextFields dans UIScrollView appelé scrollView

2) Set UITextFieldDelegate

3) Définissez 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



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

enter image description here

Étape 1:- J'ai ajouté des notifications globales de UITextField, UITextView, et UIKeyboard dans une classe singleton. je l'appelle IQKeyboardManager.

Étape 2:- Si trouvé UIKeyboardWillShowNotification, UITextFieldTextDidBeginEditingNotification ou UITextViewTextDidBeginEditingNotification notifications, j'essaie d'obtenir topMostViewController instance de la UIWindow.rootViewController hiérarchie. Afin de découvrir correctement UITextField/UITextView dessus, topMostViewController.viewLe cadre de l'image doit être ajusté.

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

Étape 4:- j'ai déménagé topMostViewController.view.frame haut / bas en fonction de la distance de déplacement prévue.

Étape5: - Si trouvé UIKeyboardWillHideNotification, UITextFieldTextDidEndEditingNotification ou UITextViewTextDidEndEditingNotification notification, j'essaie encore d'obtenir topMostViewController instance de la UIWindow.rootViewController hiérarchie.

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

Step7: - J'ai restauré topMostViewController.view.frame vers le bas selon la distance perturbée.

Step8: - J'ai instancié singleton IQKeyboardManager instance de classe sur la charge de l'application, de sorte que tous les UITextField/UITextView dans l'application va s'ajuster automatiquement en fonction de la distance de déplacement prévue.

C'est tout IQKeyboardManager fais pour toi avec PAS DE LIGNE DE CODE vraiment!! seulement besoin de faire glisser et déposer le fichier source lié au projet. IQKeyboardManager aussi soutenir Orientation de l'appareil, Gestion automatique de UIToolbar, KeybkeyboardDistanceFromTextField et beaucoup plus que tu ne le penses.


106



J'ai mis en place un universel, drop-in UIScrollView, UITableView et même UICollectionView sous-classe qui prend soin de déplacer tous les champs de texte à l'intérieur de celui-ci à l'écart du clavier.

Lorsque le clavier est sur le point d'apparaître, la sous-classe trouvera la sous-vue sur le point d'être modifiée et ajustera son image et son contenu pour s'assurer que la vue est visible, avec une animation correspondant à la fenêtre contextuelle du clavier. Lorsque le clavier disparaît, il restaure sa taille antérieure.

Il devrait fonctionner avec pratiquement n'importe quelle configuration, soit un UITableViewbasée sur une base de données, ou une interface constituée de vues placées manuellement.

Ici est: solution pour déplacer les champs de texte à l'écart du clavier


99