Question iOS 8 UITableView separator insert 0 ne fonctionne pas


J'ai une application où le UITableViewl'incrustation du séparateur est définie sur des valeurs personnalisées - Right 0, La gauche 0. Cela fonctionne parfaitement dans iOS 7.xcependant dans iOS 8.0 Je vois que l'encart séparateur est réglé sur la valeur par défaut de 15 sur la droite. Même si dans les fichiers xib, il est défini sur 0, il apparaît toujours incorrectement.

Comment puis-je supprimer le UITableViewCell marges du séparateur?


630
2017-09-10 16:05


origine


Réponses:


iOS 8.0 introduit la propriété layoutMargins sur les cellules ET les vues de table.

Cette propriété n'est pas disponible sur iOS 7.0, vous devez donc vous assurer de vérifier avant de l'affecter!

De plus, Apple a ajouté propriété à votre cellule qui l'empêchera d'hériter des paramètres de marge de votre Table View. Lorsque cette propriété est définie, vos cellules sont autorisées à configurer leurs propres marges indépendamment de la vue de la table. Pensez-y comme une dérogation.

Cette propriété est appelée preservesSuperviewLayoutMarginset en le réglant sur NO permettra à la cellule layoutMargin paramètre pour remplacer tout ce qui layoutMargin est défini sur votre TableView. Cela permet à la fois de gagner du temps (vous n'avez pas besoin de modifier les paramètres de la vue Table), et est plus concis. Veuillez vous référer à la réponse de Mike Abdullah pour une explication détaillée.

NOTE: ce qui suit est une implémentation propre pour un réglage de la marge au niveau de la cellule, comme exprimé dans la réponse de Mike Abdullah. La définition de preserveesSuperviewLayoutMargins = NO de votre cellule garantit que votre vue de table ne remplace pas les paramètres de la cellule. Si vous voulez que votre vue de table entière ait des marges cohérentes, ajustez votre code en conséquence.

Configurez vos marges de cellules:

-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Remove seperator inset
    if ([cell respondsToSelector:@selector(setSeparatorInset:)]) {
           [cell setSeparatorInset:UIEdgeInsetsZero];
    }

    // Prevent the cell from inheriting the Table View's margin settings
    if ([cell respondsToSelector:@selector(setPreservesSuperviewLayoutMargins:)]) {
        [cell setPreservesSuperviewLayoutMargins:NO];
    }

    // Explictly set your cell's layout margins
    if ([cell respondsToSelector:@selector(setLayoutMargins:)]) {
        [cell setLayoutMargins:UIEdgeInsetsZero];
    }
}

Définir la propriété preservesSuperviewLayoutMargins sur votre cellule sur NO devrait empêchez votre vue de table de surcharger les marges de votre cellule. Dans certains cas, il semble ne pas fonctionner correctement.

Si tout échoue, vous pouvez forcer brutalement les marges de votre vue Table:

-(void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];

    // Force your tableview margins (this may be a bad idea)
    if ([self.tableView respondsToSelector:@selector(setSeparatorInset:)]) {
        [self.tableView setSeparatorInset:UIEdgeInsetsZero];
    }

    if ([self.tableView respondsToSelector:@selector(setLayoutMargins:)]) {
        [self.tableView setLayoutMargins:UIEdgeInsetsZero];
    }
} 

... et voilà! Cela devrait fonctionner sur iOS 7 et 8.

MODIFIER:  Mohamed Saleh a porté à mon attention un éventuel changement d'iOS 9. Vous devrez peut-être définir la vue Table cellLayoutMarginsFollowReadableWidth à NO si vous souhaitez personnaliser les encarts ou les marges. Votre kilométrage peut varier, cela n'est pas très bien documenté.

Cette propriété n'existe que dans iOS 9, assurez-vous de vérifier avant de la définir.

if([myTableView respondsToSelector:@selector(setCellLayoutMarginsFollowReadableWidth:)])
{
    myTableView.cellLayoutMarginsFollowReadableWidth = NO;
} 

(ci-dessus le code de iOS 8 UITableView separator insert 0 ne fonctionne pas)

EDIT: Voici une approche purement Interface Builder:

TableViewAttributesInspector TableViewCellSizeInspector

NOTE: iOS 11 change et simplifie une grande partie de ce comportement, une mise à jour sera à venir ...


1048
2017-09-16 20:19



Arg !!! Après avoir joué soit en faisant cela dans votre Cell sous-classe:

- (UIEdgeInsets)layoutMargins
{
    return UIEdgeInsetsZero;
}

ou en réglant le cell.layoutMargins = UIEdgeInsetsZero; Je l'ai réparé pour moi.


251
2017-09-10 18:02



Prenons un moment pour comprendre le problème avant de charger aveuglément pour tenter de le réparer.

Un rapide coup de fouet dans le débogueur vous dira que les lignes de séparation sont des sous-vues de UITableViewCell. Il semble que la cellule elle-même assume une bonne part de responsabilité pour la disposition de ces lignes.

iOS 8 introduit le concept de marges de mise en page. Par défaut, les marges de disposition d'une vue sont 8pt de tous les côtés, et ils sont hérité des vues des ancêtres.

Le mieux que nous puissions dire, lors de la mise en place de sa ligne de séparation, UITableViewCell choisit de respecter la marge de mise en page gauche, en l'utilisant pour contraindre l'encart de gauche.

Mettre tout cela ensemble, pour atteindre l'encart désiré de zéro, nous devons:

  • Définissez la marge de mise en page gauche sur 0
  • Arrêtez toute marge héritée remplaçant cette

Mettez comme ça, c'est une tâche assez simple à réaliser:

cell.layoutMargins = UIEdgeInsetsZero;
cell.preservesSuperviewLayoutMargins = NO;

Choses à noter:

  • Ce code seulement Besoins être exécuté une fois par cellule (vous ne faites que configurer les propriétés de la cellule), et il n'y a rien de spécial quand vous choisissez de l'exécuter. Fais ce qui te semble le plus propre.
  • Malheureusement, aucune propriété n'est disponible à configurer dans Interface Builder, mais vous pouvez spécifier un attribut d'exécution défini par l'utilisateur pour preservesSuperviewLayoutMargins si on le désire.
  • De toute évidence, si votre application cible également les versions antérieures du système d'exploitation, vous devez éviter d'exécuter le code ci-dessus avant d'utiliser iOS 8 ou version ultérieure.
  • Plutôt que de définir preservesSuperviewLayoutMargins, toi pouvez configurer les vues ancêtres (telles que la table) pour avoir 0 marge gauche aussi, mais cela semble intrinsèquement plus sujet aux erreurs car vous ne contrôlez pas toute cette hiérarchie.
  • Il serait probablement légèrement plus propre de ne définir que la marge de gauche 0 et laisse les autres être.
  • Si vous voulez insérer un 0 sur les séparateurs "supplémentaires" UITableView dessine au bas des tables de style, je suppose que cela nécessitera de spécifier les mêmes paramètres au niveau de la table (pas essayé celui-là!)

174
2017-11-09 10:49



Je crois que c'est la même question que j'ai posée ici: Supprimer SeparatorInset sur iOS 8 UITableView pour XCode 6 iPhone Simulator

Dans iOS 8, il y a une nouvelle propriété pour tous les objets hérités de UIView. Ainsi, la solution pour définir le SeparatorInset dans iOS 7.x ne sera pas en mesure de supprimer l'espace blanc que vous voyez sur UITableView dans iOS 8.

La nouvelle propriété s'appelle "layoutMargins".

@property(nonatomic) UIEdgeInsets layoutMargins
Description   The default spacing to use when laying out content in the view.
Availability  iOS (8.0 and later)
Declared In   UIView.h
Reference UIView Class Reference

iOS 8 UITableView setSeparatorInset:UIEdgeInsetsZero setLayoutMargins:UIEdgeInsetsZero

La solution:-

-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{

    if ([tableView respondsToSelector:@selector(setSeparatorInset:)]) {
        [tableView setSeparatorInset:UIEdgeInsetsZero];
    }

    if ([tableView respondsToSelector:@selector(setLayoutMargins:)]) {
        [tableView setLayoutMargins:UIEdgeInsetsZero];
    }

   if ([cell respondsToSelector:@selector(setLayoutMargins:)]) {
        [cell setLayoutMargins:UIEdgeInsetsZero];
   }
}

Si vous définissez cell.layoutMargins = UIEdgeInsetsZero; sans vérifier si le layoutMargins existe, l'application va planter sur iOS 7.x. Donc, le meilleur moyen serait de vérifier si le layoutMargins existe d'abord avant setLayoutMargins:UIEdgeInsetsZero.


55
2017-09-11 12:54



Vous pouvez utiliser UIAppearance une fois, au démarrage de votre application (avant le chargement de l'interface utilisateur), pour le définir comme paramètres globaux par défaut:

// iOS 7:
[[UITableView appearance] setSeparatorStyle:UITableViewCellSeparatorStyleSingleLine];
[[UITableView appearance] setSeparatorInset:UIEdgeInsetsZero];

[[UITableViewCell appearance] setSeparatorInset:UIEdgeInsetsZero];

// iOS 8:
if ([UITableView instancesRespondToSelector:@selector(setLayoutMargins:)]) {

    [[UITableView appearance] setLayoutMargins:UIEdgeInsetsZero];
    [[UITableViewCell appearance] setLayoutMargins:UIEdgeInsetsZero];
    [[UITableViewCell appearance] setPreservesSuperviewLayoutMargins:NO];

}

De cette façon, vous gardez le code de votre UIViewController propre et pouvez toujours le remplacer si vous le souhaitez.


44
2018-02-03 10:09



Version rapide

iOS introduit la propriété layoutMargins sur les cellules ET les vues de table.

Cette propriété n'est pas disponible dans iOS 7.0, vous devez donc vous assurer de vérifier avant de l'affecter!

Cependant, Apple a ajouté un propriété appelé préserveSuperviewLayoutMargins à votre cellule qui l'empêchera d'hériter des paramètres de marge de votre Table View. De cette façon, vos cellules peuvent configurer leurs propres marges indépendamment de la vue de la table. Pensez-y comme une dérogation.

Cette propriété est appelée préserveSuperviewLayoutMarginset en le définissant sur NO peut vous permettre de remplacer les paramètres layoutMargin de votre Table View avec le paramètre layoutMargin de votre propre cellule. Cela permet à la fois de gagner du temps (vous n'avez pas besoin de modifier les paramètres de la vue Table), et est plus concis. Veuillez vous référer à la réponse de Mike Abdullah pour une explication détaillée.

NOTE: Ceci est la bonne mise en œuvre, moins désordonnée, comme l'exprime la réponse de Mike Abdullah; la définition de preserveesSuperviewLayoutMargins = NO de votre cellule garantit que votre vue Table ne remplace pas les paramètres de la cellule.

Première étape - Configurez vos marges de cellules:

/*
    Tells the delegate that the table view is about to draw a cell for a particular row.
*/
override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell,
    forRowAtIndexPath indexPath: NSIndexPath)
{
    // Remove separator inset
    if cell.respondsToSelector("setSeparatorInset:") {
        cell.separatorInset = UIEdgeInsetsZero
    }

    // Prevent the cell from inheriting the Table View's margin settings
    if cell.respondsToSelector("setPreservesSuperviewLayoutMargins:") {
        cell.preservesSuperviewLayoutMargins = false
    }

    // Explictly set your cell's layout margins
    if cell.respondsToSelector("setLayoutMargins:") {
        cell.layoutMargins = UIEdgeInsetsZero
    }
}

Définir la propriété preservesSuperviewLayoutMargins sur votre cellule sur NO devrait empêchez votre vue de table de surcharger les marges de votre cellule. Dans certains cas, il semble ne pas fonctionner correctement.

Deuxième étape - Seulement si tout échoue, vous pouvez forcer brutalement les marges de votre vue Table:

/*
    Called to notify the view controller that its view has just laid out its subviews.
*/
override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    // Force your tableview margins (this may be a bad idea)
    if self.tableView.respondsToSelector("setSeparatorInset:") {
        self.tableView.separatorInset = UIEdgeInsetsZero
    }

    if self.tableView.respondsToSelector("setLayoutMargins:") {
        self.tableView.layoutMargins = UIEdgeInsetsZero
    }
}

... et voilà! Cela devrait fonctionner sur iOS 8 ainsi que sur iOS 7.

Note: testé en utilisant iOS 8.1 et 7.1, dans mon cas, j'ai seulement besoin d'utiliser la première étape de cette explication.

La deuxième étape est seulement nécessaire si vous avez une cellule non peuplée sous les cellules rendues, c'est-à-dire. si la table est plus grande que le nombre de lignes dans le modèle de table. Ne pas effectuer la deuxième étape entraînerait des décalages de séparateur différents.


39
2017-12-23 18:34



Dans Swift, c'est un peu plus agaçant parce que layoutMargins est une propriété, vous devez donc remplacer le getter et setter.

override var layoutMargins: UIEdgeInsets {
  get { return UIEdgeInsetsZero }
  set(newVal) {}
}

Cela fera effectivement layoutMargins readonly, qui dans mon cas est bien.


35
2017-09-10 21:35



Pour iOS 9, vous devez ajouter:

if([myTableView respondsToSelector:@selector(setCellLayoutMarginsFollowReadableWidth:)])
{
    myTableView.cellLayoutMarginsFollowReadableWidth = NO;
} 

Pour plus de détails s'il vous plaît se référer à question.


21
2017-09-30 07:41



Swift 2.0 Extension

Je voulais juste partager une extension que j'ai faite pour supprimer les marges des séparateurs de cellule tableview.

extension UITableViewCell {
    func removeMargins() {

        if self.respondsToSelector("setSeparatorInset:") {
            self.separatorInset = UIEdgeInsetsZero
        }

        if self.respondsToSelector("setPreservesSuperviewLayoutMargins:") {
            self.preservesSuperviewLayoutMargins = false
        }

        if self.respondsToSelector("setLayoutMargins:") {
            self.layoutMargins = UIEdgeInsetsZero
        }
    }
}

Utilisé dans le contexte:

    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! CustomCell

    cell.removeMargins()
    return cell

18
2017-09-09 16:55



Rapide:

override func viewDidLoad() {
    super.viewDidLoad()

    if self.tableView.respondsToSelector("setSeparatorInset:") {
        self.tableView.separatorInset = UIEdgeInsetsZero
    }
    if self.tableView.respondsToSelector("setLayoutMargins:") {
        self.tableView.layoutMargins = UIEdgeInsetsZero
    }

    self.tableView.layoutIfNeeded()            // <--- this do the magic
}

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
     ...

    if cell.respondsToSelector("setSeparatorInset:") {
        cell.separatorInset = UIEdgeInsetsZero
    }
    if cell.respondsToSelector("setLayoutMargins:") {
        cell.layoutMargins = UIEdgeInsetsZero
    }

    return cell
}

13
2017-10-21 23:35



Je l'ai fait fonctionner en faisant ceci:

tableView.separatorInset = UIEdgeInsetsZero;
tableView.layoutMargins = UIEdgeInsetsZero;
cell.layoutMargins = UIEdgeInsetsZero;

10
2017-12-30 10:19