web-dev-qa-db-fra.com

Groupable UITableview supprimer la ligne de séparation externe

J'ai un groupe UITableview qui est créé par programme. De plus, une cellule avec un fichier xib est également renseignée par programme dans tableview. Jusqu'ici tout va bien. Mais je veux supprimer uniquement la ligne de séparation externe. J'ai utilisé le code ci-dessous, mais cette fois, j'ai supprimé toute la ligne de séparation. 

self.tableView.separatorColor = [UIColor clearColor];

ce n'est pas une bonne option pour ma situation. Voici la capture d'écran de ce que je veux faire;

enter image description here

51
serhat sezer

Voici ma solution:

self.tableView.separatorColor = self.tableView.backgroundColor

 @xxtesaxx, you should have a real test

13
Brook

Après avoir inspecté la hiérarchie des vues, il semble que chaque UITableViewCell ne possède que trois sous-vues: la vue de contenu (UITableViewCellContentView) et deux vues de séparation (_UITableViewCellSeparatorView). Je ne suis pas un fan de l'instanciation dynamique de classe de NSStrings (et Apple non plus ????). Cependant, étant donné que la contentView d'une UITableViewCell est accessible sans utiliser d'API privée, la solution s'avère assez simple.

L'idée est simplement de parcourir les sous-vues de votre UITableViewCell et de supprimer toutes les vues qui ne sont pas la contentView:

func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    let subviews = cell.subviews
    if subviews.count >= 3 {
        for subview in subviews {
            if subview != cell.contentView {
                subview.removeFromSuperview()
                break
            }
        }
    }
}

tableView(:willDisplayCell:forRowAtIndexPath:) est appelé plusieurs fois lors du rendu de la vue table. Par conséquent, la procédure ci-dessus garde trace de l'état en vérifiant le nombre de sous-vues de la cellule. S'il comporte trois sous-vues, les deux séparateurs sont toujours intacts. En outre, il supprime uniquement l'un des séparateurs, mais vous pouvez supprimer les deux en supprimant la variable break. Vous pouvez également spécifier si vous souhaitez supprimer le séparateur supérieur ou inférieur en vérifiant le cadre de la sous-vue. Si l'origine de l'axe des y de l'image est 0, c'est le séparateur supérieur. Si ce n'est pas 0, c'est le fond.

J'espère que cela t'aides!

Mise à jour de Swift 4, Swift 4.2:

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    let subviews = cell.subviews
    guard subviews.count >= 3 else {
        return
    }

    for subview in subviews where NSStringFromClass(subview.classForCoder) == "_UITableViewCellSeparatorView" {
        subview.removeFromSuperview()
    }
}
9
Dan Loewenherz

Vous pouvez supprimer des séparateurs même dans UITableView groupé avec une cellule statique:

class Cell: UITableViewCell {

override func layoutSubviews() {
    super.layoutSubviews()
    for view in subviews where view != contentView {
        view.removeFromSuperview()
    }
}
8
morizotter

Même en 2018, Google sert cette page comme premier résultat de cette question. Je n'ai eu aucune chance dans iOS 11 avec l'une des réponses fournies, alors voici ce que je suis venu avec:

extension UITableViewCell {
    func removeSectionSeparators() {
        for subview in subviews {
            if subview != contentView && subview.frame.width == frame.width {
                subview.removeFromSuperview()
            }
        }
    }
}

L'appel de .removeSectionSeparators () sur n'importe quelle instance UITableViewCell résoudra le problème. Dans mon cas au moins, les séparateurs de section sont les seuls avec la même largeur que la cellule elle-même (les autres sont tous en retrait).

La seule question qui reste est de savoir comment nous devrions l'appeler. On pourrait penser que willDisplayCell serait le meilleur choix, mais j'ai découvert que l'appel initial avait lieu avant que les vues de séparation ne soient générées, donc pas de dés.

J'ai fini par mettre cela dans ma méthode cellForRowAtIndexPath juste avant de retourner une cellule rechargée:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "MyReusableIdentifier", for: indexPath)

    Timer.scheduledTimer(withTimeInterval: 0.15, repeats: false) { (timer) in
        cell.removeSectionSeparators()
    }

    return cell
}

Cela ne me semble pas si élégant, mais je n’ai encore rencontré aucun problème.

EDIT: On dirait que nous avons aussi besoin de ça (pour les cellules réutilisées):

override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    cell.removeSectionSeparators()
}

Voici un avant/après dans les screenshots avec ce code:

Avant Before Separator Removal

Après After Separator Removal

7
cook

Je viens juste de trouver une solution car la cellule a contentView qui est une UIView, je pense donc que vous pouvez vous concentrer sur le résultat inférieur de contentView

Voici mon code: 

d'abord, vous devez faire le séparateur pour effacer 

tableView.separatorColor = UIColor.clear

Deuxièmement, dans la fonction cellForRowAt:

let bottomBorder = CALayer()

bottomBorder.frame = CGRect(x: 0.0, y: 43.0, width: cell.contentView.frame.size.width, height: 1.0)
bottomBorder.backgroundColor = UIColor(white: 0.8, alpha: 1.0).cgColor
cell.contentView.layer.addSublayer(bottomBorder)

ici, vous verrez l'interface utilisateur comme ceci:

 enter image description here

4
Qi Lee

C’est une question très ancienne, mais c’est l’une des premières entrées de Google lorsqu’on cherche à savoir comment supprimer les séparateurs supérieur et inférieur de chaque section. 

Après une enquête, j'ai découvert qu'il n'y avait aucun moyen ni aucune intention d'Apple de faire en sorte que cela se produise d'une manière ou d'une autre sans complication stupide de la hiérarchie des points de vue.

Heureusement, il existe un moyen absolument simple et facile d'obtenir un tel look:

 enter image description here

Je dis simple mais pour un débutant, cela pourrait être difficile en raison d’un manque de compréhension de la manière dont fonctionne UITableView et de la mise en oeuvre de vos propres cellules. Laissez-moi essayer de l'expliquer:

  1. Créer une sous-classe UITableViewCell
  2. Dans votre cellule, créez une propriété @IBOutlet weak var separatorView: UIView!
  3. Dans votre Storyboard, sélectionnez la cellule tableview et sélectionnez votre propre cellule en tant que classe qui sauvegarde la cellule. Note: vous n'avez pas devez utiliser un style personnalisé. Vous pouvez toujours utiliser Basic, Subtitle, etc.
  4. Définissez votre UITableViews Separator Style sur None pour masquer le séparateur par défaut
  5. Faites glisser une UIView sur votre cellule et redimensionnez-la afin qu'elle se trouve en bas (ou en haut) de la cellule. Utilisez le Size Inspectors Autoresizing pour le fixer au début/à la fin/en bas et donnez-lui une largeur de flex (ou Autolayout mais c'est juste au-dessus dans le cas présent)
  6. Connectez la vue à la sortie de votre classe de cellules
  7. Dans votre UITableViewDataSources cellForRowAtIndexPath:, définissez la propriété isHidden de votre séparateur personnalisé selon que le indexPath.row est la dernière ligne (ou la première, si votre vue se trouve en haut) de la section.

Voici un exemple de code:

class MyCell: UITableViewCell {
    @IBOutlet weak var separatorView: UIView!
}

class ViewController: UITableViewController {


    override func numberOfSections(in tableView: UITableView) -> Int {
        return 3
    }
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 3
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! MyCell
        cell.separatorView.isHidden = indexPath.row == 2
        return cell
    }

}

Et voici quelques captures d'écran:

 enter image description here

 enter image description here

 enter image description here

 enter image description here

Oui, c'est du travail, mais il n'y a pas moyen de faire quelque chose de gratuit lors du codage. En fin de compte, nous sommes des programmeurs et c'est à nous de faire le codage. Il est toujours préférable de passer les 5 à 10 minutes à configurer ceci plutôt que de simplement coller du code hacky qui pourrait ne pas continuer à fonctionner à l'avenir lorsque Apple décidera de modifier la hiérarchie des vues. 

En fait, cette réponse nécessitait plus de travail que la mise en œuvre du séparateur. Moi aussi, je cherchais une solution facile et rapide, mais au final, il n’en restait pas une assez bonne qui, à mon avis, valait la peine d’être utilisée. 

J'espère que vous vous sentez également sceptique lorsque vous voyez des boucles répétées itérer sur des sous-vues de cellules pour masquer ou même supprimer des vues au moment de l'exécution de la hiérarchie des vues fournie par Apple, lorsqu'il existe une solution simple, polyvalente, stable et évolutive . 7 petites étapes suffisent vraiment et elles sont faciles à comprendre.

4
xxtesaxx

Voici ce que j'ai finalement trouvé:

 enter image description here

Je n'ai pas été en mesure de trouver un meilleur moyen que celui-ci. Mais cela fonctionne beaucoup pour moi. Dernière tentative avec Xcode Version 7.3.1 (7D1014). Cette procédure a été réalisée via le storyboard. 

Fondamentalement, j'ajoute une vue UIView de 0,5 pt de hauteur sur UITableViewCell, puis une couleur d'arrière-plan pour cette vue UIView. Définissez le séparateur de UITableView parent sur Aucun. 

Voici les détails:

En considérant que vous avez déjà défini votre UITableViewCell, custom ou default. À la toute première étape, définissez le séparateur de UITableView sur Aucun.

 enter image description here

Ensuite, ajoutez une vue UIV de 1 pt de hauteur et définissez le fond comme vous le souhaitez. Dans mon cas, il s'agit du rouge.

 enter image description here

 enter image description here

Commencez à définir les contraintes. Le problème est de définir la hauteur de UIView à 0.5 pt. C'est le seul problème qui pose problème pour ce flux de travail.

UIView avec 0,5 pt de hauteur:

Partage de la manière de définir une hauteur de 0,5 pt de UIView.

D'abord (1) épinglez la vue puis (2) définissez la hauteur sur 0.5. Appuyez sur Entrée.

 enter image description here

Enfin, votre UIView ressemblera à ce qui suit.

 enter image description here

Je n'ai pas pu régler la hauteur à 0,5 autrement que de cette façon.

3
Shad

Voici la solution. Ceci est pour les cellules statiques. Si vous voulez dynamique, il suffit de réécrire "count". J'espère que ça aide.

extension NSObject {
   var theClassName: String {
       return    NSStringFromClass(self.dynamicType).componentsSeparatedByString(".").last!
   }
}

override func viewDidLoad() {
    super.viewDidLoad()
    tableView.separatorStyle = .None
}
override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    let count = tableView.numberOfRowsInSection(indexPath.section)
    if ( indexPath.row != count - 1 ) {
        for view in cell.subviews {
            if view.theClassName == "_UITableViewCellSeparatorView" {
                view.backgroundColor = UIColors.redColor()
            }
        }
    }
}
2
onemanstartup

Essayé diverses solutions basées sur la solution de contournement cell.separatorInset = UIEdgeInsetsMake(), aucune d’entre elles ne fonctionnant correctement.

Pour mon projet iOS11 UITableViewStyleGrouped, cela s’est avéré efficace:

self.tableView.separatorColor = self.tableView.backgroundColor;
1
Art

Basé sur la réponse du cuisinier, mais sans minuterie:

override func didAddSubview(_ subview: UIView) {
    super.didAddSubview(subview)
    if NSStringFromClass(subview.classForCoder) != "UITableViewCellContentView" && subview.frame.width == frame.width {
        subview.removeFromSuperview()
    }
}

Ajoutez simplement ceci dans la sous-classe d'une cellule et vous n'avez besoin de rien d'autre. Fonctionne sur iOS 12.

1
Andrii Liakh

Essayez ceci, il supprimera la ligne de séparation supérieure. 

-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if(indexPath.row == 0 && indexPath.section == 0) {
        for (UIView *view in  cell.subviews) {
            if ([NSStringFromClass([view class]) containsString:@"CellSeparator"]) {
                if (view.frame.Origin.y == 0 && CGRectGetHeight(view.frame) < 1.01 ) { //Hide first UITableViewCellSeparatorView
                    NSLog(@"%s Remove View From Cell[Section:0 Row:0] for top border [%@]:%@",__FUNCTION__,NSStringFromClass([view class]),view);
                    view.hidden = YES; //Hide
                }
            }
        }
    }
}
0
TARANG GHORI

Pour supprimer les parties supérieure et inférieure de la ligne de séparation pour chaque section. Ajoutez ceci à votre cellule statique.

override func layoutSubviews() {
    super.layoutSubviews()

    //Get the width of tableview
    let width = subviews[0].frame.width

    for view in subviews where view != contentView {
        //for top and bottom separator will be same width with the tableview width
        //so we check at here and remove accordingly
        if view.frame.width == width {
            view.removeFromSuperview()
        }
    }
}

Résultat comme ci-dessous image

 enter image description here

0
titan

Vous pouvez accéder à la vue en utilisant

override func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {

    let header = view as! UITableViewHeaderFooterView 
    header.backgroundView . .....
0

J'ai eu un problème similaire, où j'avais un Groupable UITableView avec des cellules personnalisées, tous conçus avec Interface Build en tant que fichiers .xib. Les cellules avaient des fonds blancs, supprimaient les séparateurs par défaut et ajoutaient les miens. J'avais aussi des vues d'en-tête personnalisées pour chaque section. Je règle la hauteur de ces vues d'en-tête à 44 (peut être n'importe quoi ...). Il y avait une vue en hauteur de 1 point entre mes sections, ce qui semblait bizarre. Apparemment, le système ajoute une vue d’arrière-plan claire entre les sections, même si nous spécifions une hauteur personnalisée, disons 44, et que la vue en-tête personnalisée que nous renvoyons a un blanc (ou une couleur d’arrière-plan concrète). La couleur que nous voyons derrière cette vue dégagée est en réalité la couleur de l'arrière-plan de la vue Tableau. Dans mon cas, les vues de tableau et les cellules devaient être de couleur blanche et définir le fond de la vue de table en blanc résolvait le problème (au moins visuellement, mais c'est ce que je voulais quand même). La deuxième solution consisterait à conserver le style de la vue Table à l’unis, mais à implémenter la méthode de délégué UITableView pour renvoyer 2 sections ou plus, et à créer également des en-têtes personnalisés, le cas échéant. Mais cela fera que les vues d’en-tête resteront collées au sommet pendant un certain temps (lors du défilement), jusqu’à ce que la vue d’en-tête de la section suivante se rapproche de celle-ci, puis elle commence à remonter aussi peut être un moyen facile de résoudre ce problème, pas sûr cependant).

0
ppalancica