Modifica comportamento scorrimento predefinito dell'intestazione della sezione UITableView


147

Ho un UITableView con due sezioni. È una semplice vista da tavolo. Sto usando viewForHeaderInSection per creare viste personalizzate per queste intestazioni. Fin qui tutto bene.

Il comportamento di scorrimento predefinito è che quando si incontra una sezione, l'intestazione della sezione rimane ancorata sotto la barra di navigazione, fino a quando la sezione successiva scorre in vista.

La mia domanda è questa: posso modificare il comportamento predefinito in modo che le intestazioni di sezione NON rimangano ancorate in alto, ma piuttosto, scorrere sotto la barra di navigazione con il resto delle righe di sezione?

Mi sto perdendo qualcosa di ovvio?

Grazie.


1
Questa deve essere una delle migliori domande scritte su questo sito! :) Grazie.
Fattie,

1
Controlla qui per il modo giusto per ottenere questo effetto stackoverflow.com/a/13735238/1880899
Sumit Anantwar

Risposte:


175

Il modo in cui ho risolto questo problema è di regolare il contentOffsetsecondo contentInsetin UITableViewControllerDelegate(estende UIScrollViewDelegate) in questo modo:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
       CGFloat sectionHeaderHeight = 40;
   if (scrollView.contentOffset.y<=sectionHeaderHeight&&scrollView.contentOffset.y>=0) {
       scrollView.contentInset = UIEdgeInsetsMake(-scrollView.contentOffset.y, 0, 0, 0);
   } else if (scrollView.contentOffset.y>=sectionHeaderHeight) {
       scrollView.contentInset = UIEdgeInsetsMake(-sectionHeaderHeight, 0, 0, 0);
   }
}

L'unico problema qui è che perde un po 'di rimbalzo quando si scorre verso l'alto.


{NOTA: "40" dovrebbe essere l'altezza esatta dell'intestazione TUA sezione 0. Se usi un numero maggiore dell'altezza dell'intestazione della sezione 0, vedrai che la sensazione del dito è influenzata (prova come "1000" e vedrai che il comportamento di rimbalzo è un po 'strano nella parte superiore). se il numero corrisponde all'altezza dell'intestazione della sezione 0, la sensazione del dito sembra essere perfetta o quasi perfetta.}


1
Soluzione perfetta di quella sopra.
prathumca,

4
Grazie! Questa è una soluzione perfetta Hai la soluzione per il piè di pagina della sezione?
Tuan Nguyen l'

12
Questa soluzione non gestisce correttamente la barra dei menu, che dovrebbe scorrere in cima all'elenco.
Reid Ellis,

se hai bisogno dello stesso comportamento per la vista piè di pagina della sezione, modifica l'ultima riga in questo modo: scrollView.contentInset = UIEdgeInsetsMake (0, 0, sectionHeaderHeight, 0)
alex

Questo sembra essere abbastanza: scrollView.contentInset = UIEdgeInsetsMake (scrollView.contentOffset.y> = 0? -ScrollView.contentOffset.y: 0, 0, 0, 0);
MacMark,

85

Puoi anche aggiungere una sezione con zero righe nella parte superiore e utilizzare semplicemente il piè di pagina della sezione precedente come intestazione per la successiva.


13
Nel mio caso in cui ho più di 2 sezioni, il piè di pagina si ancorerà in fondo.
Joseph Lin,

3
Questo è creativo ma è necessario regolare indexPath se si utilizza un NSFetchedResultsController per caricare la tabella.
XJones,

+1 di gran lunga la soluzione MIGLIORE - mi ci sono volute 3 linee per implementare!
Jon,

Brilliant Brilliant Brilliant :-)
iphonic

Come funzionerebbe per il footer che si fissa? Gradirei un aiuto! Grazie
darwindeeds

36

Se lo facessi, approfitterei del fatto che UITableViews in stile Plain ha le intestazioni appiccicose e quelle in stile Grouped no. Probabilmente proverei almeno a usare una cella di tabella personalizzata per imitare l'aspetto di celle Plain in una tabella raggruppata.

In realtà non l'ho provato, quindi potrebbe non funzionare, ma è quello che consiglierei di fare.


Probabilmente funzionerebbe, ma è stato provato? E sembra un sacco di lavoro quando la risposta di @ voidStern funziona perfettamente !!
Bentford,

La risposta di voidStern non funziona per me quando ho più di due sezioni. La risposta di Colin è più semplice / più elegante, senza la necessità di spostare manualmente il numero di sezione e aggiungere il conteggio delle sezioni.
Joseph Lin,

Suggerimenti: utilizzare tableView.separatorColor = [UIColor clearColor];per imitare una vista tabella semplice.
Joseph Lin,

3
Ho provato a farlo, ma quando non sono riuscito a far sembrare le celle della tabella raggruppate come quelle semplici, ovvero rimuovere il margine sinistro e destro su entrambi i lati delle celle. Come lo hai fatto?
Adam Carter,

1
Grazie mille per aver chiarito le cose su UITableViewStyle, ovvero raggruppato e semplice, che decide se l'intestazione / piè di pagina della sezione di tableview sarà appiccicoso o meno. Grazie mille @Colin Barrett
Dhaval H. Nena,

28

So che arriva tardi, ma ho trovato la soluzione definitiva!

Quello che vuoi fare è se hai 10 sezioni, lascia che dataSource restituisca 20. Usa numeri pari per le intestazioni di sezione e numeri dispari per il contenuto della sezione. qualcosa come questo

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    if (section%2 == 0) {
        return 0;
    }else {
        return 5;
    }
}

-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    if (section%2 == 0) {
        return [NSString stringWithFormat:@"%i", section+1];
    }else {
        return nil;
    }
}

Ecco! : D


grande idea. ma se hai titoli di indice di sezione, sospetto che questo li rovinerà.
roocell,

perché? puoi fare lo stesso con i titoli delle sezioni. Basta ricordare zero per i numeri dispari e un titolo per il numero pari.
LocoMike,

1
Sì, questo metodo funziona alla grande. Era un sacco di contabilità (probabilmente ha a che fare con il modo in cui devo ottenere i titoli delle sezioni) Ma ha funzionato. Il trucco è che numberOfRowsInSection e cellForRowAtIndexPath usano if (sezione% 2! = 0 && section! = 0) mentre il titoloForHeaderInSection e le altre funzioni dell'indice di sezione usano if (sezione% 2 == 0)
roocell

l'originatore dovrebbe scegliere questo come risposta. Sarebbe bello se ci fosse un modo per sottoclassare uitableview per ancorare automaticamente i titoli delle sezioni.
roocell,

Questo ha funzionato al meglio per me. Ho provato prima la soluzione di @ Colin, ma non ha funzionato bene con la pesantemente personalizzata UITableViewche sto usando.
kubi,

15

Esistono diverse cose che è necessario fare per risolvere questo problema in modo non confuso:

  1. Impostare lo stile di visualizzazione della tabella su UITableViewStyleGrouped
  2. Impostare la vista tabella backgroundColorsu[UIColor clearColor]
  3. Impostare backgroundViewsu ogni cella della vista della tabella su una vista vuota conbackgroundColor [UIColor clearColor]
  4. Se necessario, impostare la vista tabella in modo rowHeightappropriato o sovrascrivere tableView:heightForRowAtIndexPath:se le singole file hanno altezze diverse.

(+1) @Neil, ho provato la tua risposta, ma sfortunatamente, UITableViewStyleGroupedle celle della tabella hanno margini extra che cambiano il loro allineamento con l'intestazione. Questo è un problema quando si desidera effettivamente rappresentare una tabella a più colonne e utilizzare l'intestazione per mostrare i titoli delle colonne (e quindi allineare le singole voci della tabella con questi titoli).
brainjam,

15

Originariamente pubblicato qui , una soluzione rapida che utilizza IB. Lo stesso può essere fatto a livello di codice anche se in modo abbastanza semplice.

Un modo probabilmente più semplice per raggiungere questo obiettivo (utilizzando IB):

Trascina un UIView sul tuo TableView per renderlo la sua vista di intestazione.

  1. Imposta l'altezza della vista dell'intestazione su 100 px
  2. Impostare il contenuto della visualizzazione tabella Set (in alto) su -100
  3. Le intestazioni di sezione ora scorreranno proprio come qualsiasi cella normale.

Alcune persone hanno commentato dicendo che questa soluzione nasconde la prima intestazione, tuttavia non ho notato alcun problema del genere. Ha funzionato perfettamente per me ed è stata di gran lunga la soluzione più semplice che abbia mai visto finora.


Nota che probabilmente dovresti impostare la vista in modo che utilizzi un colore di sfondo di clearcolor, altrimenti se scorri oltre la cima vedi il bianco nel rimbalzo.
Doc

3
Nasconde la mia prima intestazione
Leena,

Leena, su quale versione di iOS stai eseguendo? La vista è un UITableViewController o un UIView con un UITableView in esso? Non sono sicuro del perché per alcune persone questa soluzione nasconda la prima intestazione, quindi sto cercando di trovare eventuali discrepanze.
Doc

Questa soluzione è perfetta Sto cercando un infinito aspetto di sfondo delle celle superiore e inferiore - questo lo realizza totalmente. Bello!
Taylor Halliday,

Questa soluzione è eccellente Più facile da realizzare rispetto alle altre risposte in questo thread. Secondo me, questa dovrebbe essere la risposta accettata.
John Rogers,

15

Non ero soddisfatto delle soluzioni qui descritte finora, quindi ho cercato di combinarle. Il risultato è il seguente codice, ispirato a @awulf e @cescofry. Funziona per me perché non ho un'intestazione di visualizzazione tabella reale. Se si dispone già di un'intestazione di visualizzazione tabella, potrebbe essere necessario regolare l'altezza.

// Set the edge inset
self.tableView.contentInset = UIEdgeInsetsMake(-23.0f, 0, 0, 0);

// Add a transparent UIView with the height of the section header (ARC enabled)
[self.tableView setTableHeaderView:[[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 100.0f, 23.0f)]];

Questa è stata una soluzione più semplice che ho trovato.
Zorayr,

Questo ha funzionato per me su iOS9.2, quindi anche se una risposta più vecchia, è ancora valida. E non ha nascosto l'intestazione della prima sezione. Funziona e funziona perfettamente.
idStar

Perfetto. Se la vista della tabella ha già un'intestazione, basta aumentarne l'altezza dell'offset, quindi aumentare la costante di vincolo principale del contenuto dell'intestazione per spostare il contenuto verso il basso nella posizione originale
Jason,

14

Basta cambiare lo stile di TableView:

self.tableview = [[UITableView alloc] initwithFrame:frame style:UITableViewStyleGrouped];

Documentazione UITableViewStyle :

UITableViewStylePlain: una vista tabella semplice. Eventuali intestazioni o piè di pagina di sezione vengono visualizzati come separatori in linea e fluttuano quando si scorre la vista tabella.

UITableViewStyleGrouped: una vista tabella le cui sezioni presentano gruppi distinti di righe. Le intestazioni e i piè di pagina della sezione non galleggiano.


ottima risposta, ha funzionato per me. non c'è bisogno di alcun lavoro in giro
Shams Ahmed,

9

Seleziona lo stile TableView raggruppato

Seleziona lo stile di visualizzazione tabella raggruppata dalla finestra di ispezione degli attributi di tableView nello storyboard.


5

Impostare headerView della tabella con una vista trasparente con la stessa altezza dell'intestazione nella vista in sezione. Initi anche la vista da tavolo con una cornice a-altezza.

self.tableview = [[UITableView alloc] initWithFrame:CGRectMake(0, - height, 300, 400)];

UIView *headerView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, width, height)] autorelease];
[self.tableView setTableHeaderView:headerView];

4

Ho trovato una soluzione alternativa, utilizzare la prima cella di ogni sezione anziché una sezione di intestazione reale, questa soluzione non sembra così pulita, ma funziona così bene, è possibile utilizzare una cella prototipo definita per la sezione delle intestazioni e nel metodo cellForRowAtIndexPath chiedi indexPath.row == 0, se vero, usa la cella prototipo della sezione header, altrimenti usa la tua cella prototipo predefinita.


Se vuoi ancora lavorare con indexPath.row& indexPath.section, assicurati di restituire un'altezza di 0.0fin - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)sectionmodo che le intestazioni siano invisibili.
Minestra

4

Cambia il tuo stile TableView:

self.tableview = [[UITableView alloc] initwithFrame:frame style:UITableViewStyleGrouped];

Come da documentazione Apple per UITableView:

UITableViewStylePlain: una vista tabella semplice. Eventuali intestazioni o piè di pagina di sezione vengono visualizzati come separatori in linea e fluttuano quando si scorre la vista tabella.

UITableViewStyleGrouped: una vista tabella le cui sezioni presentano gruppi distinti di righe. Le intestazioni e i piè di pagina della sezione non galleggiano. Spero che questo piccolo cambiamento ti possa aiutare ..


2

Ora che lo stile raggruppato sembra sostanzialmente lo stesso dello stile normale in iOS 7 (in termini di planarità e sfondo), per noi la soluzione migliore e più semplice (cioè meno confusa) è stata semplicemente cambiare lo stile della vista tabella in raggruppato. Sollevare con il contenuto Le inserzioni sono sempre stati un problema quando abbiamo integrato una barra di navigazione a scorrimento nella parte superiore. Con uno stile di visualizzazione tabella raggruppata, sembra esattamente lo stesso (con le nostre celle) e le intestazioni di sezione rimangono fisse. Nessuna stranezza a scorrimento.


Questa è la soluzione migliore soprattutto se le celle sono personalizzate, sembra semplicemente fermare il "hold" dell'intestazione della sezione quando lo scroll colpisce la parte superiore.
Acciaio riciclato,

1

Assegna un inserto negativo a tableView. Se hai intestazioni a sezione alta 22px e non vuoi che siano appiccicose, subito dopo aver ricaricatoData aggiungi:

self.tableView.contentInset = UIEdgeInsetsMake(-22, 0, 0, 0); 
self.tableView.contentSize = CGSizeMake(self.tableView.contentSize.width, self.tableView.contentSize.height+22); 

Funziona come un incanto per me. Funziona anche per i piè di pagina della sezione, basta assegnare l'inserzione negativa nella parte inferiore.


Questo taglia la prima intestazione ??
cannyboy

Ha funzionato perfettamente per me !! Grazie
Daniel

0

Aggiungo la tabella a una vista di scorrimento e sembra funzionare bene.


0

Controlla la mia risposta qui . Questo è il modo più semplice per implementare le intestazioni di sezione non mobili senza alcun hack.


0

La risposta di @ LocoMike si adattava meglio al mio tableView, tuttavia si è rotto anche usando i piè di pagina. Quindi, questa è la soluzione corretta quando si usano intestazioni e piè di pagina:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return (self.sections.count + 1) * 3;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if (section % 3 != 1) {
        return 0;
    }
    section = section / 3;
    ...
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
    if (section % 3 != 0) {
        return nil;
    }
    section = section / 3;
    ...
}

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    if (section % 3 != 0) {
        return 0;
    }
    section = section / 3;
    ...
}

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
    if (section % 3 != 2) {
        return 0;
    }
    section = section / 3;
    ...
}

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    if (section % 3 != 0) {
        return nil;
    }
    section = section / 3;
    ...
}

- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
    if (section % 3 != 2) {
        return nil;
    }
    section = section / 3;
    ...
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    int section = indexPath.section;
    section = section / 3;
    ...
}

0

Versione rapida della risposta @awulf, che funziona alla grande!

func scrollViewDidScroll(scrollView: UIScrollView) {
    let sectionHeight: CGFloat = 80
    if scrollView.contentOffset.y <= sectionHeight {
        scrollView.contentInset = UIEdgeInsetsMake( -scrollView.contentOffset.y, 0, 0, 0)
    }else if scrollView.contentOffset.y >= sectionHeight {
        scrollView.contentInset = UIEdgeInsetsMake(-sectionHeight, 0, 0, 0)
    }
}

-2

Ho imparato che basta impostare la proprietà tableHeaderView, vale a dire:

 tableView.tableHeaderView = customView;

e basta.

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.