Personalizza la sezione dell'intestazione UITableView


141

Voglio personalizzare l' UITableViewintestazione per ogni sezione. Finora ho implementato

-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section

questo UITabelViewDelegatemetodo. Quello che voglio fare è ottenere un'intestazione corrente per ogni sezione e aggiungerla UILabelcome sottoview.

Finora non sono riuscito a farlo. Perché non sono riuscito a trovare nulla per ottenere l'intestazione di sezione predefinita. Prima domanda, c'è un modo per ottenere l'intestazione di sezione predefinita ?

Se non è possibile, devo creare una vista contenitore che è un UIViewma, questa volta ho bisogno di impostare il colore di sfondo predefinito, il colore dell'ombra ecc. Perché, se guardi attentamente nell'intestazione della sezione, è già personalizzato.

Come posso ottenere questi valori predefiniti per ciascuna intestazione di sezione?

Grazie a tutti.


1
Cosa c'è di sbagliato nell'utilizzo tableView:titleForHeaderInSection:?
Borrrden,

Restituisce un NSString, ho bisogno di impostare un carattere personalizzato, quindi non posso se usotableView:titleForHeaderInSection:
Limon

Oppure puoi usare le immagini per imitare le intestazioni di sezione predefinite. teehanlax.com/blog/ios-6-gui-psd-iphone-5
Desdenova

@limon: Come implementare intestazione di sezione: stackoverflow.com/a/32261262/1457385
shallowThought

Risposte:


288

Puoi provare questo:

 -(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, 18)];
    /* Create custom view to display section header... */
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10, 5, tableView.frame.size.width, 18)];
    [label setFont:[UIFont boldSystemFontOfSize:12]];
     NSString *string =[list objectAtIndex:section];
    /* Section header is in 0th index... */
    [label setText:string];
    [view addSubview:label];
    [view setBackgroundColor:[UIColor colorWithRed:166/255.0 green:177/255.0 blue:186/255.0 alpha:1.0]]; //your background color...
    return view;
}

questo è il tuo colore bg più colorato che vuoi impostare che puoi
Lochana Ragupathy

Questo è il problema, ho già fatto quello che hai scritto. Ma non conosco il colore di sfondo predefinito dell'intestazione della sezione, che è un po 'grigia. Ma ho bisogno che sia esattamente l'intestazione di sezione predefinita.
limon,

15
hey vieni in uso Digital color meter
Lochana Ragupathy

assicurati di impostare anche il backgroundColor di UILabel. So di essere stato leggermente confuso quando il mio background non stava diventando chiaro per me.
shulmey,

3
cos'è l'elenco nella riga NSString * string = [list objectAtIndex: section]; qualcuno può dirmelo
Nisha Gupta,

45

La risposta selezionata usando tableView :viewForHeaderInSection:è corretta.

Solo per condividere un suggerimento qui.

Se si utilizza storyboard / xib, è possibile creare un'altra cella prototipo e utilizzarla per la "cella della sezione". Il codice per configurare l'intestazione è simile a come si configura per le celle di riga.

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    static NSString *HeaderCellIdentifier = @"Header";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:HeaderCellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:HeaderCellIdentifier];
    }

    // Configure the cell title etc
    [self configureHeaderCell:cell inSection:section];

    return cell;
}

14
ci sono molte cose sbagliate con questa soluzione. Innanzitutto, se si implementa "tableView (tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool", si noterà che l'intestazione della sezione si sposterà insieme alla riga quando si fa scorrere. Per evitarlo, devi invece restituire cell.contentView. Il problema più grande è il fatto che con questa soluzione l'app si arresta in modo anomalo quando si preme a lungo l'intestazione della sezione. Il modo corretto è quello di creare un pennino che estende UITableViewHeaderFooterView, registrarlo con la vista tabella e restituirlo in questo metodo. Testato su iOS8
Kachi il

@Kachi La soluzione sta usando viewForHeaderInSectionnon è canEditRowAtIndexPathcome lei ha ricordato. Non ho mai verificato l'incidente che hai detto, ma potresti chiarire quanto una lunga pressione provocherà un incidente?
Samwize,

1
ciò che intendevo era che se implementassi questa soluzione E implementassi canEditRowAtIndexPath, vedrai che anche l'intestazione scorrerà con la riga più in alto che stai eliminando se non restituisci cell.contentView. Vedi questo messaggio SO: stackoverflow.com/questions/26009722/… La pressione prolungata provoca un arresto anomalo perché un messaggio tenta di essere inviato a un oggetto deallocato. Vedi questo messaggio SO: stackoverflow.com/questions/27622290/…
Kachi

1
Non utilizzare mai UITableViewCellcome vista di intestazione. Risulterà molto difficile eseguire il debug dei glitch visivi: l'intestazione a volte scompare a causa del modo in cui le celle vengono rimosse, e si cercherà per ore perché fino a quando non ti rendi conto UITableViewCellche non appartiene all'intestazione UITableView.
raven_raven,

L'uso di a UITableViewCellcome intestazione è semplicemente sbagliato.
Alex Zavatone,

31

La versione rapida di Lochana Tejas risponde:

override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    let view = UIView(frame: CGRectMake(0, 0, tableView.frame.size.width, 18))
    let label = UILabel(frame: CGRectMake(10, 5, tableView.frame.size.width, 18))
    label.font = UIFont.systemFontOfSize(14)
    label.text = list.objectAtIndex(indexPath.row) as! String
    view.addSubview(label)
    view.backgroundColor = UIColor.grayColor() // Set your background color

    return view
}

1
come rendere dinamica l'altezza dell'etichetta secondo il testo che si trova all'interno della vista?
Pratik Shah,

La overrideparola chiave è ridondante. Inoltre, considera di riutilizzare le visualizzazioni di intestazione anziché ricrearle.
Vadim Bulavin,

17

Se si utilizza la visualizzazione predefinita dell'intestazione, è possibile modificare solo il testo con

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section

Per Swift:

override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {

Se si desidera personalizzare la vista, è necessario crearne una nuova da soli.


10

perché non usare UITableViewHeaderFooterView ?


Puoi usarlo solo se non usi anche - (UIView *) tableView: (UITableView *) tableView viewForHeaderInSection: (NSInteger) sezione.
SAHM,

1
Risposta perfettamente valida. Inoltre, l'utilizzo di UITableViewHeaderFooterView beneficia del riciclaggio della vista proprio come le celle.
Gregzo,

6
@dmarsi Non ho trovato prove del loro deprecamento.
Fawkes,

8

Se headerInSection non viene visualizzato, puoi provare questo.

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    return 45;
}

Ciò restituisce un'altezza per l'intestazione di una determinata sezione.


1
Ti dispiace elaborare la tua risposta?
CinCout il

La sezione dell'intestazione non verrà visualizzata a meno che non si specifichi con un metodo l'hook dell'altezza dell'intestazione della sezione. Per impostazione predefinita, UITableView non mostra le intestazioni se non viene specificata l'altezza. @CinCout
theprojectabot

6

Swift 3 versione di lochana ed estemendoza risponde:

override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {

    let view = UIView(frame: CGRect(x:0, y:0, width:tableView.frame.size.width, height:18))
    let label = UILabel(frame: CGRect(x:10, y:5, width:tableView.frame.size.width, height:18))
    label.font = UIFont.systemFont(ofSize: 14)
    label.text = "This is a test";
    view.addSubview(label);
    view.backgroundColor = UIColor.gray;
    return view

}

Inoltre, tieni presente che devi anche implementare:

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

5

Prova questo......

override func tableView(tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) 
{
    // Background view is at index 0, content view at index 1
    if let bgView = view.subviews[0] as? UIView
    {
        // do your stuff
    }

    view.layer.borderColor = UIColor.magentaColor().CGColor
    view.layer.borderWidth = 1
}

5

Le altre risposte fanno un buon lavoro nel ricreare la vista di intestazione predefinita, ma in realtà non rispondono alla domanda principale:

c'è un modo per ottenere l'intestazione di sezione predefinita?

C'è un modo: implementalo tableView:willDisplayHeaderView:forSection:nel tuo delegato. La vista di intestazione predefinita verrà passata al secondo parametro e da lì puoi lanciarla in un UITableViewHeaderFooterViewe quindi aggiungere / modificare le viste secondarie come desideri.

Obj-C

- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section
{
    UITableViewHeaderFooterView *headerView = (UITableViewHeaderFooterView *)view;

    // Do whatever with the header view... e.g.
    // headerView.textLabel.textColor = [UIColor whiteColor]
}

veloce

override func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int)
{
    let headerView = view as! UITableViewHeaderFooterView

    // Do whatever with the header view... e.g.
    // headerView.textLabel?.textColor = UIColor.white
}

Non è necessario lanciarlo. Puoi semplicemente aggiungere ciò che vuoi alla vista. In effetti, la creazione di un nuovo oggetto non farà nulla se non lo si assegna a view.
Alex Zavatone,

@AlexZavatone Esatto, non è necessario eseguirne il cast se si stanno solo aggiungendo visualizzazioni. È utile se si desidera personalizzare alcune delle visualizzazioni predefinite come l'etichetta di testo.
Craig Brown,

4
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    //put your values, this is part of my code
    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 30.0f)];
    [view setBackgroundColor:[UIColor redColor]];
    UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(20, 5, 150, 20)];
    [lbl setFont:[UIFont systemFontOfSize:18]];
    [lbl setTextColor:[UIColor blueColor]];
    [view addSubview:lbl];

    [lbl setText:[NSString stringWithFormat:@"Section: %ld",(long)section]];

    return view;
}

4

Questa è la soluzione più semplice possibile. Il seguente codice può essere utilizzato direttamente per creare un'intestazione di sezione personalizzata.

 -(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    SectionHeaderTableViewCell *headerView = [tableView dequeueReusableCellWithIdentifier:@"sectionHeader"];

    //For creating a drop menu of rows from the section
    //==THIS IS JUST AN EXAMPLE. YOU CAN REMOVE THIS IF-ELSE.==
    if (![self.sectionCollapsedArray[section] boolValue])
    {
        headerView.imageView.image = [UIImage imageNamed:@"up_icon"];
    }
    else
    {
        headerView.imageView.image = [UIImage imageNamed:@"drop_icon"];
    }

    //For button action inside the custom cell
    headerView.dropButton.tag = section;
    [headerView.dropButton addTarget:self action:@selector(sectionTapped:) forControlEvents:UIControlEventTouchUpInside];

    //For removing long touch gestures.
    for (UIGestureRecognizer *recognizer in headerView.contentView.gestureRecognizers)
    {
        [headerView.contentView removeGestureRecognizer:recognizer];
        [headerView removeGestureRecognizer:recognizer];
    }

    return headerView.contentView;
}

NOTA: SectionHeaderTableViewCell è un UITableViewCell personalizzato creato in Storyboard.


SectionHeaderTableViewCell - uso di identificatore non dichiarato
Boris Gafurov,

@BorisGafurov SectionHeaderTableViewCell è solo un nome di esempio che ho dato a UITableViewCell, che ho creato nello storyboard.
Anish Kumar l'

2

Se fossi in te, farei un metodo che restituisca un UIView dato un NSString da contenere. Per esempio

+ (UIView *) sectionViewWithTitle:(NSString *)title;

Nell'implementazione di questo metodo creare un UIView, aggiungere un UILabel con le proprietà che si desidera impostare e, naturalmente, impostare il titolo su quello indicato.


Sì, posso farlo, ma la mia domanda è come posso ottenere lo sfondo dell'intestazione della sezione predefinita, il valore dell'ombra, il resto è facile da implementare.
limon,

cosa intendi per impostazione predefinita intestazione della sezione di sfondo
Lochana Ragupathy

1
Bene, il modo più semplice sarebbe usare l'applicazione Digital Color Meter per ottenere i colori desiderati. Prendere per codice sarebbe difficile, per quanto ne so ...
cpprulez,

2

@ Soluzione di Samwize in Swift (quindi votalo!). Fantastico utilizzando lo stesso meccanismo di riciclaggio anche per le sezioni di intestazione / piè di pagina:

func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    let settingsHeaderSectionCell:SettingsHeaderSectionCell = self.dequeueReusableCell(withIdentifier: "SettingsHeaderSectionCell") as! SettingsHeaderSectionCell

    return settingsHeaderSectionCell
}

2
- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section
{
    if([view isKindOfClass:[UITableViewHeaderFooterView class]]){

        UITableViewHeaderFooterView *headerView = view;

        [[headerView textLabel] setTextColor:[UIColor colorWithHexString:@"666666"]];
        [[headerView textLabel] setFont:[UIFont fontWithName:@"fontname" size:10]];
    }
}

Se vuoi cambiare il carattere del textLabel nell'intestazione della sezione, lo vuoi fare in willDisplayHeaderView. Per impostare il testo puoi farlo in viewForHeaderInSection o titleForHeaderInSection. In bocca al lupo!


2

Esempio completo 2019 da copiare e incollare

Prima imposta "Raggruppato" sullo storyboard: deve accadere al momento dell'inizializzazione, non puoi davvero impostarlo in un secondo momento, quindi è più facile ricordare di farlo sullo storyboard:

inserisci qui la descrizione dell'immagine

Il prossimo,

È necessario implementare heightForHeaderInSection a causa di un bug Apple.

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

C'è ancora un bug di Apple - da dieci anni a questa parte - in cui semplicemente non mostrerà la prima intestazione (cioè l'indice 0) se non hai una heightForHeaderInSectionchiamata.

Quindi, tableView.sectionHeaderHeight = 70semplicemente non funziona, è rotto .

L'impostazione di una cornice non ottiene nulla:

In viewForHeaderInSectionsemplicemente creare un UIView ().

È inutile / non ottiene nulla se UIView (frame ...) poiché iOS imposta semplicemente le dimensioni della vista come determinato dalla tabella.

Quindi la prima riga viewForHeaderInSectionsarà semplicemente let view = UIView()e questa è la vista che ritorni.

func tableView(_ tableView: UITableView,
                       viewForHeaderInSection section: Int) -> UIView? {
    let view = UIView()
    
    let l = UILabel()
    view.addSubview(l)
    l.bindEdgesToSuperview()
    l.backgroundColor = .systemOrange
    l.font = UIFont.systemFont(ofSize: 15)
    l.textColor = .yourClientsFavoriteColor
    
    switch section {
    case 0:
        l.text =  "First section on screen"
    case 1:
        l.text =  "Here's the second section"
    default:
        l.text =  ""
    }
    
    return view
}

Ecco fatto: qualsiasi altra cosa è una perdita di tempo.

Un altro problema "pignolo" di Apple.


L'estensione di convenienza utilizzata sopra è:

extension UIView {
    
    // incredibly useful:
    
    func bindEdgesToSuperview() {
        
        guard let s = superview else {
            preconditionFailure("`superview` nil in bindEdgesToSuperview")
        }
        
        translatesAutoresizingMaskIntoConstraints = false
        leadingAnchor.constraint(equalTo: s.leadingAnchor).isActive = true
        trailingAnchor.constraint(equalTo: s.trailingAnchor).isActive = true
        topAnchor.constraint(equalTo: s.topAnchor).isActive = true
        bottomAnchor.constraint(equalTo: s.bottomAnchor).isActive = true
    }
}

1

Aggiungi magicamente l'intestazione della vista tabella rapidamente

Di recente ho provato questo.

Avevo bisogno di una e sola intestazione nell'intero UITableView.

Come se volessi un UIImageView nella parte superiore di TableView. Quindi ho aggiunto un UIImageView sopra UITableViewCell e automaticamente è stato aggiunto come tableViewHeader. Ora collego ImageView a ViewController e ho aggiunto l'immagine.

Ero confuso perché ho fatto qualcosa del genere per la prima volta. Quindi, per cancellare la mia confusione, apri il formato xml di MainStoryBoard e scopri che la vista immagine è stata aggiunta come intestazione.

Ha funzionato per me. Grazie xCode e rapidità.


1

chiama questo metodo delegato

-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{

return @"Some Title";
}

questo darà la possibilità di aggiungere automaticamente un'intestazione predefinita con titolo dinamico.

È possibile utilizzare intestazioni / piè di pagina riutilizzabili e personalizzabili.

https://github.com/sourov2008/UITableViewCustomHeaderFooterSection


1

swif 4.2

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

    header.textLabel?.textAlignment = .center // for all sections

    switch section {
    case 1:  //only section No.1
        header.textLabel?.textColor = .black
    case 3:  //only section No.3
        header.textLabel?.textColor = .red
    default: //
        header.textLabel?.textColor = .yellow
    }
}


0

Se vuoi solo aggiungere un titolo all'intestazione tableView non aggiungere una vista. In swift 3.x il codice va così:

override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    var lblStr = ""
    if section == 0 {
        lblStr = "Some String 1"
    }
    else if section == 1{
        lblStr = "Some String 2"
    }
    else{
        lblStr = "Some String 3"
    }
    return lblStr
}

È possibile implementare un array per recuperare il titolo per le intestazioni.


0

Tornando alla domanda originale (4 anni dopo), piuttosto che ricostruire la propria intestazione di sezione, iOS può semplicemente chiamarti (con willDisplayHeaderView: forSection :) subito dopo aver creato quello predefinito. Ad esempio, volevo aggiungere un pulsante grafico sul bordo destro dell'intestazione della sezione:

- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section {
    UITableViewHeaderFooterView * header = (UITableViewHeaderFooterView *) view;
    if (header.contentView.subviews.count >  0) return; //in case of reuse
    CGFloat rightEdge = CGRectGetMaxX(header.contentView.bounds);
    UIButton * button = [[UIButton alloc] initWithFrame:CGRectMake(rightEdge - 44, 0, 44, CGRectGetMaxY(header.contentView.bounds))];
    [button setBackgroundImage:[UIImage imageNamed:@"graphIcon"] forState:UIControlStateNormal];
    [button addTarget:self action:@selector(graphButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
    [view addSubview:button];
}

0

Utilizzare tableView: willDisplayHeaderView:per personalizzare la vista quando sta per essere visualizzata.

Ciò offre il vantaggio di poter prendere la vista già creata per la vista dell'intestazione ed estenderla, invece di dover ricreare l'intera vista dell'intestazione da soli.

Ecco un esempio che colora la sezione dell'intestazione in base a un BOOL e aggiunge un elemento di testo di dettaglio all'intestazione.

- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section
{
//    view.tintColor = [UIColor colorWithWhite:0.825 alpha:1.0]; // gray
//    view.tintColor = [UIColor colorWithRed:0.825 green:0.725 blue:0.725 alpha:1.0]; // reddish
//    view.tintColor = [UIColor colorWithRed:0.925 green:0.725 blue:0.725 alpha:1.0]; // pink

    // Conditionally tint the header view
    BOOL isMyThingOnOrOff = [self isMyThingOnOrOff];

    if (isMyThingOnOrOff) {
        view.tintColor = [UIColor colorWithRed:0.725 green:0.925 blue:0.725 alpha:1.0];
    } else {
        view.tintColor = [UIColor colorWithRed:0.925 green:0.725 blue:0.725 alpha:1.0];
    }

    /* Add a detail text label (which has its own view to the section header… */
    CGFloat xOrigin = 100; // arbitrary
    CGFloat hInset = 20;
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(xOrigin + hInset, 5, tableView.frame.size.width - xOrigin - (hInset * 2), 22)];

    label.textAlignment = NSTextAlignmentRight;

    [label setFont:[UIFont fontWithName:@"Helvetica-Bold" size:14.0]
    label.text = @"Hi.  I'm the detail text";

    [view addSubview:label];
}

0

Rapido 4.2

In Swift 4.2 il nome della tabella è leggermente cambiato.

    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        let view = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.size.width, height: 18))
        let label = UILabel(frame: CGRect(x: 10, y: 5, width: tableView.frame.size.width, height: 18))
        label.font = UIFont.systemFont(ofSize: 14)
        label.text = list.objectAtIndex(section) as! String
        view.addSubview(label)
        view.backgroundColor = UIColor.gray // Set your background color

        return view
    }
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.