web-dev-qa-db-fra.com

UITableView: la manière correcte d'afficher un séparateur pour la dernière cellule

La question est de savoir quel est le moyen le plus approprié d’afficher un séparateur dans la dernière cellule d’un tableau ou d’une section. 

Fondamentalement, c'est ce que je suis après.

enter image description here Cela provient de l'application de musique native, ce qui me laisse penser qu'il devrait être possible de réaliser simplement avec UITableView, ils n'utiliseraient pas une API privée pour les séparateurs de cellules, n'est-ce pas?

Je sais que vous pouvez vous en sortir sans utiliser de séparateurs réels, mais en ajoutant une ligne de pixel au bas de la cellule. Mais je ne suis pas fan de cette approche car

  1. Quand une cellule est sélectionnée/mise en surbrillance son séparateur et le séparateur de la cellule précédente est automatiquement masqué (voir la deuxième capture d'écran avec l'option "Vous devez être fou" sélectionnée). Et c’est quelque chose que je veux que UITableView gère au lieu de le faire moi-même si j’utilise une ligne d’un pixel .__ (ce qui est particulièrement pratique lorsque les séparateurs de cellules n’étendent pas tous Jusqu’au bord de la vue sous forme de tableau. , les séparateurs et l’arrière-plan de la cellule sélectionnée ne sont pas beaux ensemble).
  2. Je souhaite que mes cellules soient aussi plates que possible pour les performances de défilement.

De plus, il y a quelque chose dans la référence UITableView qui me fait penser qu'il existe un moyen facile d'obtenir ce que je veux:

Dans iOS 7 et versions ultérieures, les séparateurs de cellules ne s'étendent pas jusqu'au fichier Bord de la vue de table. Cette propriété définit l'encart par défaut pour tout les cellules du tableau, un peu comme rowHeight définit la hauteur par défaut de cellules. Il est également utilisé pour gérer les séparateurs “extra” dessinés à le bas des tables de style simples.

Est-ce que quelqu'un sait exactement comment utiliser ces "extra" séparateurs dessinés au bas des tables en style clair? Parce que c'est exactement ce dont j'ai besoin. Je pensais qu'attribuer separatorInset à UITableView et non pas UITableViewCell ferait l'affaire, mais ce n'est pas le cas, la dernière cellule manque toujours de son séparateur.

Pour le moment, je ne vois qu’une option: avoir un pied de page personnalisé pour imiter le séparateur de la dernière cellule. Et ce n’est pas bon, surtout si vous voulez avoir un pied de section utilisant la méthode tableView:titleForFooterInSection:.

29
dariaa

Cela a parfaitement fonctionné pour moi d'ajouter un séparateur à la dernière cellule. s'amuser!

self.tableView.tableFooterView = [[UIView alloc] init];
16
Timo Cengiz

Lorsque vous ajoutez headerView ou footerView à votre table, la dernière ligne de séparation disparaît. 

L'exemple ci-dessous vous permettra de contourner le problème en affichant le séparateur sur la dernière cellule. La seule chose que vous devez faire davantage est de faire disparaître ce séparateur après la sélection d'une cellule. Le comportement est donc le même que dans le reste des cellules.

Pour Swift 4.0

func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {

    let result = UIView()

    // recreate insets from existing ones in the table view
    let insets = tableView.separatorInset
    let width = tableView.bounds.width - insets.left - insets.right
    let sepFrame = CGRect(x: insets.left, y: -0.5, width: width, height: 0.5)

    // create layer with separator, setting color
    let sep = CALayer()
    sep.frame = sepFrame
    sep.backgroundColor = tableView.separatorColor?.cgColor
    result.layer.addSublayer(sep)

    return result
}
8
lukszar

Je viens de trouver quelque chose qui fonctionne pour moi. En quelques mots: donnez à votre UITableView un tableFooterView et définissez la hauteur de son cadre sur 0 . Cela fait apparaître un séparateur réel, avec les encarts appropriés.

Plus en détail: si vous utilisez le storyboard, faites glisser un UIView vers le bas de votre vue Tableau (dans l'arborescence de gauche) pour qu'il s'affiche juste en dessous de la cellule Vue Tableau, au même niveau hiérarchique. Cela crée une tableFootView. Bien sûr, cela peut aussi être fait par programme.

Ensuite, dans l'implémentation de votre UITableViewController:

UIView *footerView = self.tableView.tableFooterView;
CGRect footerFrame = footerView.frame;
footerFrame.size.height = 0;
[footerView setFrame:footerFrame];

Laissez-moi savoir si cela fonctionne pour vous! Cela pourrait également fonctionner pour le premier séparateur si vous utilisiez plutôt un tableHeaderView, je ne l’ai pas essayé cependant.

7
SimonFrr

Vous pouvez faire quelque chose comme ceci si vous n'utilisez pas de sections: 

- (void)viewDidLoad
{
     self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectMake(insetLeftSide, 0, width - insetRightSide, 1)];
}

Si vous utilisez des sections, implémentez le pied de page dans chaque section sous la forme d'un point. Dans les méthodes

- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
}

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
}

Cela vous permettra d’avoir un séparateur pour votre dernière cellule qui, en fait, n’est pas un séparateur, c’est un pied de page avec lequel vous pouvez jouer et le faire ressembler à un séparateur.

2
artud2000

Voici donc une solution très simple dans Swift 4 qui fonctionne:

Dans override func viewDidLoad(){}, j'ai simplement implémenté cette ligne de code:

    self.tableView.tableFooterView = UIView(frame: .zero)

Par conséquent, cela garantit que seule la dernière cellule obtient le séparateur inséré.

Cela a parfaitement fonctionné pour moi, j'espère que ça le fera aussi pour vous!

2
Nii Mantse

J'ai eu un problème similaire et j'ai trouvé une solution de contournement. Apple masque le dernier séparateur uitableviewcell et l’affiche ensuite si vous sélectionnez la cellule ou si vous appelez sélectionner et désélectionner cette cellule.

J'ai donc enseigné que le meilleur est en - (void)layoutSubviews. La vue de séparation s'appelle _separatorView et c'est une propriété privée. En utilisant les états sélectionnés/mis en surbrillance de la cellule, vous pouvez créer quelque chose comme ceci:

- (void)layoutSubviews
{
    // Call super so the OS can do it's layout first
    [super layoutSubviews];

    // Get the separator view
    UIView *separatorView = [self valueForKey:@"_separatorView"];
    // Make the custom inset
    CGRect newFrame = CGRectMake(0.0, 0.0, self.bounds.size.width, separatorView.frame.size.height);
    newFrame = CGRectInset(newFrame, 15.0, 0.0);
    [separatorView setFrame:newFrame];

    // Show or hide the bar based on cell state        
    if (!self.selected) {
        separatorView.hidden = NO;
    }
    if (self.isHighlighted) {
        separatorView.hidden = YES;
    }
}

Quelque chose comme ça.

2
Cyupa

Dans iOS 8, si vous avez un style ordinaire UITableView et que vous ajoutez un pied de page, le dernier séparateur est parti. Toutefois, vous pouvez facilement le recréer en ajoutant une vue de séparation personnalisée au pied de page.

Cet exemple imite exactement le style de séparateur Today Widget

    override func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {

        //create footer view
        let result = UIView()
        result.frame.size.height = tableView.rowHeight

        //recreate last cell separator, which gets hidden by footer
        let sepFrame = CGRectMake(15, -0.5, tableView.frame.width, 0.5);
        let vibrancyEffectView = UIVisualEffectView.init(effect: UIVibrancyEffect.notificationCenterVibrancyEffect())
        vibrancyEffectView.frame = sepFrame
        vibrancyEffectView.contentView.backgroundColor = tableView.separatorColor
        result.addSubview(vibrancyEffectView)
        return result
}
1
Vilém Kurz

Si vous ajoutez un pied de page vide, la vue tableau supprimera tous les séparateurs de lignes restants (pour les cellules inexistantes), mais inclura toujours le séparateur de la dernière cellule:

- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
    return [UIView new]; 
}
1
Oren

Swift 3

J'ai trouvé ce vieux problème, alors j'ai essayé la même chose dans Swift:

    tableView.tableFooterView = UIView()
    tableView.tableFooterView?.height = 0 // Maybe not necessary

Mais cela a conduit à un autre problème (dans mon cas). Alors je l'ai résolu différemment. J'ai ajouté une cellule supplémentaire à la fin de cette section, vide et dont la hauteur est égale à zéro:

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
      return previousNumberOfRows + 1
    }

    override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
      return indexPath.row == previousNumberOfRows ? 0 : previousCellHeight
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
      if indexPath.row == items.count {
        return UITableViewCell()
    } else {
       previousCellInitialization()
    }

Ceci est une solution moins concise, mais fonctionne dans plus de cas, si vous avez plusieurs sections, vues de pied de page existantes ...

0
Cocatrix

Fonctionne dans iOS 7.x et 8.x (le mettre dans cellForRowAtIndexPath):

(PS remplace "max éléments de votre source de données" par le nombre de sources de données de votre tableau)

 if (row == <max elements of your datasource>-1) {
     UIView* separatorLineView = [[UIView alloc] initWithFrame:CGRectMake(0, cell.contentView.frame.size.height-1, self.view.frame.size.width, 1)];/// change size as you need.
     separatorLineView.tag = 666;
     separatorLineView.backgroundColor = [UIColor colorWithRed: 204.0/255.0 green: 204.0/255.0 blue: 204.0/255.0 alpha:1.0];
     UIView *separator = [cell.contentView viewWithTag:666];
     // case of orientation changed..
     if (separator.frame.size.width != cell.contentView.frame.size.width) {
        [[cell.contentView viewWithTag:666] removeFromSuperview];
        separator = nil;
     }
     if (separator==nil) [cell.contentView addSubview:separatorLineView];
 }
0
Alessandro Ornano

Ceci est certainement aider. Travail. mais définir le séparateur "none" de l'inspecteur d'attributs . Écrire le code suivant dans cellForRowAtIndexPath method

if(indexPath.row==arrData.count-1){
 UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(0,           
 cell.contentView.frame.size.height - 1.0,      
 cell.contentView.frame.size.width, 1)];

    lineView.backgroundColor = [UIColor blackColor];
    [cell.contentView addSubview:lineView];
}
0
Mr.Javed Multani

Le code ci-dessous a fonctionné pour moi:

UIView *footerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, 0.35)];
footerView.backgroundColor = [UIColor whiteColor];
CGRect frame = footerView.frame;
frame.Origin.x = 15;
frame.size.width = frame.size.width - 15;
UIView *blackView = [[UIView alloc] initWithFrame:frame];
[blackView setBackgroundColor:[UIColor blackColor]];
blackView.alpha = 0.25;
[footerView addSubview:blackView];
tableView.tableFooterView = footerView;

J'espère que ça marchera pour toi aussi.

0
Ashik