Separatore di iOS 8 UITableView 0 non funzionante




15 Answers

Arg !!! Dopo averlo giocato, esegui questa operazione nella sottoclasse Cell :

- (UIEdgeInsets)layoutMargins
{
    return UIEdgeInsetsZero;
}

o impostando il file cell.layoutMargins = UIEdgeInsetsZero; risolto per me.

ios objective-c swift uitableview ios8

Ho un'app in cui il separatore di UITableView è impostato su valori personalizzati - Destra 0 , Sinistra 0 . Funziona perfettamente su iOS 7.x , tuttavia in iOS 8.0 vedo che il separatore è impostato sul valore predefinito di 15 sulla destra. Anche se nei file xib è impostato su 0 , viene comunque visualizzato in modo errato.

Come rimuovere i margini del separatore di UITableViewCell ?




Credo che questa sia la stessa domanda che ho posto qui: Rimuovi SeparatorInset su iOS 8 UITableView per XCode 6 iPhone Simulator

In iOS 8 , c'è una nuova proprietà per tutti gli oggetti ereditati da UIView . Pertanto, la soluzione per impostare SeparatorInset in iOS 7.x non sarà in grado di rimuovere lo spazio bianco visualizzato su UITableView in iOS 8.

La nuova proprietà si chiama " 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

La soluzione:-

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

Se imposti cell.layoutMargins = UIEdgeInsetsZero; senza verificare se esiste il layoutMargins , l'app si bloccherà su iOS 7.x. Quindi, il modo migliore sarebbe controllare se il layoutMargins esiste prima di setLayoutMargins:UIEdgeInsetsZero .




Versione rapida

iOS introduce la proprietà layoutMargins su celle E viste tabella.

Questa proprietà non è disponibile in iOS 7.0, quindi è necessario assicurarsi di controllare prima di assegnarlo!

Tuttavia, Apple ha aggiunto una proprietà chiamata preservesSuperviewLayoutMargins alla tua cella che impedirà di ereditare le impostazioni dei margini della tua Vista tabella. In questo modo, le tue celle possono configurare i propri margini indipendentemente dalla vista tabella. Pensalo come un override.

Questa proprietà si chiama preservesSuperviewLayoutMargins e impostandola su NO può consentire di ignorare le impostazioni di layoutMargin della Vista tabella con l'impostazione di layout del mouse della propria cella. Risparmia tempo ( non è necessario modificare le impostazioni della Vista tabella ) ed è più conciso. Si prega di fare riferimento alla risposta di Mike Abdullah per una spiegazione dettagliata.

NOTA: questa è l'implementazione corretta e meno disordinata, come espresso nella risposta di Mike Abdullah; impostazione delle preservazioni della cellaSuperviewLayoutMargins = NO garantisce che la vista tabella non sostituisca le impostazioni della cella.

Primo passo: imposta i margini della tua cella:

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

L'impostazione della proprietà preservesSuperviewLayoutMargins sulla tua cella su NO dovrebbe impedire alla vista tabella di ignorare i margini della cella. In alcuni casi, sembra non funzionare correttamente.

Secondo passaggio: solo se tutto fallisce, puoi forzare la forza bruta sui margini della vista tabella:

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

... e ci sei! Questo dovrebbe funzionare su iOS 8 e iOS 7.

Nota: testato usando iOS 8.1 e 7.1, nel mio caso ho solo dovuto usare il primo passo di questa spiegazione.

Il Secondo Passo è richiesto solo se hai una cella non popolata sotto le celle renderizzate, es. se la tabella è più grande del numero di righe nel modello di tabella. Se non si esegue la seconda fase, si otterrebbero offset di separatori diversi.




Per iOS 9 è necessario aggiungere:

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

Per maggiori dettagli si prega di fare riferimento alla question .




Swift:

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
}



Per quanto riguarda il suggerimento di cdstamper al posto della vista tabella, l'aggiunta delle righe sottostanti nel metodo layoutSubview della cella funziona per me.

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



Dopo molte indagini ...

Ecco l'unico modo per controllare completamente questa roba (che potrei trovare)

Per controllare completamente entrambi i separatori e i margini di layout su ogni cella. Fai questo nel metodo willDisplayCell sul tuo 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'oggetto cella controlla il separatore e contentView controlla tutto il resto. Se i tuoi riquadri separatori sono mostrati in un colore inaspettato, questo dovrebbe risolverlo:

cell.backgroundColor = cell.contentView.backgroundColor



Per me la linea semplice ha fatto il lavoro

cell.layoutMargins = UIEdgeInsetsZero



Questo è il codice che funziona per me, in 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)
    }
}

Questo mi sembra il più pulito (per ora), poiché tutte le correzioni bordo / margine di cella / tabellaView vengono eseguite nella tableView:willDisplayCell:forRowAtIndexPath: metodo, senza dover inserire codice non necessario in tableView:cellForRowAtIndexPath:

A proposito, sto solo impostando il separatore di sinistra della cellaInset / layoutMargins, perché in questo caso non voglio rovinare i miei vincoli che ho impostato nella mia cella.

Codice aggiornato a 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)
        }
    }



Utilizzare lo snippet di codice seguente per evitare problemi di padding indesiderati per UITableView in IOS 8 e 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];
    }
}



Lukasz risponde in 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
    }



Ecco un modo semplice per rimuovere globalmente l'inserto.

In UITableViewCell+Extensions.swift :

import UIKit

extension UITableViewCell {

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

}

Nell'applicazione AppDelegate application:didFinishLaunchingWithOptions: ::

  UITableViewCell.appearance().separatorInset = UIEdgeInsetsZero

Si potrebbe pensare a a) anche solo sovrascrivere separatorInset nell'estensione, oppure b) impostare invece il proxy dell'aspetto per layoutMargins . Neanche funzionerà. Anche se separatorInset è indicato come proprietà, il tentativo di sovrascriverlo come una proprietà (o metodo) genera errori del compilatore. Inoltre, l'impostazione del proxy dell'aspetto per layoutMargins UITableView (o anche per l'impostazione dei proxy di aspetto per layoutMargins e separatorInset UITableView ) non ha alcun effetto.




Dopo aver visto le risposte al terzo piano, ho cercato di capire quale fosse il rapporto tra l'impostazione del separatore tra TableView e TableViewCell e fatto qualche test. Ecco le mie conclusioni:

  1. possiamo considerare che l'impostazione del separatore della cella a zero deve spostare il separatore in due passaggi: il primo passo è impostare il separatorinset della cella su zero. il secondo passo è quello di impostare il marginlayout della cella a zero.

  2. imposta il separatorinset di TableView e marginlayout può influenzare il separatorinset della cella. Tuttavia, dal test, ho trovato che il separatorinset del TableView sembra essere inutile, marginlayout di TableView può effettivamente influenzare marginlayout della cella.

  3. set Cell's PreservesSuperviewLayoutMargins = false, può tagliare l'effetto marginlayout di TableView su Cells.

  4. una delle soluzioni:

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



In un modo più compatto rispetto alla risposta più votata ...

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

}




Questo ha funzionato perfettamente per me su iOS 8 e iOS 9.

Per 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;
    }





Related