Come nascondere la prima intestazione di sezione in UITableView (stile raggruppato)


108

Poiché il design delle viste tabella che utilizzano lo stile raggruppato è cambiato notevolmente con iOS 7, vorrei nascondere (o rimuovere) la prima intestazione di sezione. Finora non sono riuscito a raggiungerlo.

Un po 'semplificato, il mio codice ha questo aspetto:

- (CGFloat) tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    if (section == 0)
        return 0.0f;
    return 32.0f;
}

- (UIView*) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    if (section == 0) {
        UIView* view = [[UIView alloc] initWithFrame: CGRectMake(0.0f, 0.0f, 640.0f, 0.0f)];
        return view;
    }
    return nil;
}

- (NSString*) tableView:(UITableView *) tableView titleForHeaderInSection:(NSInteger)section
{
    if (section == 0) {
        return nil;
    } else {
        // return some string here ...
    }
}

Se restituisco un'altezza di 0, gli altri due metodi non verranno mai chiamati con l'indice di sezione 0. Tuttavia, un'intestazione di sezione vuota viene ancora disegnata con l'altezza predefinita. (In iOS 6, vengono chiamati i due metodi. Tuttavia, il risultato visibile è lo stesso.)

Se restituisco un valore diverso, l'intestazione della sezione ottiene l'altezza specificata.

Se restituisco 0,01, è quasi corretto. Tuttavia, quando attivo "Colore immagini disallineate" nel simulatore, contrassegna tutte le celle della vista tabella (che sembra essere una conseguenza logica).

Le risposte alla domanda UITableView: nascondi intestazione dalla sezione vuota sembrano indicare che alcune persone sono riuscite a nascondere l'intestazione della sezione. Ma potrebbe applicarsi allo stile semplice (invece di quello raggruppato).

Il miglior compromesso finora è restituire l'altezza 0,5, risultando in una linea leggermente più spessa sotto la barra di navigazione. Tuttavia, apprezzerei se qualcuno sapesse come nascondere completamente l'intestazione della prima sezione.

Aggiornare

Secondo l' analisi di caglar ( https://stackoverflow.com/a/19056823/413337 ), il problema sorge solo se la visualizzazione tabella è contenuta in un controller di navigazione.


Non ho capito quella parte => if (section == 0) return view; ritorno nullo; cioè restituendo una vista quando è la prima sezione e nullo altrimenti?
Zen,

L'idea è di restituire una vista con un'altezza di 0 per la prima sezione e restituire zero per tutte le altre sezioni in modo che la vista tabella utilizzi la vista intestazione predefinita per esse. La parte nulla funziona bene; la vista tabella mostra un'intestazione per queste sezioni. Ma la parte per la sezione 0 è irrilevante perché il metodo non viene mai chiamato con section == 0.
Codo

1
Questa risposta sembra essere breve e dolce. stackoverflow.com/a/23955420/3965
Mr Rogers

Risposte:


154

Ho una soluzione alternativa che mi sembra ragionevolmente pulita. Quindi sto rispondendo alla mia stessa domanda.

Poiché 0 poiché l'altezza della prima intestazione di sezione non funziona, ritorno 1. Quindi utilizzo contentInset per nascondere l'altezza sotto la barra di navigazione.

Objective-C:

- (CGFloat) tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    if (section == 0)
            return 1.0f;
    return 32.0f;
}

- (NSString*) tableView:(UITableView *) tableView titleForHeaderInSection:(NSInteger)section
{
    if (section == 0) {
        return nil;
    } else {
        // return some string here ...
    }
}

- (void) viewDidLoad
{
    [super viewDidLoad];

     self.tableView.contentInset = UIEdgeInsetsMake(-1.0f, 0.0f, 0.0f, 0.0);
}

Swift:

override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return section == 0 ? 1.0 : 32
}

override func viewDidLoad() {
    super.viewDidLoad()

    tableView.contentInset = UIEdgeInsets(top: -1, left: 0, bottom: 0, right: 0)
}

6
Usare un'altezza dell'intestazione di 0.1f è ancora meglio per nasconderlo.
Chuck Krutsinger

4
Ho provato a usare 0.1f. Ma il risultato è che i disegni non sono più allineati ai pixel, causando sfocature e riducendo le prestazioni. Provalo nel simulatore: ha un'opzione per evidenziare l'allineamento problematico.
Codo

31
In realtà, una migliore implementazione (meno probabile che si interrompa in futuro) è quella di utilizzare CGFLOAT_MINinvece di un valore hardcoded. In altre parole, non farlo return 1.0fo 0.1finvece, return CGFLOAT_MINse Apple cambia mai il valore minimo accettabile, avrai del codice da modificare se codifichi il valore restituito. Inoltre, non sai già se stai utilizzando il valore più piccolo possibile. Utilizzando la costante definita, hai la garanzia di utilizzare il valore più piccolo possibile e il tuo codice sopravviverà alle modifiche del sistema operativo.
Chris Ostmo

11
@ Chris: temo che non ti sia venuta l'idea. Non restituisco un valore molto piccolo ma un multiplo della dimensione di un pixel in modo che il disegno rimanga allineato ai pixel (per buone prestazioni e nitidezza). L'ho quindi compensato utilizzando il riquadro del contenuto. È improbabile che ciò cambi in futuro poiché si tratta di una distanza visibile e considerevole e non qualcosa che il sistema operativo potrebbe ignorare.
Codo

8
+1 Per non utilizzare valori pixel frazionari come offset dell'interfaccia utente.
Ricardo Sanchez-Saez

52

Ecco come nascondere la prima intestazione di sezione in UITableView (stile raggruppato).

Soluzione Swift 3.0 e Xcode 8.0

  1. Il delegato di TableView dovrebbe implementare il metodo heightForHeaderInSection

  2. All'interno del metodo heightForHeaderInSection, restituisci il numero meno positivo. (non zero!)

    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    
        let headerHeight: CGFloat
    
        switch section {
        case 0:
            // hide the header
            headerHeight = CGFloat.leastNonzeroMagnitude
        default:
            headerHeight = 21
        }
    
        return headerHeight
    }

6
restituire CGFloat.leastNonzeroMagnitude invece di 0 mi ha aiutato. Grazie!
anoo_radha

Risposta perfetta, grazie
Pierre

Tra l'altro, CGFLOAT_MINper objc è identico CGFloat.leastNonzeroMagnitudea Swift
DawnSong

36

La risposta è stata molto divertente per me e il mio team e ha funzionato a meraviglia

  • In Interface Builder, sposta la vista tabella sotto un'altra vista nella gerarchia della vista.

MOTIVO:

Abbiamo osservato che ciò accade solo per la prima visualizzazione nella gerarchia di visualizzazioni, se questa prima visualizzazione è una UITableView . Quindi, tutte le altre UITableViews simili non hanno questa sezione fastidiosa, tranne la prima. Abbiamo provato a spostare UITableView fuori dal primo posto nella gerarchia di visualizzazione e tutto funzionava come previsto.


1
Hai ancora l'effetto vetro smerigliato della barra di navigazione quando scorri la visualizzazione tabella?
Codo

Avrai questo effetto di sfocatura quando imposterai di conseguenza il tuo tableView. Ad esempio, dovresti impostare contentInsetsu per {0, 64, 0, 0}avere un offset di 64px dall'alto (barra di stato più barra di navigazione). La tableView deve essere attaccata nella parte superiore dello schermo, non la topLayoutGuide (per farla raggiungere sotto la barra di navigazione)
Julian F. Weinert

Se non stai usando pull per aggiornare, questo andrebbe bene.
Michael

2
Wow. Questo ha funzionato per me in iOS 9 e mi ha lasciato senza fiato.
assegnare il

Questa dovrebbe essere la risposta accettata. Un bug così strano!
Oded Harth

25

Usa questo trucco per il tipo raggruppato tableView

Copia incolla sotto il codice per la visualizzazione della tabella nel metodo viewDidLoad :

tableView.tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, tableView.bounds.size.width, 0.01f)];

Non l'ho provato ma sospetto che questa soluzione abbia lo stesso svantaggio di alcune delle altre soluzioni proposte: i disegni non sono più allineati ai pixel, causando sfocature e riducendo le prestazioni. Il simulatore può rivelarlo: ha un'opzione per evidenziare l'allineamento problematico. Tuttavia, se viene arrotondato per difetto a 0, allora è davvero una bella soluzione.
Codo

Sì, immagino che venga arrotondato per difetto a 0. Perché l'ho usato molte volte, ma non ho trovato sfocature nei disegni.
Nitesh Borad

TableHeaderView e vista di intestazione di sezione? qual è la differenza,
AsifHabib

O leggermente più corta: _tableView.tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 1)].
Mojuba

@ AsifHabib: tableHeaderView è posto in cima a tutti gli elementi della tabella. È la visualizzazione dell'intestazione per la tabella stessa. E la vista dell'intestazione della sezione deve essere posizionata su ciascuna sezione. Possono esserci molte viste di intestazione di sezione in base al numero di sezioni specificato nella tabella. Ma ci sarà solo una vista dell'intestazione della tabella.
Nitesh Borad,

21

in questo modo va bene.

override func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    if section == 0 {
        return CGFloat.min
    }
    return 25
}

override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    if section == 0 {
        return nil
    }else {
        ...
    }
}

2
Questa è una bella variazione della mia soluzione tranne che utilizza valori frazionari. In questo modo, il testo e le immagini non sono più allineati ai pixel, il disegno viene rallentato e il risultato può diventare sfocato. Il simulatore ha l'opzione "Colore immagini disallineate" per rivelare questo problema.
Codo

Funziona perfettamente per le persone come me che usano celle statiche con containerView
thibaut noah

3
Swift 3> "CGFloat.min" è stato rinominato "CGFloat.leastNormalMagnitude"
rjobidon

6

Ho appena copiato il tuo codice e ho provato. Funziona normalmente (provato nel simulatore). Ho allegato la visualizzazione dei risultati. Vuoi una tale vista, giusto? O ho frainteso il tuo problema?

inserisci qui la descrizione dell'immagine


1
Sì, è fondamentalmente quello che voglio, tranne per il fatto che la mia vista tabella è in un controller di navigazione. Potrebbe fare la differenza?
Codo

2
Ho aggiunto tableView al controller di navigazione e la tua situazione appare :) Penso che in iOS 7, questa correzione dell'altezza dell'intestazione per impostazione predefinita nella vista tabella in stile raggruppato. Modificando il frame di tableView, la prima vista dell'intestazione potrebbe essere nascosta (come set x = 0 y = -40). Tuttavia, so che questa soluzione non è una buona soluzione.
caglar

1
Grazie mille per il tuo lavoro. Quindi sembra che il problema sorga solo se la vista tabella utilizza lo stile raggruppato ed è contenuta all'interno di un controller di navigazione.
Codo

Cercando di passare da viewcontroller a tableviewcontroller non sono riuscito a risolvere il problema con l'intestazione. Forse mi manca qualcosa cercando di convertirlo. (iOS 7.0.3 sim)
Evgeni Petrov

1
Questo problema compare anche in questa istantanea! la cella 0 non inizia da x: 0.0f & y: 0.0f.
Burhanuddin Sunelwala

6

Swift3: heightForHeaderInSection funziona con 0, devi solo assicurarti che l'intestazione sia impostata su clipsToBounds.

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
       return 0
}

se non imposti clipsToBounds, l'intestazione nascosta sarà visibile durante lo scorrimento.

func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
    guard let header = view as? UITableViewHeaderFooterView else { return }

    header.clipsToBounds = true
}

1
clipsToBound = true è molto importante se prevedi di nascondere completamente la vista dell'intestazione di sezione. L'impostazione della sua altezza su 0 / CGFLOAT_MIN non è sufficiente.
Altimac

5

Aggiornamento [19/09/17]: la vecchia risposta non funziona più per me in iOS 11. Grazie Apple. Quanto segue ha fatto:

self.tableView.sectionHeaderHeight = UITableViewAutomaticDimension;
self.tableView.estimatedSectionHeaderHeight = 20.0f;
self.tableView.contentInset = UIEdgeInsetsMake(-18.0, 0.0f, 0.0f, 0.0);

Risposta precedente:

Come pubblicato nei commenti di Chris Ostomo, per me ha funzionato quanto segue:

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    return CGFLOAT_MIN; // to get rid of empty section header
}

Sospetto che il contenuto della visualizzazione tabella non sia più allineato ai pixel, causando sfocature e riducendo le prestazioni. Il simulatore può rivelarlo: ha un'opzione per evidenziare l'allineamento problematico. Tuttavia, se viene arrotondato per difetto a 0, allora è davvero una bella soluzione.
Codo

No, non ho notato problemi con i contenuti. I vincoli sembravano a posto.
Manindra Moharana

1
Welp! Non funziona più in iOS 11! La mia correzione è durata meno di una settimana .. 😞
Manindra Moharana

4

Ecco come sbarazzarsi dell'intestazione della sezione superiore in un UITableView raggruppato, in Swift:

tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: CGFloat.leastNormalMagnitude))

3

In Swift 4.2 e molte versioni precedenti, invece di impostare l'altezza della prima intestazione su 0 come nelle altre risposte, puoi semplicemente impostare le altre intestazioni su nil. Supponiamo che tu abbia due sezioni e desideri che solo la seconda (cioè 1) abbia un'intestazione. Quell'intestazione avrà il testo Foobar :

override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    return section == 1 ? "Foobar" : nil
}

3

Prova questo se desideri rimuovere completamente tutte le intestazioni di sezione

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return CGFloat.leastNormalMagnitude
}

func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
    return CGFloat.leastNormalMagnitude
}

Questo è solo quello che mi serve. Una soluzione semplice e facile. 1+
iGhost

0

Non posso ancora commentare, ma ho pensato di aggiungere che se hai un UISearchControllersul tuo controller con UISearchBarcome tuo tableHeaderView, l'impostazione dell'altezza della prima sezione come 0 in heightForHeaderInSectionfunziona davvero.

Uso in self.tableView.contentOffset = CGPointMake(0, self.searchController.searchBar.frame.size.height);modo che la barra di ricerca sia nascosta per impostazione predefinita.

Il risultato è che non c'è un'intestazione per la prima sezione e scorrendo verso il basso verrà mostrata la barra di ricerca proprio sopra la prima riga.


0

più semplice è di gran lunga per tornare nil, o ""in func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String?una sezione in cui non si desidera visualizzare nell'intestazione.


0

Versione Swift: Swift 5.1
Per lo più, puoi impostare l'altezza in tableView delegate in questo modo:

func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
   return UIView(frame: CGRect(x: 0, y: 0, width: view.width, height: CGFloat.leastNormalMagnitude))
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
   return CGFloat.leastNormalMagnitude
}

A volte, quando hai creato UITableView con Xib o Storyboard, la risposta di up non funziona. puoi provare la seconda soluzione:

let headerView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: CGFloat.leastNormalMagnitude))
self.tableView.tableHeaderView = headerView

Spero che funzioni per te!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.