UITableView
défini sur des cellules statiques.
Est-il possible de masquer certaines des cellules par programme?
Vous recherchez cette solution:
StaticDataTableViewController 2.0
https://github.com/xelvenone/StaticDataTableViewController
qui peut afficher/masquer/recharger n'importe quelle cellule statique avec ou sans animation!
[self cell:self.outletToMyStaticCell1 setHidden:hide];
[self cell:self.outletToMyStaticCell2 setHidden:hide];
[self reloadDataAnimated:YES];
Remarque: utilisez toujours uniquement (reloadDataAnimated: YES/NO) (N'appelez pas directement [self.tableView reloadData])
Ceci n'utilise pas la solution de hacky avec le réglage height à 0 et vous permet d'animer le changement et de masquer des sections entières
Pour masquer des cellules statiques dans UITable:
Dans votre classe de délégué de contrôleur UITableView:
Objectif c:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell* cell = [super tableView:tableView cellForRowAtIndexPath:indexPath];
if(cell == self.cellYouWantToHide)
return 0; //set the hidden cell's height to 0
return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}
Rapide:
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
var cell = super.tableView(tableView, cellForRowAtIndexPath: indexPath)
if cell == self.cellYouWantToHide {
return 0
}
return super.tableView(tableView, heightForRowAtIndexPath: indexPath)
}
Cette méthode sera appelée pour chaque cellule de la UITable. Une fois qu'il appelle la cellule que vous souhaitez masquer, nous définissons sa hauteur sur 0. Nous identifions la cellule cible en créant un point de vente pour elle:
La meilleure solution est décrite dans le blog suivant http://ALi-reynolds.com/2013/06/29/hide-cells-in-static-table-view/
Concevez votre vue de table statique comme d'habitude dans le générateur d'interface – complète avec toutes les cellules potentiellement cachées. Mais il y a une chose que vous doit faire pour chaque cellule potentielle que vous voulez cacher - cochez la case Propriété “Clip subviews” de la cellule, sinon le contenu du fichier La cellule ne disparaît pas lorsque vous essayez de la masquer (en la réduisant height - plus tard).
SO - vous avez un commutateur dans une cellule et le commutateur est censé se cacher et montrer des cellules statiques. Accrochez-le à un IBAction et faites-le ce:
[self.tableView beginUpdates]; [self.tableView endUpdates];
Cela vous donne de belles animations pour les cellules qui apparaissent et en train de disparaître. Maintenant, implémentez la méthode déléguée vue de table suivante:
- (float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.section == 1 && indexPath.row == 1) { // This is the cell to hide - change as you need // Show or hide cell if (self.mySwitch.on) { return 44; // Show the cell - adjust the height as you need } else { return 0; // Hide the cell } } return 44; }
Et c'est tout. Basculez le commutateur et la cellule se cache et réapparaît avec un Belle animation en douceur.
Ma solution va dans le même sens que Gareth, bien que je fasse certaines choses différemment.
Voici:
1. Masquer les cellules
Il n'y a aucun moyen de cacher directement les cellules. UITableViewController
est la source de données qui fournit les cellules statiques et il n’existe actuellement aucun moyen de lui indiquer "ne pas fournir la cellule x" . Nous devons donc fournir notre propre source de données, que les délégués à la UITableViewController
afin de: récupérez les cellules statiques.
Le plus simple consiste à sous-classer UITableViewController
et à remplacer toutes les méthodes qui doivent se comporter différemment lors du masquage de cellules.
Dans le cas le plus simple (tableau à section unique, toutes les cellules ont la même hauteur), ceci se présente comme suit:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [super tableView:tableView numberOfRowsInSection:section] - numberOfCellsHidden;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Recalculate indexPath based on hidden cells
indexPath = [self offsetIndexPath:indexPath];
return [super tableView:tableView cellForRowAtIndexPath:indexPath];
}
- (NSIndexPath*)offsetIndexPath:(NSIndexPath*)indexPath
{
int offsetSection = indexPath.section; // Also offset section if you intend to hide whole sections
int numberOfCellsHiddenAbove = ... // Calculate how many cells are hidden above the given indexPath.row
int offsetRow = indexPath.row + numberOfCellsHiddenAbove;
return [NSIndexPath indexPathForRow:offsetRow inSection:offsetSection];
}
Si votre tableau comporte plusieurs sections ou si les cellules ont des hauteurs différentes, vous devez remplacer plusieurs méthodes. Le même principe s'applique ici: vous devez décaler indexPath, section et ligne avant de déléguer à super.
Notez également que le paramètre indexPath pour des méthodes telles que didSelectRowAtIndexPath:
sera différent pour la même cellule, en fonction de l'état (c'est-à-dire du nombre de cellules masquées). Il est donc probablement judicieux de toujours décaler tout paramètre indexPath et de travailler avec ces valeurs.
2. Animer le changement
Comme Gareth l'a déjà indiqué, vous rencontrez des problèmes majeurs si vous animez des modifications à l'aide de la méthode reloadSections:withRowAnimation:
.
J'ai découvert que si vous appelez reloadData:
immédiatement après, l'animation est bien améliorée (il ne reste que quelques problèmes mineurs). La table est affichée correctement après l'animation.
Donc ce que je fais c'est:
- (void)changeState
{
// Change state so cells are hidden/unhidden
...
// Reload all sections
NSIndexSet* reloadSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [self numberOfSectionsInTableView:tableView])];
[tableView reloadSections:reloadSet withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView reloadData];
}
cellOneOutlet.hidden = true
remplacez maintenant la méthode ci-dessous, vérifiez quel statut de cellule est masqué et renvoyez la hauteur 0 pour ces cellules. C’est l’une des nombreuses façons dont vous pouvez masquer n’importe quelle cellule dans tableView statique dans Swift.
override func tableView(tableView: UITableView, heightForRowAtIndexPathindexPath: NSIndexPath) -> CGFloat
{
let tableViewCell = super.tableView(tableView,cellForRowAtIndexPath: indexPath)
if tableViewCell.hidden == true
{
return 0
}
else{
return super.tableView(tableView, heightForRowAtIndexPath: indexPath)
}
}
J'ai proposé une alternative qui masque les sections et ne les supprime pas. J'ai essayé l'approche de @ henning77, mais j'ai continué à rencontrer des problèmes lorsque j'ai changé le nombre de sections de la UITableView statique. Cette méthode a très bien fonctionné pour moi, mais j'essaie principalement de masquer des sections plutôt que des lignes. Je supprime certaines lignes à la volée avec succès, mais c'est beaucoup plus compliqué. J'ai donc essayé de regrouper les éléments dans des sections que je dois afficher ou masquer. Voici un exemple de la façon dont je cache des sections:
D'abord je déclare une propriété NSMutableArray
@property (nonatomic, strong) NSMutableArray *hiddenSections;
Dans viewDidLoad (ou après avoir interrogé vos données), vous pouvez ajouter des sections que vous souhaitez masquer au tableau.
- (void)viewDidLoad
{
hiddenSections = [NSMutableArray new];
if(some piece of data is empty){
// Add index of section that should be hidden
[self.hiddenSections addObject:[NSNumber numberWithInt:1]];
}
... add as many sections to the array as needed
[self.tableView reloadData];
}
Puis implémentez ce qui suit les méthodes de délégué TableView
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
if([self.hiddenSections containsObject:[NSNumber numberWithInt:section]]){
return nil;
}
return [super tableView:tableView titleForHeaderInSection:section];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if([self.hiddenSections containsObject:[NSNumber numberWithInt:indexPath.section]]){
return 0;
}
return [super tableView:tableView heightForRowAtIndexPath:[self offsetIndexPath:indexPath]];
}
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
if([self.hiddenSections containsObject:[NSNumber numberWithInt:indexPath.section]]){
[cell setHidden:YES];
}
}
Définissez ensuite la hauteur de l'en-tête et du pied de page sur 1 pour les sections masquées, car vous ne pouvez pas définir la hauteur sur 0. Cela crée un espace supplémentaire de 2 pixels, mais nous pouvons le compenser en ajustant la hauteur du prochain en-tête visible.
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
CGFloat height = [super tableView:tableView heightForHeaderInSection:section];
if([self.hiddenSections containsObject:[NSNumber numberWithInt:section]]){
height = 1; // Can't be zero
}
else if([self tableView:tableView titleForHeaderInSection:section] == nil){ // Only adjust if title is nil
// Adjust height for previous hidden sections
CGFloat adjust = 0;
for(int i = (section - 1); i >= 0; i--){
if([self.hiddenSections containsObject:[NSNumber numberWithInt:i]]){
adjust = adjust + 2;
}
else {
break;
}
}
if(adjust > 0)
{
if(height == -1){
height = self.tableView.sectionHeaderHeight;
}
height = height - adjust;
if(height < 1){
height = 1;
}
}
}
return height;
}
-(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
if([self.hiddenSections containsObject:[NSNumber numberWithInt:section]]){
return 1;
}
return [super tableView:tableView heightForFooterInSection:section];
}
Ensuite, si vous avez des lignes spécifiques à masquer, vous pouvez ajuster le nombre numberOfRowsInSection et les lignes retournées dans cellForRowAtIndexPath. Dans cet exemple, j'ai une section de trois lignes où trois peuvent être vides et doivent être supprimées.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSInteger rows = [super tableView:tableView numberOfRowsInSection:section];
if(self.organization != nil){
if(section == 5){ // Contact
if([self.organization objectForKey:@"Phone"] == [NSNull null]){
rows--;
}
if([self.organization objectForKey:@"Email"] == [NSNull null]){
rows--;
}
if([self.organization objectForKey:@"City"] == [NSNull null]){
rows--;
}
}
}
return rows;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
return [super tableView:tableView cellForRowAtIndexPath:[self offsetIndexPath:indexPath]];
}
Utilisez offsetIndexPath pour calculer le chemin indexPath des lignes pour lesquelles vous supprimez des lignes de manière conditionnelle. Pas nécessaire si vous ne cachez que des sections
- (NSIndexPath *)offsetIndexPath:(NSIndexPath*)indexPath
{
int row = indexPath.row;
if(self.organization != nil){
if(indexPath.section == 5){
// Adjust row to return based on which rows before are hidden
if(indexPath.row == 0 && [self.organization objectForKey:@"Phone"] == [NSNull null] && [self.organization objectForKey:@"Email"] != [NSNull null]){
row++;
}
else if(indexPath.row == 0 && [self.organization objectForKey:@"Phone"] == [NSNull null] && [self.organization objectForKey:@"Address"] != [NSNull null]){
row = row + 2;
}
else if(indexPath.row == 1 && [self.organization objectForKey:@"Phone"] != [NSNull null] && [self.organization objectForKey:@"Email"] == [NSNull null]){
row++;
}
else if(indexPath.row == 1 && [self.organization objectForKey:@"Phone"] == [NSNull null] && [self.organization objectForKey:@"Email"] != [NSNull null]){
row++;
}
}
}
NSIndexPath *offsetPath = [NSIndexPath indexPathForRow:row inSection:indexPath.section];
return offsetPath;
}
Il y a beaucoup de méthodes à remplacer, mais ce qui me plaît dans cette approche, c'est qu'elle est réutilisable. Configurez le tableau hiddenSections, ajoutez-le et il masquera les sections correctes. Cacher les lignes est un peu plus compliqué, mais possible. Nous ne pouvons pas simplement définir la hauteur des lignes que nous souhaitons masquer sur 0 si nous utilisons un UITableView groupé, car les bordures ne seront pas dessinées correctement.
Il s'avère que vous pouvez masquer et afficher des cellules dans un UITableView statique - et avec une animation. Et ce n'est pas si difficile à accomplir.
Vidéo du projet de démonstration
L'essentiel:
Use tableView:heightForRowAtIndexPath:
pour spécifier les hauteurs de cellule de manière dynamique en fonction de certains états.tableView.beginUpdates();tableView.endUpdates()
.tableView.cellForRowAtIndexPath:
à l'intérieur de tableView:heightForRowAtIndexPath:
. Utilisez indexPaths en cache pour différencier les cellules.Oui, c'est tout à fait possible, bien que je sois actuellement aux prises avec le même problème. J'ai réussi à faire en sorte que les cellules se cachent et tout fonctionne correctement, mais je ne peux actuellement pas animer la chose proprement. Voici ce que j'ai trouvé:
Je cache des lignes en fonction de l'état d'un commutateur ON/OFF dans la première ligne de la première section. Si le commutateur est sur ON, il y a 1 ligne en dessous dans la même section, sinon il y a 2 lignes différentes.
J'ai un sélecteur appelé lorsque le commutateur est basculé et je règle une variable pour indiquer l'état dans lequel je me trouve. J'appelle ensuite:
[[self tableView] reloadData];
Je remplace la fonction tableView: willDisplayCell: forRowAtIndexPath: et si la cellule est supposée être masquée, je procède comme suit:
[cell setHidden:YES];
Cela cache la cellule et son contenu, mais ne supprime pas l'espace qu'elle occupe.
Pour supprimer cet espace, remplacez la fonction tableView: heightForRowAtIndexPath: et renvoyez 0 pour les lignes devant être masquées.
Vous devez également redéfinir tableView: numberOfRowsInSection: et renvoyer le nombre de lignes de cette section. Vous devez faire quelque chose d'étrange ici pour que si votre table est un style groupé, les coins arrondis apparaissent sur les bonnes cellules. Dans mon tableau statique, il y a le jeu complet de cellules pour la section. Il y a donc la première cellule contenant l'option, puis 1 cellule pour les options d'état ON et 2 cellules supplémentaires pour les options d'état OFF, soit un total de 4 cellules. Lorsque l'option est activée, je dois renvoyer 4, cela inclut l'option masquée afin que la dernière option affichée ait une boîte arrondie. Lorsque l'option est désactivée, les deux dernières options ne sont pas affichées, donc je retourne 2. Tout cela semble maladroit. Désolé si ce n'est pas très clair, c'est difficile à décrire. Juste pour illustrer la configuration, voici la construction de la section de tableau dans IB:
Ainsi, lorsque l’option est activée, la table indique deux lignes:
Lorsque l'option est désactivée, le tableau indique quatre lignes:
Cette approche n’est pas correcte pour plusieurs raisons, c’est tout ce que j’ai eu avec mes expériences jusqu’à présent, alors laissez-moi savoir si vous trouvez une meilleure solution. Les problèmes que j'ai observés jusqu'à présent sont:
Il est faux de dire à la table que le nombre de lignes est différent de ce qui est vraisemblablement contenu dans les données sous-jacentes.
Je n'arrive pas à animer le changement. J'ai essayé d'utiliser tableView: reloadSections: withRowAnimation: au lieu de reloadData et les résultats ne semblent pas avoir de sens, j'essaie toujours de faire en sorte que cela fonctionne. Actuellement, ce qui semble se produire est que tableView ne met pas à jour les lignes correctes, donc il en reste une qui doit être affichée et un vide est laissé sous la première ligne. Je pense que cela pourrait être lié au premier point concernant les données sous-jacentes.
J'espère que quelqu'un pourra suggérer d'autres méthodes ou peut-être comment étendre l'animation, mais peut-être que cela vous aidera à démarrer. Mes excuses pour le manque d'hyperliens vers des fonctions, je les ai insérées mais elles ont été rejetées par le filtre anti-spam parce que je suis un utilisateur relativement nouveau.
Selon la réponse de Justas, mais pour Swift 4:
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let cell = super.tableView(tableView, cellForRowAt: indexPath)
if cell == self.cellYouWantToHide {
return 0
}
return super.tableView(tableView, heightForRowAt: indexPath)
}
Les réponses ci-dessus qui masquent/affichent les cellules, modifient rowHeight ou gâchent avec les contraintes de mise en page automatique ne m'ont pas fonctionné en raison de problèmes de mise en page automatique. Le code est devenu intolérable.
Pour une table statique simple, ce qui a fonctionné le mieux pour moi a été de:
Voici un exemple de mon contrôleur de vue de table:
@IBOutlet weak var titleCell: UITableViewCell!
@IBOutlet weak var nagCell: UITableViewCell!
@IBOutlet weak var categoryCell: UITableViewCell!
var cellsToShow: [UITableViewCell] = []
override func viewDidLoad() {
super.viewDidLoad()
determinCellsToShow()
}
func determinCellsToShow() {
if detail!.duration.type != nil {
cellsToShow = [titleCell, nagCell, categoryCell]
}
else {
cellsToShow = [titleCell, categoryCell]
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
return cellsToShow[indexPath.row]
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cellsToShow.count
}
Dans> Swift 2.2, j'ai combiné quelques réponses ici.
Créez un point de départ du storyboard pour le lier à votre staticCell.
@IBOutlet weak var updateStaticCell: UITableViewCell!
override func viewDidLoad() {
...
updateStaticCell.hidden = true
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if indexPath.row == 0 {
return 0
} else {
return super.tableView(tableView, heightForRowAtIndexPath: indexPath)
}
}
Je veux masquer ma première cellule, je règle donc la hauteur sur 0 comme décrit ci-dessus.
J'ai trouvé une solution pour animer les cellules cachées dans un tableau statique.
// Class for wrapping Objective-C block
typedef BOOL (^HidableCellVisibilityFunctor)();
@interface BlockExecutor : NSObject
@property (strong,nonatomic) HidableCellVisibilityFunctor block;
+ (BlockExecutor*)executorWithBlock:(HidableCellVisibilityFunctor)block;
@end
@implementation BlockExecutor
@synthesize block = _block;
+ (BlockExecutor*)executorWithBlock:(HidableCellVisibilityFunctor)block
{
BlockExecutor * executor = [[BlockExecutor alloc] init];
executor.block = block;
return executor;
}
@end
Un seul dictionnaire supplémentaire est nécessaire:
@interface MyTableViewController ()
@property (nonatomic) NSMutableDictionary * hidableCellsDict;
@property (weak, nonatomic) IBOutlet UISwitch * birthdaySwitch;
@end
Et regardez l'implémentation de MyTableViewController. Nous avons besoin de deux méthodes pour convertir indexPath entre les index visibles et invisibles ...
- (NSIndexPath*)recoverIndexPath:(NSIndexPath *)indexPath
{
int rowDelta = 0;
for (NSIndexPath * ip in [[self.hidableCellsDict allKeys] sortedArrayUsingSelector:@selector(compare:)])
{
BlockExecutor * executor = [self.hidableCellsDict objectForKey:ip];
if (ip.section == indexPath.section
&& ip.row <= indexPath.row + rowDelta
&& !executor.block())
{
rowDelta++;
}
}
return [NSIndexPath indexPathForRow:indexPath.row+rowDelta inSection:indexPath.section];
}
- (NSIndexPath*)mapToNewIndexPath:(NSIndexPath *)indexPath
{
int rowDelta = 0;
for (NSIndexPath * ip in [[self.hidableCellsDict allKeys] sortedArrayUsingSelector:@selector(compare:)])
{
BlockExecutor * executor = [self.hidableCellsDict objectForKey:ip];
if (ip.section == indexPath.section
&& ip.row < indexPath.row - rowDelta
&& !executor.block())
{
rowDelta++;
}
}
return [NSIndexPath indexPathForRow:indexPath.row-rowDelta inSection:indexPath.section];
}
Une valeur IBAction sur UISwitch changeante:
- (IBAction)birthdaySwitchChanged:(id)sender
{
NSIndexPath * indexPath = [self mapToNewIndexPath:[NSIndexPath indexPathForRow:1 inSection:1]];
if (self.birthdaySwitch.on)
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
else
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
Quelques méthodes UITableViewDataSource et UITableViewDelegate:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
int numberOfRows = [super tableView:tableView numberOfRowsInSection:section];
for (NSIndexPath * indexPath in [self.hidableCellsDict allKeys])
if (indexPath.section == section)
{
BlockExecutor * executor = [self.hidableCellsDict objectForKey:indexPath];
numberOfRows -= (executor.block()?0:1);
}
return numberOfRows;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
indexPath = [self recoverIndexPath:indexPath];
return [super tableView:tableView cellForRowAtIndexPath:indexPath];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
indexPath = [self recoverIndexPath:indexPath];
return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// initializing dictionary
self.hidableCellsDict = [NSMutableDictionary dictionary];
[self.hidableCellsDict setObject:[BlockExecutor executorWithBlock:^(){return self.birthdaySwitch.on;}] forKey:[NSIndexPath indexPathForRow:1 inSection:1]];
}
- (void)viewDidUnload
{
[self setBirthdaySwitch:nil];
[super viewDidUnload];
}
@end
Pour iOS 11, j'ai constaté qu'une version modifiée de la réponse de Mohamed Saleh fonctionnait mieux, avec quelques améliorations basées sur la documentation d'Apple. Il s'anime bien, évite les hacks laids ou les valeurs codées en dur et utilise les hauteurs de ligne déjà définies dans Interface Builder.
Le concept de base consiste à définir la hauteur des lignes sur 0 pour toutes les lignes masquées. Ensuite, utilisez tableView.performBatchUpdates
pour déclencher une animation qui fonctionne de manière cohérente.
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath == indexPathOfHiddenCell {
if cellIsHidden {
return 0
}
}
// Calling super will use the height set in your storyboard, avoiding hardcoded values
return super.tableView(tableView, heightForRowAt: indexPath)
}
Vous devrez vous assurer que cellIsHidden
et indexPathOfHiddenCell
sont définis de manière appropriée à votre cas d'utilisation. Pour mon code, ce sont des propriétés sur mon contrôleur de vue de table.
Quelle que soit la méthode utilisée pour contrôler la visibilité (probablement une action sur un bouton ou didSelectRow
), basculez l'état cellIsHidden dans un bloc performBatchUpdates
:
tableView.performBatchUpdates({
// Use self to capture for block
self.cellIsHidden = !self.cellIsHidden
}, completion: nil)
Apple recommande performBatchUpdates
sur beginUpdates
/endUpdates
autant que possible.
Réponse dans Swift :
Ajoutez la méthode suivante dans votre TableViewController:
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return indexPathOfCellYouWantToHide == indexPath ? 0 : super.tableView(tableView, heightForRowAtIndexPath: indexPath)
}
si tableView tente de dessiner la cellule que vous souhaitez masquer, elle ne l'affichera pas car sa hauteur sera définie sur 0pt grâce à la méthode ci-dessus, tout le reste ne sera pas modifié.
Veuillez noter que indexPathOfCellYouWantToHide
peut être modifié à tout moment :)
D'accord, après quelques tentatives, j'ai une réponse non commune… .. J'utilise la variable "isHidden" ou "hidden" pour vérifier si cette cellule doit être masquée.
créer un IBOutlet sur votre contrôleur de vue .@IBOutlet weak var myCell: UITableViewCell!
Mettez à jour la myCell
dans votre fonction personnalisée, par exemple, vous pouvez l'ajouter dans viewDidLoad:
override func viewDidLoad() {
super.viewDidLoad()
self.myCell.isHidden = true
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let cell = super.tableView(tableView, cellForRowAt: indexPath)
guard !cell.isHidden else {
return 0
}
return super.tableView(tableView, heightForRowAt: indexPath)
}
Cela réduira votre logique dans la méthode de délégation et vous devrez uniquement vous concentrer sur les besoins de votre entreprise.
Swift 4:
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
var height = super.tableView(tableView, heightForRowAt: indexPath)
if (indexPath.row == HIDDENROW) {
height = 0.0
}
return height
}
Vous pouvez sûrement. Tout d’abord, revenez à votre tableView le nombre de cellules que vous souhaitez afficher, puis appelez super
pour obtenir certaines cellules de votre storyboard et renvoyez-les pour tableView:
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.mode.numberOfCells()
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = super.tableView(tableView, cellForRowAtIndexPath: self.mode.indexPathForIndexPath(indexPath))
return cell
}
Si vos cellules ont une taille différente, renvoyez-le aussi:
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return super.tableView(tableView, heightForRowAtIndexPath: self.mode.indexPathForIndexPath(indexPath))
}
La solution de k06a ( https://github.com/k06a/ABStaticTableViewController ) est préférable car elle masque toute la section, y compris les en-têtes de cellules et les pieds de page, où cette solution ( https://github.com/peterpaulis/StaticDataTableViewController ) cache tout sauf le pied de page.
MODIFIER
Je viens de trouver une solution si vous voulez masquer le pied de page dans StaticDataTableViewController
. Voici ce que vous devez copier dans le fichier StaticTableViewController.m:
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section {
if ([tableView.dataSource tableView:tableView numberOfRowsInSection:section] == 0) {
return nil;
} else {
return [super tableView:tableView titleForFooterInSection:section];
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
CGFloat height = [super tableView:tableView heightForFooterInSection:section];
if (self.originalTable == nil) {
return height;
}
if (!self.hideSectionsWithHiddenRows) {
return height;
}
OriginalSection * os = self.originalTable.sections[section];
if ([os numberOfVissibleRows] == 0) {
//return 0;
return CGFLOAT_MIN;
} else {
return height;
}
//return 0;
return CGFLOAT_MIN;
}
Pour le scénario le plus simple lorsque vous masquez les cellules tout en bas de la vue tableau, vous pouvez ajuster tableView contentInset après avoir masqué la cellule:
- (void)adjustBottomInsetForHiddenSections:(NSInteger)numberOfHiddenSections
{
CGFloat bottomInset = numberOfHiddenSections * 44.0; // or any other 'magic number
self.tableView.contentInset = UIEdgeInsetsMake(self.tableView.contentInset.top, self.tableView.contentInset.left, -bottomInset, self.tableView.contentInset.right);
}
En plus de la solution @Saleh Masum:
Si vous obtenez erreurs de mise en page automatique, vous pouvez simplement supprimer les contraintes du tableViewCell.contentView
Swift 3:
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let tableViewCell = super.tableView(tableView, cellForRowAt: indexPath)
if tableViewCell.isHidden == true
{
tableViewCell.contentView.removeConstraints(tableViewCell.contentView.constraints)
return 0
}
else{
return super.tableView(tableView, heightForRowAt: indexPath)
}
}
Cette solution dépend du flux de votre application. Si vous souhaitez afficher/masquer la cellule dans la même instance de contrôleur de vue, cela peut ne pas être le meilleur choix, car supprime les contraintes.
C'est une nouvelle façon de faire cela en utilisant https://github.com/k06a/ABStaticTableViewController
NSIndexPath *ip = [NSIndexPath indexPathForRow:1 section:1];
[self deleteRowsAtIndexPaths:@[ip] withRowAnimation:UITableViewRowAnimationFade]
J'ai un meilleur moyen de masquer les cellules statiques et même les sections de manière dynamique, sans aucun piratage.
Définir la hauteur des lignes sur 0 peut masquer une ligne, mais cela ne fonctionne pas si vous souhaitez masquer une section entière contenant des espaces même si vous masquez toutes les lignes.
Mon approche est de construire un tableau de section de cellules statiques. Ensuite, le contenu de la vue table sera piloté par le tableau de section.
Voici un exemple de code:
var tableSections = [[UITableViewCell]]()
private func configTableSections() {
// seciton A
tableSections.append([self.cell1InSectionA, self.cell2InSectionA])
// section B
if shouldShowSectionB {
tableSections.append([self.cell1InSectionB, self.cell2InSectionB])
}
// section C
if shouldShowCell1InSectionC {
tableSections.append([self.cell1InSectionC, self.cell2InSectionC, self.cell3InSectionC])
} else {
tableSections.append([self.cell2InSectionC, self.cell3InSectionC])
}
}
func numberOfSections(in tableView: UITableView) -> Int {
return tableSections.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableSections[section].count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
return tableSections[indexPath.section][indexPath.row]
}
De cette façon, vous pouvez rassembler tout votre code de configuration sans avoir à écrire le code désagréable pour calculer le nombre de lignes et de sections. Et bien sûr, plus de 0
hauteur.
Ce code est également très facile à maintenir. Par exemple, si vous souhaitez ajouter/supprimer plus de cellules ou de sections.
De même, vous pouvez créer un tableau de titre d'en-tête de section et un tableau de titre de pied de page pour configurer les titres de section de manière dynamique.