web-dev-qa-db-fra.com

UITextField sauts de texte

J'ai ViewController avec 2 UITextField éléments: nom d'utilisateur et mot de passe. Je mets délégué pour ces champs, qui comprend le code ci-dessous:

func textFieldShouldReturn(textField: UITextField) -> Bool {
    if textField === self.loginField {
        self.loginField.resignFirstResponder()
        self.passwordField.becomeFirstResponder()
        return false
    }

    return true
}

Cette logique devrait faire passer l'utilisateur du champ de texte de connexion au mot de passe lorsqu'il appuie sur le bouton Suivant du clavier. Mais je suis resté avec le pépin: après

self.passwordField.becomeFirstResponder()

le texte dans le champ de connexion passe au coin supérieur gauche et au dos. Et quoi de plus étrange: ce petit problème ne se reproduit que la première fois, alors vous devez recréer ViewController pour observer ce comportement

Voici la vidéo du petit problème http://tinypic.com/player.php?v=6nsemw%3E&s=8#.VgVb3cuqpHx

J'ai fini avec ceci:

func textFieldShouldReturn(textField: UITextField) -> Bool {
    if textField === self.loginField {
        self.loginField.resignFirstResponder()
        // Shitty workaround. Hi, Apple!
        self.loginField.setNeedsLayout()
        self.loginField.layoutIfNeeded()

        self.passwordField.becomeFirstResponder()
        return false
    }

    return true
}
47
user3237732

Sur la base de certaines des idées affichées ici, il s'agit d'une solution facile à mettre en œuvre, qui fonctionne (pour moi) dans tous les cas et ne semble pas avoir d'effets secondaires:

- (void)textFieldDidEndEditing:(UITextField *)textField
{
    // Workaround for the jumping text bug.
    [textField resignFirstResponder];
    [textField layoutIfNeeded];
}

Cette solution fonctionne à la fois si vous passez au champ suivant par programmation à partir de -textFieldShouldReturn: ou si l'utilisateur touche simplement un autre répondeur.

50
Dave Batton

Dans une sous-classe UITextField, vous pouvez effectuer les opérations suivantes:

-(BOOL)resignFirstResponder
{
    BOOL resigned = [super resignFirstResponder];
    [self layoutIfNeeded];
    return resigned;
}

Le truc ici est de s’assurer que vous appelez layoutIfNeeded après que resignFirstResponder a été appelé.

Le faire de cette façon est très pratique car vous n'avez pas besoin d'appeler vous-même resignFirstResponder dans les rappels des délégués, car cela m'a causé des problèmes dans un UIScrollView, mais ce qui précède ne fonctionne pas :)

16
liamnichols

Utilisez ce code pour éviter le saut de texte dans UITextField.

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

      if(textField == self.txtUserName){
        [self.txtEmail becomeFirstResponder];
      }
      else if (textField == self.txtEmail){
        [self.txtPassword becomeFirstResponder];
      }
      else if (textField == self.txtPassword){
        [self.txtConfirmPassword becomeFirstResponder];
      }
      else if (textField == self.txtConfirmPassword){
        [self.txtFirstName becomeFirstResponder];
      }
      else{
        [textField resignFirstResponder];
      }

   return YES;
}

- (void)textFieldDidEndEditing:(UITextField *)textField
{
   [textField resignFirstResponder];
   [textField layoutIfNeeded];
}
8
Himanshu Mahajan
func textFieldDidEndEditing(_ textField: UITextField) {

    textField.layoutIfNeeded()
}
5
IT Gypsy

Je suis aussi confronté au même problème. Le code ci-dessous est travaillé pour moi.

func textFieldDidEndEditing(_ textField: UITextField) {

    textField.layoutIfNeeded()
}
5
Ramakrishna

Sur la base de ce que je comprends de this :

Ce problème peut survenir lorsque des modifications de disposition ou des animations gérées dans les rappels au clavier affichent et masquent les notifications (généralement lorsque vous souhaitez que le champ de texte soit déplacé de manière à ce que le clavier ne le masque pas).

Solution: Je faisais face à ce problème alors que je faisais layoutIfNeeded à chaque fois que le clavier indiquait qu'on l'appelait en supposant que son coffre-fort était en sécurité.

1
Santhosh R

Une option plus "générique" consiste à utiliser des notifications directement dans votre UITextField sous-classe:

 - (void)setupJumpingTextWorkaround {
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(forceLayout)
                                                 name:UITextFieldTextDidEndEditingNotification object:self];
}

- (void)forceLayout {
        [self setNeedsLayout];
        [self layoutIfNeeded];
    }

N'oubliez pas de vous désabonner

1
d.lebedev

Je ne donne pas mes délégués des champs de texte. Au lieu de cela, je crée une action IBAction et l'attache à l'événement "Did End On Exit". Le problème survient également avec cette méthode, mais uniquement sous iOS 9. Il semble s'agir d'un bogue du système d'exploitation.

Mon action ressemble à ceci:

@IBAction func textFieldAction(sender: UITextField) {
    if sender === usernameField {
        passwordField.becomeFirstResponder()
    }
}

Avec ce qui précède, le problème se produit, mais lorsque je fais le dessous, le problème disparaît:

@IBAction func textFieldAction(sender: UITextField) {
    if sender === usernameField {
        sender.resignFirstResponder()
        passwordField.becomeFirstResponder()
    }
}

Je ne semble pas avoir besoin d'appeler setNeedsLayout().

0
Daniel T.