Passen Sie den UITableView-Headerabschnitt an


141

Ich möchte den UITableViewHeader für jeden Abschnitt anpassen . Bisher habe ich implementiert

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

diese UITabelViewDelegateMethode. Was ich tun möchte, ist, den aktuellen Header für jeden Abschnitt UILabelabzurufen und ihn einfach als Unteransicht hinzuzufügen.

Bisher kann ich das nicht erreichen. Weil ich nichts gefunden habe, um den Standardabschnittskopf zu erhalten. Erste Frage: Gibt es eine Möglichkeit, den Standardabschnittskopf zu erhalten ?

Wenn dies nicht möglich ist, muss ich eine Containeransicht erstellen, bei der es sich UIViewjedoch um eine Standardansicht handelt. Diesmal muss ich jedoch die Standardhintergrundfarbe, die Schattenfarbe usw. festlegen. Wenn Sie sich die Kopfzeile des Abschnitts genau ansehen, ist sie bereits angepasst.

Wie kann ich diese Standardwerte für jeden Abschnittskopf erhalten?

Danke euch allen.


1
Was ist falsch an der Verwendung tableView:titleForHeaderInSection:?
Borrrden

Es gibt ein zurück NSString, ich muss benutzerdefinierte Schriftart einstellen, damit ich nicht kann, wenn ichtableView:titleForHeaderInSection:
limon

Sie können auch Bilder verwenden, um die Standardabschnittsüberschriften nachzuahmen. teehanlax.com/blog/ios-6-gui-psd-iphone-5
Desdenova

@limon: So implementieren Sie Abschnitt Header: stackoverflow.com/a/32261262/1457385
flatThought

Antworten:


288

Sie können dies versuchen:

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

das ist deine bg Farbe, egal welche Farbe du
einstellen möchtest

Das ist das Problem, ich habe bereits getan, was Sie geschrieben haben. Aber ich kenne nicht die Standardhintergrundfarbe der Abschnittsüberschrift, die irgendwie grau ist. Aber ich brauche es, um genau Standard-Abschnittsüberschrift zu sein.
Limon

15
hey komm schon digitales Farbmessgerät
Lochana Ragupathy

Stellen Sie sicher, dass Sie auch die Hintergrundfarbe des UILabels einstellen. Ich weiß, dass ich etwas verwirrt war, als mein Hintergrund für mich nicht klar wurde.
Shulmey

3
Was ist Liste in Zeile NSString * string = [Liste objectAtIndex: Abschnitt]; Jeder kann es mir sagen
Nisha Gupta

45

Die ausgewählte Antwort mit tableView :viewForHeaderInSection:ist korrekt.

Nur um hier einen Tipp zu teilen.

Wenn Sie Storyboard / xib verwenden, können Sie eine weitere Prototypzelle erstellen und diese für Ihre "Abschnittszelle" verwenden. Der Code zum Konfigurieren des Headers ähnelt dem Konfigurieren für Zeilenzellen.

- (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
Mit dieser Lösung stimmt eine Reihe von Dingen nicht. Wenn Sie "tableView (tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool" implementieren, werden Sie feststellen, dass sich die Abschnittsüberschrift beim Verschieben mit der Zeile bewegt. Um dies zu vermeiden, müssen Sie stattdessen cell.contentView zurückgeben. Das größere Problem ist die Tatsache, dass bei dieser Lösung die App abstürzt, wenn Sie lange auf die Abschnittsüberschrift drücken. Der richtige Weg besteht darin, eine Schreibfeder zu erstellen, die UITableViewHeaderFooterView erweitert, sie mit der Tabellenansicht zu registrieren und in dieser Methode zurückzugeben. Getestet auf iOS8
Kachi

@Kachi Die Lösung verwendet viewForHeaderInSectionnicht canEditRowAtIndexPathwie Sie erwähnt. Ich überprüfe nie den Absturz, den Sie gesagt haben, aber können Sie aufklären, wie ein langes Drücken einen Absturz verursacht?
Samwize

1
Ich meinte, wenn Sie diese Lösung implementieren UND canEditRowAtIndexPath implementieren, werden Sie sehen, dass der Header auch mit der obersten Zeile verschoben wird, die Sie löschen, wenn Sie cell.contentView nicht zurückgeben. Siehe diesen SO-Beitrag: stackoverflow.com/questions/26009722/… Das lange Drücken verursacht einen Absturz, da eine Nachricht versucht, an ein freigegebenes Objekt gesendet zu werden. Siehe diesen SO-Beitrag: stackoverflow.com/questions/27622290/…
Kachi

1
Bitte niemals UITableViewCellals Header-Ansicht verwenden. Es wird sehr schwierig sein, visuelle Störungen zu beheben - der Header verschwindet manchmal, weil Zellen aus der Warteschlange entfernt werden, und Sie werden stundenlang nach dem Grund suchen, warum dies so ist, bis Sie feststellen, dass UITableViewCelles nicht zum UITableViewHeader gehört.
Raven_raven

Die Verwendung von a UITableViewCellals Header ist einfach falsch.
Alex Zavatone

31

Schnelle Version von Lochana Tejas Antwort:

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
Wie kann die Etikettenhöhe gemäß dem Text in der Ansicht dynamisiert werden?
Pratik Shah

Das overrideSchlüsselwort ist redundant. Darüber hinaus sollten Sie Header-Ansichten wiederverwenden, anstatt sie neu zu erstellen.
Vadim Bulavin

17

Wenn Sie die Standard-Header-Ansicht verwenden, können Sie den Text nur mit ändern

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

Für Swift:

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

Wenn Sie die Ansicht anpassen möchten, müssen Sie selbst eine neue erstellen.


10

Sie können dies nur verwenden, wenn Sie nicht auch den Abschnitt - (UIView *) tableView: (UITableView *) tableView viewForHeaderInSection: (NSInteger) verwenden.
SAHM

1
Vollkommen gültige Antwort. Die Verwendung von UITableViewHeaderFooterView profitiert ebenso wie Zellen vom View-Recycling.
Gregzo

6
@dmarsi Ich habe keine Beweise dafür gefunden, dass sie veraltet sind.
Fawkes

8

Wenn headerInSection nicht angezeigt wird, können Sie dies versuchen.

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

Dies gibt eine Höhe für die Kopfzeile eines bestimmten Abschnitts zurück.


1
Möchten Sie Ihre Antwort ausarbeiten?
CinCout

Der Header-Abschnitt wird nur angezeigt, wenn Sie mit einem Methoden-Hook die 'Höhe' des Section-Headers angeben. UITableView zeigt standardmäßig keine Header an, wenn keine Höhe angegeben ist. @CinCout
theprojectabot

6

Swift 3 Version von Lochana und Estemendoza antwortet:

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

}

Beachten Sie außerdem, dass Sie AUCH Folgendes implementieren müssen:

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

5

Versuche dies......

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

Mit den anderen Antworten wird die Standard-Header-Ansicht gut wiederhergestellt, aber Ihre Hauptfrage wird nicht beantwortet:

Gibt es eine Möglichkeit, den Standardabschnittskopf zu erhalten?

Es gibt einen Weg - implementieren tableView:willDisplayHeaderView:forSection:Sie ihn einfach in Ihrem Delegaten. Die Standard-Header-Ansicht wird an den zweiten Parameter übergeben. Von dort aus können Sie sie in eine UITableViewHeaderFooterViewumwandeln und dann nach Bedarf Unteransichten hinzufügen / ändern.

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

Schnell

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
}

Sie müssen es nicht wirken. Sie können der Ansicht einfach hinzufügen, was Sie möchten. Das Erstellen eines neuen Objekts führt nur dann zu, wenn Sie es zuweisen view.
Alex Zavatone

@AlexZavatone Richtig, Sie müssen es nicht umsetzen, wenn Sie nur Ansichten hinzufügen. Dies ist hilfreich, wenn Sie einige der Standardansichten wie die Textbezeichnung anpassen möchten.
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

Dies ist die einfachste mögliche Lösung. Der folgende Code kann direkt zum Erstellen einer benutzerdefinierten Abschnittsüberschrift verwendet werden.

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

HINWEIS: SectionHeaderTableViewCell ist eine benutzerdefinierte UITableViewCell, die in Storyboard erstellt wurde.


SectionHeaderTableViewCell - Verwendung der nicht deklarierten Kennung
Boris Gafurov

@BorisGafurov SectionHeaderTableViewCell ist nur ein Beispielname, den ich meiner UITableViewCell gegeben habe, die ich im Storyboard erstellt habe.
Anish Kumar

2

Wenn ich Sie wäre, würde ich eine Methode erstellen, die eine UIView zurückgibt, wenn ein NSString enthalten ist. Beispielsweise

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

Erstellen Sie bei der Implementierung dieser Methode eine UIView, fügen Sie ihr ein UILabel mit den Eigenschaften hinzu, die Sie festlegen möchten, und setzen Sie den Titel natürlich auf die angegebene.


Ja, das kann ich, aber meine Frage ist, wie ich den Standardhintergrund für Abschnittsüberschriften und den Schattenwert erhalten kann. Der Rest ist einfach zu implementieren.
Limon

Was meinst du mit Standard Abschnitt Header Hintergrund
Lochana Ragupathy

1
Am einfachsten wäre es, die Anwendung Digital Color Meter zu verwenden, um die gewünschten Farben zu erhalten. Es wäre schwierig, sie per Code zu
erfassen

2

@ Samwizes Lösung in Swift (also stimme ihm zu!). Genial, wenn der gleiche Recyclingmechanismus auch für Kopf- / Fußzeilen verwendet wird:

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

Wenn Sie die Schriftart des textLabel in Ihrer Abschnittsüberschrift ändern möchten, möchten Sie dies in willDisplayHeaderView tun. Um den Text festzulegen, können Sie dies in viewForHeaderInSection oder titleForHeaderInSection tun. Viel Glück!


2

Vollständiges Beispiel für 2019 zum Kopieren und Einfügen

Stellen Sie zuerst "Gruppiert" im Storyboard ein: Es muss zur Init-Zeit geschehen, Sie können es später nicht wirklich festlegen, daher ist es einfacher, sich daran zu erinnern, es im Storyboard zu tun:

Geben Sie hier die Bildbeschreibung ein

Nächster,

Muss heightForHeaderInSection aufgrund eines Apple-Fehlers implementieren .

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

Es gibt immer noch einen Apple-Fehler - seit zehn Jahren - bei dem der erste Header (dh Index 0) einfach nicht angezeigt wird, wenn Sie keinen haben heightForHeaderInSection Anruf haben.

Also, tableView.sectionHeaderHeight = 70funktioniert einfach nicht, es ist kaputt .

Das Setzen eines Rahmens bringt nichts:

Im viewForHeaderInSection einfach eine UIView erstellen ().

Es ist sinnlos / erreicht nichts, wenn Sie UIView (Frame ...) da iOS einfach die Größe der Ansicht der Tabelle festlegt.

Die erste Zeile von viewForHeaderInSectionwird also einfach sein let view = UIView()und das ist die Ansicht, die Sie zurückgeben.

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
}

Das war's - alles andere ist Zeitverschwendung.

Ein weiteres "pingeliges" Apple-Problem.


Die oben verwendete Komforterweiterung lautet:

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

Fügen Sie den Tabellenansichtskopf auf magische Weise schnell hinzu

Kürzlich habe ich das versucht.

Ich brauchte einen und nur einen Header in der gesamten UITableView.

Als ob ich eine UIImageView oben in der TableView haben wollte. Also habe ich ein UIImageView über der UITableViewCell hinzugefügt und es wurde automatisch als tableViewHeader hinzugefügt. Jetzt verbinde ich die ImageView mit dem ViewController und füge das Image hinzu.

Ich war verwirrt, weil ich so etwas zum ersten Mal gemacht habe. Um meine Verwirrung zu beseitigen, öffnen Sie das XML-Format des MainStoryBoard und stellen Sie fest, dass die Bildansicht als Header hinzugefügt wurde.

Es hat bei mir funktioniert. Danke xCode und schnell.



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

Wenn Sie dem tableView-Header nur einen Titel hinzufügen möchten, fügen Sie keine Ansicht hinzu. In Swift 3.x sieht der Code folgendermaßen aus:

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
}

Sie können ein Array implementieren, um den Titel für die Header abzurufen.


0

Zurück zur ursprünglichen Frage (4 Jahre später): Anstatt Ihren eigenen Abschnittsheader neu zu erstellen, kann iOS Sie einfach anrufen (mit willDisplayHeaderView: forSection :), direkt nachdem der Standard erstellt wurde. Zum Beispiel wollte ich eine Grafikschaltfläche am rechten Rand der Abschnittsüberschrift hinzufügen:

- (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

Verwenden Sie tableView: willDisplayHeaderView:diese Option, um die Ansicht anzupassen, wenn sie angezeigt werden soll.

Dies gibt Ihnen den Vorteil, dass Sie die bereits für die Header-Ansicht erstellte Ansicht übernehmen und erweitern können, anstatt die gesamte Header-Ansicht selbst neu erstellen zu müssen.

Hier ist ein Beispiel, das den Header-Abschnitt basierend auf einem BOOL einfärbt und dem Header ein Detailtextelement hinzufügt.

- (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

Swift 4.2

In Swift 4.2 wurde der Name der Tabelle etwas geändert.

    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
    }
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.