web-dev-qa-db-fra.com

Comment faire défiler un UITableView vers une section qui ne contient pas de lignes?

Dans une application sur laquelle je travaille, j'ai un style simple UITableView qui peut contenir une section contenant zéro ligne. Je veux pouvoir faire défiler cette section à l'aide de scrollToRowAtIndexPath: atScrollPosition: animated: mais j'obtiens une erreur lorsque j'essaie de faire défiler cette section en raison de l'absence de lignes enfants.

L'application de calendrier d'Apple est capable de le faire. Si vous regardez votre calendrier en mode liste et qu'il n'y a aucun événement dans votre calendrier pour aujourd'hui, une section vide est insérée pour aujourd'hui et vous pouvez y accéder en utilisant le bouton Aujourd'hui de la barre d'outils. au bas de l'écran. Autant que je sache, Apple utilise peut-être un UITableView personnalisé ou une API privée ...

La seule solution à laquelle je peux penser est d'insérer un UITableCell vide dans une hauteur de 0 pixel et de faire défiler jusqu'à celui-ci. Mais je crois comprendre que le fait de disposer de cellules de différentes hauteurs est très mauvais pour les performances de défilement. Je vais quand même essayer quand même, peut-être que la performance ne sera pas trop mauvaise.

Mise à jour

Comme il semble n'y avoir aucune solution à ce problème, j'ai déposé un rapport de bug avec Apple. Si cela vous concerne aussi, remplissez un double de rdar: // problem/6263339 ( Lien Radar ouvert) si vous souhaitez que cela soit corrigé plus rapidement.

Mise à jour # 2

J'ai une solution de contournement décente à cette question, jetez un oeil à ma réponse ci-dessous.

31
Mike Akers

UPDATE: On dirait que ce bogue est corrigé dans iOS 3.0. Vous pouvez utiliser la variable NSIndexPath suivante pour accéder à une section contenant 0 ligne:

[NSIndexPath indexPathForRow:NSNotFound inSection:section]

Je laisse ici ma solution de contournement originale à quiconque conserve un projet utilisant le SDK 2.x.


Trouvé une solution de contournement décent:

CGRect sectionRect = [tableView rectForSection:indexOfSectionToScrollTo];
[tableView scrollRectToVisible:sectionRect animated:YES];

Le code ci-dessus fait défiler la table pour que la section désirée soit visible mais pas nécessairement en haut ou en bas de la zone visible. Si vous souhaitez faire défiler la section en haut, procédez comme suit:

CGRect sectionRect = [tableView rectForSection:indexOfSectionToScrollTo];
sectionRect.size.height = tableView.frame.size.height;
[tableView scrollRectToVisible:sectionRect animated:YES];

Modifiez sectionRect comme vous le souhaitez pour faire défiler la section souhaitée vers le bas ou le milieu de la zone visible.

117
Mike Akers

C'est une vieille question, mais Apple n'a toujours rien ajouté qui puisse aider ou résoudre le bogue bloquant lorsque la section n'a pas de lignes.

Pour moi, j'avais vraiment besoin de faire défiler une nouvelle section vers le milieu lors de l'ajout, alors j'utilise maintenant ce code:

if (rowCount > 0) {
    [self.tableView scrollToRowAtIndexPath: [NSIndexPath indexPathForRow: 0 inSection: sectionIndexForNewFolder] 
                          atScrollPosition: UITableViewScrollPositionMiddle
                                  animated: TRUE];
} else { 
    CGRect sectionRect = [self.tableView rectForSection: sectionIndexForNewFolder];
    // Try to get a full-height rect which is centred on the sectionRect
    // This produces a very similar effect to UITableViewScrollPositionMiddle.
    CGFloat extraHeightToAdd = sectionRect.size.height - self.tableView.frame.size.height;
    sectionRect.Origin.y -= extraHeightToAdd * 0.5f;
    sectionRect.size.height += extraHeightToAdd;
    [self.tableView scrollRectToVisible:sectionRect animated:YES];
}

J'espère que vous l'aimerez - il est basé sur le code de Mike Akers, comme vous pouvez le voir, mais effectue le calcul pour le défilement au milieu au lieu du haut. Merci Mike - tu es une star.

4
Simon Tillson

Une approche rapide de la même chose:

if rows > 0 {
    let indexPath = IndexPath(row: 0, section: section)
    self.tableView.setContentOffset(CGPoint.zero, animated: true)
    self.tableView.scrollToRow(at: indexPath, at: .top, animated: true)
}

else {
    let sectionRect : CGRect = tableView.rect(forSection: section)
    tableView.scrollRectToVisible(sectionRect, animated: true)
}
0
Chaitanya Ramji