web-dev-qa-db-fra.com

Comment faire défiler automatiquement UIScrollView quand un UITextField devient le premier répondant

J'ai vu des publications autour de ici qui suggèrent que UIScrollViews devrait défiler automatiquement si une sous-vue UITextField devient le premier intervenant; Cependant, je n'arrive pas à comprendre comment le faire fonctionner. 

Ce que j'ai est une UIViewController qui a une UIScrollView et dans la UIScrollView il y a plusieurs champs de texte. 

Je sais comment faire cela manuellement si nécessaire; Cependant, d'après ce que j'ai lu, il semble possible de le faire défiler automatiquement. Aidez-moi, s'il vous plaît.

25
Nosrettap

J'espère que cet exemple vous aideraVous pouvez faire défiler n'importe quel point à l'aide de ce code.

scrollView.contentOffset = CGPointMake(0,0);

Donc, si vous avez un champ de texte, il doit avoir une position x, y visible, afin que vous puissiez utiliser 

CGPoint point = textfield.frame.Origin ;
scrollView.contentOffset = point 

Cela devrait faire l'affaire,

Mais si vous ne savez pas quand appeler ce code, vous devez donc apprendre UITextFieldDelegate methods 

Implémentez cette méthode dans votre code

- (void)textFieldDidBeginEditing:(UITextField *)textField {
// Place Scroll Code here
}

J'espère que vous savez utiliser les méthodes de délégation.

30
Adeel Pervaiz

Je sais que cette question a déjà reçu une réponse, mais je pensais partager la combinaison de codes que j'avais utilisée de @Adeel et @Basil, car cela semble parfaitement fonctionner pour moi sur iOS 9.

-(void)textFieldDidBeginEditing:(UITextField *)textField {

    // Scroll to the text field so that it is
    // not hidden by the keyboard during editing.
    [scroll setContentOffset:CGPointMake(0, (textField.superview.frame.Origin.y + (textField.frame.Origin.y))) animated:YES];
}

-(void)textFieldDidEndEditing:(UITextField *)textField {

    // Remove any content offset from the scroll
    // view otherwise the scroll view will look odd.
    [scroll setContentOffset:CGPointMake(0, 0) animated:YES];
}

J'ai aussi utilisé la méthode animée, cela permet une transition beaucoup plus douce.

10
Supertecnoboff

Vous ne devez rien faire manuellement. C'est le comportement par défaut. Il y a deux possibilités pour lesquelles vous ne voyez pas le comportement

  1. La raison la plus probable est que le clavier couvre votre UITextField. Voir ci-dessous pour la solution
  2. L'autre possibilité est que vous ayez une autre UIScrollView quelque part dans la hiérarchie de la vue entre la UITextField et la UIScrollView que vous voulez faire défiler automatiquement. Ceci est moins probable mais peut toujours causer des problèmes.

Pour le n ° 1, vous souhaitez mettre en œuvre quelque chose de similaire aux recommandations d’Apple pour Déplacement du contenu situé sous le clavier . Notez que le code fourni par Apple ne prend pas en compte la rotation. Pour des améliorations sur leur code, consultez le présent article de blog l’implémentation de la méthode keyboardDidShow qui traduit correctement le cadre du clavier à l’aide de la fenêtre.

6
Michael McGuire
- (void)textFieldDidBeginEditing:(UITextField *)textField {
    CGRect rect = [textField bounds];
    rect = [textField convertRect:rect toView:self.scrollView];
    rect.Origin.x = 0 ;
    rect.Origin.y -= 60 ;
    rect.size.height = 400;

    [self.scrollView scrollRectToVisible:rect animated:YES];
}
4
George

Vous pouvez utiliser cette fonction pour autoScroll de UITextField

sur UITextFieldDelegate

- (void)textFieldDidBeginEditing:(UITextField *)textField {

[self autoScrolTextField:textField onScrollView:self.scrollView];
}




- (void) autoScrolTextField: (UITextField *) textField onScrollView: (UIScrollView *) scrollView { 
 float slidePoint = 0.0f;
float keyBoard_Y_Origin = self.view.bounds.size.height - 216.0f;
float textFieldButtomPoint = textField.superview.frame.Origin.y + (textField.frame.Origin.y + textField.frame.size.height);

if (keyBoard_Y_Origin < textFieldButtomPoint - scrollView.contentOffset.y) {
    slidePoint = textFieldButtomPoint - keyBoard_Y_Origin + 10.0f;
    CGPoint point = CGPointMake(0.0f, slidePoint);
    scrollView.contentOffset = point;
}

MODIFIER:

J'utilise maintenant IQKeyboardManager Merci au développeur de ceci, vous devez l'essayer.

3
Basil Mariano

Voici la mise à jour de Swift 4 vers la réponse de @ Supertecnoboff. Cela a très bien fonctionné pour moi.

func textFieldDidBeginEditing(_ textField: UITextField) {
    scroll.setContentOffset(CGPoint(x: 0, y: (textField.superview?.frame.Origin.y)!), animated: true)
}

func textFieldDidEndEditing(_ textField: UITextField) {
    scroll.setContentOffset(CGPoint(x: 0, y: 0), animated: true)
}

Assurez-vous d'étendre UITextFieldDelegate et de définir le délégué des champs de texte sur self.

2
donmiller

Si vous avez plusieurs champs de texte, dites Textfield1, Textfield2, Textfield3 et vous voulez faire défiler la vue à défilement le long de l'axe des y lorsque textfield2 devient le premier répondant:

if([Textfield2 isFirstResponder])
{
    scrollView.contentOffset = CGPointMake(0,yourY);
} 
1
Deep Batra

Comme Michael McGuire l'a mentionné au point 2 ci-dessus, le comportement par défaut du système se comporte mal lorsque la vue de défilement contient une autre vue de défilement entre le champ de texte et la vue de défilement. J'ai constaté que l'inconduite se produisait également lorsqu'il y avait une vue de défilement simplement suivant dans le champ de texte (les deux étant incorporés dans la vue de défilement qui doit être ajustée pour afficher le champ de texte lorsque celui-ci veut commencer C'est sur iOS 12.1.

Mais ma solution est différente de ce qui précède. Dans ma vue de défilement de niveau supérieur, qui est sous-classée afin que je puisse ajouter des propriétés et remplacer des méthodes, je substitue scrollRectToVisible:animated:. Il appelle simplement son [super scrollRectToVisible:animated:] à moins qu'un jeu de propriétés lui indique d'ajuster la rect transmise, qui est le cadre du champ de texte. Lorsque la propriété est non-nil, il s'agit d'une référence à la UITextField en question et la rect est ajustée pour que la vue de défilement aille plus loin que ce que le système pensait. Je mets donc ceci dans le fichier d’en-tête de la sous-classe UIScrollView:

@property (nullable) UITextField *textFieldToBringIntoView;

(avec @synthesize textFieldToBringIntoView; approprié dans l'implémentation. Ensuite, j'ai ajouté cette méthode de substitution à l'implémentation:

- (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)how
{
    if (textFieldToBringIntoView) {
       // Do whatever mucking with `rect`'s Origin needed to make it visible
       // based on context or its spatial relationship with the other
       // view that the system is getting confused by.

       textFieldToBringIntoView = nil;        // Go back to normal
       }
    [super scrollRectToVisible:rect animated:how];
}

Dans la méthode de délégation pour la UITextField au moment de commencer l'édition, définissez simplement textFieldToBringIntoView sur la textField en question:

- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
    // Ensure it scrolls into view so that keyboard doesn't obscure it
    // The system is about to call |scrollRectIntoView:| for the scrolling
    // superview, but the system doesn't get things right in certain cases.

    UIScrollView *parent = (UIScrollView *)textField.superview;
    // (or figure out the parent UIScrollView some other way)

    // Tell the override to do something special just once
    // based on this text field's position in its parent's scroll view.
    parent.textFieldToBringIntoView = textField;
    // The override function will set this back to nil

    return(YES);
}

Cela semble fonctionner. Et si Apple corrige leur bogue, il semble que cela puisse encore fonctionner (doigts croisés).

0
jsbox