254 votes

UITableView et problème de défilement du clavier

Après de nombreux essais et erreurs, j'abandonne et je pose la question. J'ai vu beaucoup de personnes ayant des problèmes similaires mais qui n'arrivent pas à trouver toutes les réponses.

J'ai un UITableView qui est composé de cellules personnalisées. Les cellules sont constituées de 5 champs de texte juxtaposés (comme une grille).

Lorsque j'essaie de faire défiler et de modifier les cellules au bas de l'écran de l UITableView Je n'arrive pas à positionner correctement mes cellules au-dessus du clavier.

J'ai vu de nombreuses réponses parlant de changer la taille de la vue, etc... mais aucune d'entre elles n'a fonctionné correctement jusqu'à présent.

Quelqu'un pourrait-il clarifier la "bonne" façon de procéder à l'aide d'un exemple de code concret ?

Merci d'avance, Jonathan

127voto

Sam Ho Points 425

Si vous utilisez UITableViewController au lieu de UIViewController, il le fera automatiquement.

94voto

user91083 Points 607

La fonction qui effectue le défilement pourrait être beaucoup plus simple :

- (void) textFieldDidBeginEditing:(UITextField *)textField {
    UITableViewCell *cell;

    if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1) {
    // Load resources for iOS 6.1 or earlier
        cell = (UITableViewCell *) textField.superview.superview;

    } else {
        // Load resources for iOS 7 or later
        cell = (UITableViewCell *) textField.superview.superview.superview; 
       // TextField -> UITableVieCellContentView -> (in iOS 7!)ScrollView -> Cell!
    }
    [tView scrollToRowAtIndexPath:[tView indexPathForCell:cell] atScrollPosition:UITableViewScrollPositionTop animated:YES];
}

C'est ça. Pas de calculs du tout.

71voto

ZeLegolas Points 189

Je fais quelque chose de très similaire, c'est générique, pas besoin de calculer quelque chose de spécifique pour votre code. Il suffit de vérifier les remarques sur le code :

Dans MyUIViewController.h

@interface MyUIViewController: UIViewController <UITableViewDelegate, UITableViewDataSource>
{
     UITableView *myTableView;
     UITextField *actifText;
}

@property (nonatomic, retain) IBOutlet UITableView *myTableView;
@property (nonatomic, retain) IBOutlet UITextField *actifText;

- (IBAction)textFieldDidBeginEditing:(UITextField *)textField;
- (IBAction)textFieldDidEndEditing:(UITextField *)textField;

-(void) keyboardWillHide:(NSNotification *)note;
-(void) keyboardWillShow:(NSNotification *)note;

@end

Dans MyUIViewController.m

@implementation MyUIViewController

@synthesize myTableView;
@synthesize actifText;

- (void)viewDidLoad 
{
    // Register notification when the keyboard will be show
    [[NSNotificationCenter defaultCenter] addObserver:self
                                          selector:@selector(keyboardWillShow:)
                                          name:UIKeyboardWillShowNotification
                                          object:nil];

    // Register notification when the keyboard will be hide
    [[NSNotificationCenter defaultCenter] addObserver:self
                                          selector:@selector(keyboardWillHide:)
                                          name:UIKeyboardWillHideNotification
                                          object:nil];
}

// To be link with your TextField event "Editing Did Begin"
//  memoryze the current TextField
- (IBAction)textFieldDidBeginEditing:(UITextField *)textField
{
    self.actifText = textField;
}

// To be link with your TextField event "Editing Did End"
//  release current TextField
- (IBAction)textFieldDidEndEditing:(UITextField *)textField
{
    self.actifText = nil;
}

-(void) keyboardWillShow:(NSNotification *)note
{
    // Get the keyboard size
    CGRect keyboardBounds;
    [[note.userInfo valueForKey:UIKeyboardFrameBeginUserInfoKey] getValue: &keyboardBounds];

    // Detect orientation
    UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
    CGRect frame = self.myTableView.frame;

    // Start animation
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDuration:0.3f];

    // Reduce size of the Table view 
    if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown)
        frame.size.height -= keyboardBounds.size.height;
    else 
        frame.size.height -= keyboardBounds.size.width;

    // Apply new size of table view
    self.myTableView.frame = frame;

    // Scroll the table view to see the TextField just above the keyboard
    if (self.actifText)
      {
        CGRect textFieldRect = [self.myTableView convertRect:self.actifText.bounds fromView:self.actifText];
        [self.myTableView scrollRectToVisible:textFieldRect animated:NO];
      }

    [UIView commitAnimations];
}

-(void) keyboardWillHide:(NSNotification *)note
{
    // Get the keyboard size
    CGRect keyboardBounds;
    [[note.userInfo valueForKey:UIKeyboardFrameBeginUserInfoKey] getValue: &keyboardBounds];

    // Detect orientation
    UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
    CGRect frame = self.myTableView.frame;

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDuration:0.3f];

    // Reduce size of the Table view 
    if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown)
        frame.size.height += keyboardBounds.size.height;
    else 
        frame.size.height += keyboardBounds.size.width;

    // Apply new size of table view
    self.myTableView.frame = frame;

    [UIView commitAnimations];
}

@end

45voto

ph1983 Points 207

J'ai eu le même problème mais j'ai remarqué qu'il n'apparaît que dans une seule vue. J'ai donc commencé à chercher les différences dans les contrôleurs.

J'ai découvert que le comportement de défilement est défini dans le fichier - (void)viewWillAppear:(BOOL)animated de la super instance.

Assurez-vous donc de l'implémenter comme ceci :

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    // your code
}

Et cela n'a pas d'importance si vous utilisez UIViewController ou UITableViewController et l'a vérifié en mettant un UITableView en tant que sous-vue de self.view dans l'application UIViewController . C'était le même comportement. La vue ne permettait pas de défiler si l'appel [super viewWillAppear:animated]; a disparu.

41voto

mickm Points 181

Je ne l'ai peut-être pas remarqué, car je n'ai pas lu tout le message ici, mais ce que j'ai trouvé semble étonnamment simple. Je ne l'ai pas encore testé dans toutes les situations, mais il semble que cela devrait fonctionner parfaitement.

il suffit d'ajuster le contentInset du tableau de la hauteur du clavier, puis de faire défiler la cellule vers le bas :

- (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.myTableView.contentInset = contentInsets;
    self.myTableView.scrollIndicatorInsets = contentInsets;

    [self.myTableView scrollToRowAtIndexPath:self.currentField.indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}

et bien sûr

- (void)keyboardWasHidden:(NSNotification *)aNotification
{
    [UIView animateWithDuration:.3 animations:^(void) 
    {
        self.myTableView.contentInset = UIEdgeInsetsZero;
        self.myTableView.scrollIndicatorInsets = UIEdgeInsetsZero;
    }];
}

est-ce trop simple ? est-ce que j'ai raté quelque chose ? jusqu'à présent, cela fonctionne bien pour moi, mais comme je l'ai dit, je ne l'ai pas encore mis à l'épreuve...

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X