Le séparateur UITableView iOS 8 ne fonctionne pas

662

J'ai une application où l' UITableViewencart de séparation du est défini sur des valeurs personnalisées - Droite 0, Gauche 0. Cela fonctionne parfaitement dans iOS 7.x, mais iOS 8.0je vois que l'encart de séparation est défini sur la valeur par défaut de 15droite. Même si dans les fichiers xib sur lesquels il est défini 0, il s'affiche toujours de manière incorrecte.

Comment supprimer les UITableViewCellmarges du séparateur?

user3570727
la source
Avez-vous essayé de mettre l'encart à 0,001 au lieu de 0? Je me souviens avoir eu un problème similaire où l'encart de bord ne réagissait pas à 0 mais réagissait à 0,001 (ou quelque chose de similaire petit).
freshking
J'ai essayé ça et ça n'a pas marché non plus.
user3570727
4
Ensuite, je suggère de définir la couleur des séparateurs [UIColor clearColor]et de dessiner vos propres séparateurs. Vous êtes beaucoup plus flexible de cette façon.
freshking
1
Je n'arrive toujours pas à croire que ce n'est toujours pas l'un des UITableViewCellSeparatorStyledéfauts. Même la réponse acceptée est un hack vraiment sale à mon avis.
Enrico Susatyo

Réponses:

1071

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

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

La solution simple consiste à sous-classer votre cellule et à remplacer la propriété des marges de disposition, comme suggéré par @ user3570727. Cependant, vous perdrez tout comportement du système comme l'héritage des marges de la zone sûre, donc je ne recommande pas la solution ci-dessous:

(Objectif c)

-(UIEdgeInsets)layoutMargins { 
     return UIEdgeInsetsZero // override any margins inc. safe area
}

(rapide 4.2):

override var layoutMargins: UIEdgeInsets { get { return .zero } set { } }

Si vous ne souhaitez pas remplacer la propriété ou devez la définir de manière conditionnelle, continuez à lire.


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

Cette propriété est appelée preservesSuperviewLayoutMarginset sa définition NOpermettra au layoutMarginparamètre de la cellule de remplacer tout ce qui layoutMarginest défini sur votre TableView. Il permet à la fois de gagner du temps ( vous n'avez pas à 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.

REMARQUE: ce qui suit est une implémentation propre pour un paramètre de marge au niveau de la cellule , comme exprimé dans la réponse de Mike Abdullah. La définition de vos cellules preservesSuperviewLayoutMargins=NOgarantit que votre vue de table ne remplace pas les paramètres de la cellule. Si vous souhaitez réellement que l'ensemble de votre vue de table ait des marges cohérentes, veuillez ajuster votre code en conséquence.

Configurez vos marges de cellule:

-(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];
    }
}

Swift 4:

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    // Remove seperator inset
    if cell.responds(to: #selector(setter: UITableViewCell.separatorInset)) {
        cell.separatorInset = .zero
    }
    // Prevent the cell from inheriting the Table View's margin settings
    if cell.responds(to: #selector(setter: UITableViewCell.preservesSuperviewLayoutMargins)) {
        cell.preservesSuperviewLayoutMargins = false
    }
    // Explictly set your cell's layout margins
    if cell.responds(to: #selector(setter: UITableViewCell.layoutMargins)) {
        cell.layoutMargins = .zero
    }
}

La définition de la preservesSuperviewLayoutMarginspropriété NO sur votre cellule devrait empêcher votre vue de table de remplacer vos marges de cellule. Dans certains cas, il semble ne pas fonctionner correctement.

Si tout échoue, vous pouvez forcer brutalement vos marges d'affichage de 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];
    }
} 

Swift 4:

func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    // Force your tableview margins (this may be a bad idea)
    if tableView.responds(to: #selector(setter: UITableView.separatorInset)) {
        tableView.separatorInset = .zero
    }
    if tableView.responds(to: #selector(setter: UITableView.layoutMargins)) {
        tableView.layoutMargins = .zero
    }
}

... et c'est parti! Cela devrait fonctionner sur iOS 7 et 8.


EDIT: Mohamed Saleh attiré mon attention sur un éventuel changement dans iOS 9. Vous devrez peut - être régler le Tableau de cellLayoutMarginsFollowReadableWidthla NOsi vous souhaitez personnaliser ou marges des encarts. Votre kilométrage peut varier, cela n'est pas très bien documenté.

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

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

Swift 4:

if myTableView.responds(to: #selector(setter: self.cellLayoutMarginsFollowReadableWidth)) {
    myTableView.cellLayoutMarginsFollowReadableWidth = false
}

(le code ci-dessus à partir du séparateur UITableView iOS 8 ne fonctionne pas )

EDIT: Voici une pure approche Interface Builder:

TableViewAttributesInspector TableViewCellSizeInspector

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

cdstamper
la source
2
Pour les vues de table à l'intérieur d'un UIPopoverController, j'ai dû faire les deux comme indiqué ci-dessus, au lieu de simplement dans le willDisplayCell.
Zhang
44
J'ai également constaté que malgré tout le code ci-dessus, je devais encore ajouter cell.preservesSuperviewLayoutMargins = NOla suggestion de @ bffmike ou après avoir fait défiler les façons dont les encarts apparaîtront. (wtf ??)
inorganik
Et si nous voulons définir la marge uniquement pour un type de cellule dans une table groupée?
SAHM
Vous pouvez essayer de le définir dans willDisplayCell et voir si cela fonctionne réellement (vous avez une poignée sur la cellule, donc cela devrait être trivial). Si ce n'est pas le cas, nous devons déposer un bogue. Des marges de disposition spécifiques aux cellules devraient être possibles, OMI.
cdstamper
2
Cela a fonctionné pour moi avec l'ajout de cell.preservesSuperviewLayoutMarginsdans ma méthode de source de données:- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
mts
257

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

- (UIEdgeInsets)layoutMargins
{
    return UIEdgeInsetsZero;
}

ou en le cell.layoutMargins = UIEdgeInsetsZero;fixant pour moi.

user3570727
la source
13
la première solution dans cette réponse a fonctionné pour moi, la 2ème n'a pas fonctionné.
spybart
5
N'utilisez pas simplement cell.layoutMargins = UIEdgeInsetsZero; car il plantera sur iOS 7.x. Il vaut mieux vérifier si le sélecteur existe avant de l'utiliser. Voir ma solution ci-dessous.
Ricky
3
Il ne définit pas cell.layoutMargins ... Cette solution fonctionne très bien lorsque vous avez déjà des cellules personnalisées.
Sjoerd Perfors
11
Cela fonctionnera bien dans iOS 7, car la méthode ne sera pas appelée! Vous devez également définir les layoutMargins de la vue de table, sinon cela ne fonctionnera pas.
cdstamper
2
outrepasser l'accesseur a fonctionné pour moi. mais pas toutes les autres solutions. même la configuration de l' separatorInsetIB n'a pas fonctionné. il y a aussi un problème avec les couleurs d'arrière-plan de la vue tableau. ce sont des trucs vraiment malades.
glasz
178

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

Un rapide coup d'œil 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 présentation d'une vue sont 8ptde tous les côtés et héritées des vues ancêtres.

Autant que nous puissions le dire, lors de la disposition de sa ligne de séparation, UITableViewCellchoisit de respecter la marge de disposition de gauche, en l'utilisant pour contraindre l'encart gauche.

En mettant tout cela ensemble, pour atteindre l'encart souhaité de zéro, nous devons:

  • Définissez la marge de mise en page gauche sur 0
  • Arrêtez toutes les marges héritées remplaçant

En d'autres termes, c'est une tâche assez simple à réaliser:

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

A noter:

  • Ce code ne doit être exécuté qu'une fois par cellule (vous configurez simplement les propriétés de la cellule après tout), et il n'y a rien de spécial quand vous choisissez de l'exécuter. Faites ce qui vous 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 preservesSuperviewLayoutMarginssi vous le souhaitez.
  • De toute évidence, si votre application cible également les versions antérieures du système d'exploitation, vous devrez éviter d'exécuter le code ci-dessus jusqu'à ce qu'il s'exécute sur iOS 8 et supérieur.
  • Plutôt que de définir preservesSuperviewLayoutMargins, vous pouvez configurer des vues d'ancêtre (telles que la table) pour qu'elles aient également 0laissé une marge, mais cela semble intrinsèquement plus sujet aux erreurs car vous ne contrôlez pas toute cette hiérarchie.
  • Il serait probablement un peu plus propre de ne fixer que la marge gauche 0et de laisser les autres être.
  • Si vous voulez avoir un insert 0 sur les séparateurs "supplémentaires" qui UITableViewdessine au bas des tables de style simples, je suppose que cela nécessitera de spécifier les mêmes paramètres au niveau de la table aussi (je n'ai pas essayé celui-ci!)
Mike Abdullah
la source
3
Je vous remercie! C'est vraiment la réponse la plus concise. Bien mieux que de remplacer deux méthodes et de le forcer brutalement.
LunaCodeGirl
16
Dans iOS 8, pour moi, cela ne fonctionnerait pas sans[self.tableView setSeparatorInset:UIEdgeInsetsMake(0, 0, 0, 0)];
davetw12
1
Vous avez mon vote, merci pour l'explication claire. Je mentionnerai simplement que le TableView lui-même a également des layoutMargins qui peuvent devoir être définis en plus du separatorInset, dans certains cas.
cdstamper
@ davetw12 et @cdstamper Pouvez-vous en apporter la preuve? Toutes mes explorations jusqu'à présent disent que la mise à la fois layoutMarginset preservesSuperviewLayoutMarginssur la cellule est tout ce qui est nécessaire. Tout le reste ressemble à faire confiance au vaudou.
Mike Abdullah
3
Non, ce n'est pas une forme de vaudou @MikeAbdullah. Pour éviter la valeur par défaut separatorInsetd'un UITableViewCelldans iOS 8, vous devez définir la valeur UIEdgeInsetszéro sur le UITableViewet le UITableViewCell. Si vous ne faites pas les deux, vous aurez toujours un encart gauche supérieur à zéro. Je l'ai confirmé plusieurs fois.
davetw12
58

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 existe une nouvelle propriété pour tous les objets hérités UIView. Ainsi, la solution pour définir l' SeparatorInsetiOS 7.x ne pourra pas supprimer l'espace blanc que vous voyez sur l'UITableView dans iOS 8.

La nouvelle propriété est appelée " 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 s'il layoutMarginsexiste, l'application se bloque sur iOS 7.x. Ainsi, la meilleure façon serait de vérifier si le layoutMarginspremier existe avant setLayoutMargins:UIEdgeInsetsZero.

Ricky
la source
Comment cette approche peut-elle être utilisée si la cible de déploiement est définie sur iOS 7?
Petar
J'ai mis le code de tableView dans viewDidLoad et fonctionne très bien. Je pense qu'il n'est pas nécessaire de les appeler à chaque fois dans willDisplayCell ().
Abdullah Umer
46

Vous pouvez utiliser UIAppearance une fois, au démarrage de votre application (avant le chargement de l'interface utilisateur), pour la 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.

Lukasz
la source
41

iOS présente la propriété layoutMargins sur les cellules ET les vues de tableau.

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

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

Cette propriété est appelée préserveSuperviewLayoutMargins et la définir sur NO peut vous permettre de remplacer les paramètres layoutMargin de votre vue Tableau par le paramètre layoutMargin de votre propre cellule. Il permet à la fois de gagner du temps ( vous n'avez pas à 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.

REMARQUE: il s'agit de l'implémentation appropriée et moins compliquée, comme exprimé dans la réponse de Mike Abdullah; définir la conservation de votre celluleSuperviewLayoutMargins = NO garantira que votre vue Tableau ne remplace pas les paramètres de la cellule.

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

/*
    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
    }
}

Si vous définissez la propriété NO de la propriété conserveSuperviewLayoutMargins sur votre cellule, votre vue de table ne doit pas remplacer vos marges de cellule. Dans certains cas, il ne semble pas fonctionner correctement.

Deuxième étape - Seulement si tout échoue, vous pouvez forcer brutalement vos marges d'affichage de 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 c'est parti! Cela devrait fonctionner sur iOS 8 ainsi que sur iOS 7.

Remarque: testé avec iOS 8.1 et 7.1, dans mon cas, je n'avais besoin que de la première étape de cette explication.

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

Roi-sorcier
la source
1
Vous n'avez pas besoin de vérifier les sélecteurs dans la willDisplayCellméthode car la méthode elle-même est déjà iOS 8+ et ne sera jamais appelée à partir d'anciennes versions.
Rivera
38

Dans Swift, c'est un peu plus ennuyeux car layoutMarginsc'est une propriété, vous devez donc remplacer le getter et le setter.

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

Cela rendra effectivement en layoutMarginslecture seule, ce qui dans mon cas est très bien.

swilliams
la source
Seule cette solution a fonctionné pour moi. Et je n'avais pas besoin d'ajouter de code de lignes supplémentaire dans les méthodes. J'ai utilisé des cellules personnalisées.
Ramis
2
Pour la cellule statique, à l'exception de la substitution de layoutMargins, vous devez toujours changer le style de séparateur de cellule en "Encarts personnalisés" et définir la valeur de gauche sur "0" dans le storyboard.
hufeng03
22

Pour iOS 9, vous devez ajouter:

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

Pour plus de détails, veuillez vous référer à la question .

Julian Król
la source
12
il est amusant d'ajouter du code pour chaque version afin que l'apparence initiale reste la même ...
Christian
20

Extension Swift 2.0

Je voulais juste partager une extension que j'ai faite pour supprimer les marges des séparateurs de cellules 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é en contexte:

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

    cell.removeMargins()
    return cell
Dan Beaulieu
la source
15

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
}
Alexander Volkov
la source
11

Je l'ai fait fonctionner en faisant ceci:

tableView.separatorInset = UIEdgeInsetsZero;
tableView.layoutMargins = UIEdgeInsetsZero;
cell.layoutMargins = UIEdgeInsetsZero;
ideawu
la source
9

Quant à ce que cdstamper a suggéré au lieu de la vue de table, l'ajout de lignes ci-dessous dans la méthode layoutSubview de la cellule fonctionne pour moi.

- (void)layoutSubviews 
{
    [super layoutSubviews];

    if ([self respondsToSelector:@selector(setSeparatorInset:)])
                [self setSeparatorInset:UIEdgeInsetsZero];

        if ([self respondsToSelector:@selector(setPreservesSuperviewLayoutMargins:)])
        {
            [self setPreservesSuperviewLayoutMargins:NO];;
        }

        if ([self respondsToSelector:@selector(setLayoutMargins:)]) 
        {
            [self setLayoutMargins:UIEdgeInsetsZero];
        }
}
Vijay VS
la source
9

Exemple Swift 3.0:

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    // removing seperator inset
    if cell.responds(to: #selector(setter: UITableViewCell.separatorInset)) {
        cell.separatorInset = .zero
    }
    // prevent the cell from inheriting the tableView's margin settings
    if cell.responds(to: #selector(setter: UIView.preservesSuperviewLayoutMargins)) {
        cell.preservesSuperviewLayoutMargins = false
    }
    // explicitly setting cell's layout margins
    if cell.responds(to: #selector(setter: UITableViewCell.layoutMargins)) {
        cell.layoutMargins = .zero
    }
}
mkz
la source
9

Après de nombreuses recherches ...

Voici le seul moyen de contrôler complètement ce genre de choses (que j'ai pu trouver)

Pour contrôler complètement les insertions de séparateur et les marges de disposition sur chaque cellule. Pour ce faire, dans la willDisplayCellméthode sur votre UITableviewDelegate.

func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    cell.layoutMargins = UIEdgeInsetsZero
    cell.contentView.layoutMargins = UIEdgeInsetsMake(0, 10, 0, 10)
    cell.separatorInset = UIEdgeInsetsMake(0, 0, 0, 0)
}

L'objet cellule contrôle le séparateur et le contentViewcontrôle tout le reste. Si vos espaces d'encart séparateur apparaissent dans une couleur inattendue, cela devrait le résoudre:

cell.backgroundColor = cell.contentView.backgroundColor
Matjan
la source
8

Solution simple dans Swift pour iOS 8 avec une personnalisationUITableViewCell

override func awakeFromNib() {
    super.awakeFromNib()

    self.layoutMargins = UIEdgeInsetsZero
    self.separatorInset = UIEdgeInsetsZero
}

De cette façon, vous définissez layoutMarginet separatorInsetune seule fois au lieu de le faire pour chacun, willDisplayCellcomme le suggèrent la plupart des réponses ci-dessus.

Si vous utilisez une coutume, UITableViewCellc'est le bon endroit pour le faire. Sinon, vous devriez le faire en tableView:cellForRowAtIndexPath.

Juste un autre indice: vous n'avez pas besoin de définir preservesSuperviewLayoutMargins = falsecar la valeur par défaut est déjà NO!

Francesco Vadicamo
la source
8

Pour moi, la ligne simple a fait le travail

cell.layoutMargins = UIEdgeInsetsZero
apinho
la source
appelé cela dans la méthode déléguée cellForRowAtIndexPath. Bonne réponse :)
saintjab
7

Il suffit d'ajouter le code ci-dessous pour résoudre ce programme.

Bonne chance à toi!

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

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

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

}
JimmyChang
la source
5

Réponse de Lukasz dans Swift:

    // iOS 7:
    UITableView.appearance().separatorStyle = .SingleLine
    UITableView.appearance().separatorInset = UIEdgeInsetsZero
    UITableViewCell.appearance().separatorInset = UIEdgeInsetsZero

    // iOS 8:
    if UITableView.instancesRespondToSelector("setLayoutMargins:") {
        UITableView.appearance().layoutMargins = UIEdgeInsetsZero
        UITableViewCell.appearance().layoutMargins = UIEdgeInsetsZero
        UITableViewCell.appearance().preservesSuperviewLayoutMargins = false
    }
Naka
la source
5

Voici le code qui fonctionne pour moi, dans Swift:

override func viewDidLoad() 
{
    super.viewDidLoad()
    ...
    if tableView.respondsToSelector("setSeparatorInset:") {
        tableView.separatorInset = UIEdgeInsetsZero
    }
}

func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell,forRowAtIndexPath indexPath: NSIndexPath)
{
    if cell.respondsToSelector("setSeparatorInset:") {
        cell.separatorInset.left = CGFloat(0.0)
    }
    if tableView.respondsToSelector("setLayoutMargins:") {
        tableView.layoutMargins = UIEdgeInsetsZero
    }
    if cell.respondsToSelector("setLayoutMargins:") {
        cell.layoutMargins.left = CGFloat(0.0)
    }
}

Cela me semble le plus propre (pour l'instant), car tous les ajustements de bord / marge cell / tableView sont effectués dans la tableView:willDisplayCell:forRowAtIndexPath:méthode, sans bourrer de code inutile tableView:cellForRowAtIndexPath:.

Btw, je ne fais que définir le séparateur gauche de la celluleInset / layoutMargins, car dans ce cas, je ne veux pas bousiller mes contraintes que j'ai définies dans ma cellule.

Code mis à jour vers Swift 2.2:

 override func viewDidLoad() {
   super.viewDidLoad()       

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

 override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell,forRowAtIndexPath indexPath: NSIndexPath) {
        if cell.respondsToSelector(Selector("setSeparatorInset:")) {
            cell.separatorInset.left = CGFloat(0.0)
        }
        if tableView.respondsToSelector(Selector("setLayoutMargins:")) {
            tableView.layoutMargins = UIEdgeInsetsZero
        }
        if cell.respondsToSelector(Selector("setLayoutMargins:")) {
            cell.layoutMargins.left = CGFloat(0.0)
        }
    }
Ivan
la source
Qu'est-ce qui ne fonctionne pas exactement pour vous? Je viens de tester ce code sur le simulateur iPhone 5, avec le SDK iOS 8.1 installé, et tout est comme lors de la publication de cette réponse. Le code a été compilé et exécuté avec Xcode 6.1.1.
Ivan
4

La plupart des réponses montrent de séparation et empiècements marges de mise en page étant réparties sur une variété de méthodes (c. -à- viewDidLayoutSubviews, willDisplayCell, etc.) pour les cellules et tableviews, mais j'ai trouvé que juste de mettre ces derniers dans des cellForRowAtIndexPathœuvres grandes. Semble comme la manière la plus propre.

// kill insets for iOS 8
if ([[UIDevice currentDevice].systemVersion floatValue] >= 8) {
    cell.preservesSuperviewLayoutMargins = NO;
    [cell setLayoutMargins:UIEdgeInsetsZero];
}
// iOS 7 and later
if ([cell respondsToSelector:@selector(setSeparatorInset:)])
    [cell setSeparatorInset:UIEdgeInsetsZero];
inorganik
la source
4

Utilisez l'extrait de code ci-dessous pour éviter les problèmes de remplissage indésirables pour UITableView dans IOS 8 et 7.

-(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];
    }
}
Anooj VM
la source
4

Au lieu de mettre à jour preservesSuperviewLayoutMarginset à layoutMarginschaque fois que la cellule défile (en utilisant willDisplayCell), je suggère de le faire une fois dans cellForRowAtIndexPath::

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

    let cell = super.tableView(tableView, cellForRowAtIndexPath: indexPath)

    cell.preservesSuperviewLayoutMargins = false
    cell.layoutMargins = UIEdgeInsetsZero

    return cell

}
Rudolf Adamkovič
la source
4

Voici un moyen simple de supprimer globalement l'encart.

Dans UITableViewCell+Extensions.swift:

import UIKit

extension UITableViewCell {

  override public var layoutMargins: UIEdgeInsets {
    get { return UIEdgeInsetsZero }
    set { }
  }

}

Dans AppDelegate application:didFinishLaunchingWithOptions::

  UITableViewCell.appearance().separatorInset = UIEdgeInsetsZero

Vous pourriez penser à a) remplacer simplement separatorInsetl'extension, ou b) définir le proxy d'apparence à la layoutMarginsplace. Ni l'un ni l'autre ne fonctionnera. Même s'il separatorInsetest indiqué qu'il s'agit d'une propriété, tenter de la remplacer en tant que propriété (ou méthode) génère des erreurs de compilation. Et définir le proxy d'apparence pour UITableViewCell's layoutMargins(ou, d'ailleurs, définir également les proxys d'apparence pour UITableView' s layoutMarginset separatorInset) n'a aucun effet.

Scott Gardner
la source
3

Dans iOS8:

Ajout de ceci à ma sous-classe UITableViewCell:

- (UIEdgeInsets)layoutMargins {
    return UIEdgeInsetsZero;
}

et ceci à "tableView: cellForRowAtIndexPath" ou "tableView: willDisplayCell":

[editCell setSeparatorInset:UIEdgeInsetsZero];

A FONCTIONNÉ pour moi.

Saru
la source
2
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        // ... Get the cell
        cell.separatorInset = UIEdgeInsetsMake(0.f, 20.f, 0.f, [UIScreen mainScreen].bounds.size.width - 20);
        // others
        return cell;
}

Pour toute cellule spécifique, vous souhaitez masquer le séparateur.

xmurobi
la source
2

Après avoir vu les réponses à l'étage 3, j'ai essayé de comprendre la relation entre la configuration du séparateur entre TableView et TableViewCell et j'ai fait quelques tests. Voici mes conclusions:

  1. nous pouvons considérer que la mise à zéro du séparateur de cellule doit déplacer le séparateur en deux étapes: la première étape consiste à régler le séparateur de cellule à zéro. la deuxième étape consiste à mettre la marge de la cellule à zéro.

  2. définissez le séparateur de TableView et la disposition de marge peut affecter le séparateur de la cellule . Cependant, d'après le test, je trouve que le jeu de séparateurs de TableView semble être inutile, le marginlayout de TableView peut en fait affecter le marginlayout de la cellule .

  3. définir Cell's PreservesSuperviewLayoutMargins = false, peut couper l' effet marginlayout de TableView sur les cellules.

  4. une des solutions:

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        var cell = UITableViewCell()
    
        cell.preservesSuperviewLayoutMargins = false
        cell.separatorInset = UIEdgeInsetsZero
        cell.layoutMargins = UIEdgeInsetsZero
    
        return cell
    }
Xin Chen
la source
2

C'est ma solution. Cela s'applique à la sous-classe de cellule personnalisée, ajoutez-les simplement à la sous-classe.

  1. - (UIEdgeInsets)layoutMargins {    
        return UIEdgeInsetsMake(0, 10, 0, 10);
    }

2.

self.separatorInset = UIEdgeInsetsMake(0, 10, 0, 10);

Et il est pratique que vous puissiez personnaliser la position du séparateur sans demander à votre concepteur d'en dessiner un pour vous ..........

Guoyu
la source
1

De manière plus compacte que la réponse la plus votée ...

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

    if ([cell respondsToSelector:@selector(setSeparatorInset:)] && [cell respondsToSelector:@selector(setPreservesSuperviewLayoutMargins:)] && [cell respondsToSelector:@selector(setLayoutMargins:)]) {
         [cell setSeparatorInset:UIEdgeInsetsZero];
         [cell setPreservesSuperviewLayoutMargins:NO];
         [cell setLayoutMargins:UIEdgeInsetsZero];
    }

}

subharb
la source
1

L'ajout de cet extrait, simple et élégant dans Swift, fonctionne pour moi dans iOS8 :)

    // tableview single line
func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    cell.preservesSuperviewLayoutMargins = false
    cell.layoutMargins = UIEdgeInsetsZero
}
ddnl
la source
1

Cela a parfaitement fonctionné pour moi dans iOS 8 et iOS 9.

Pour OBJ-C

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(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];
        }
         return cell;
    }
jithin
la source