UITableView: Header vor leerem Abschnitt ausblenden

76

Ich habe eine UITableView, die Ausgaben von einem aktuellen Monat anzeigt (siehe Screenshot):

Mein Problem ist mit der Kopfzeile für leere Abschnitte. Gibt es eine Möglichkeit, sie zu verstecken? Die Daten werden aus Coredata geladen.

Dies ist der Code, der den Headertitel generiert:

TitleForHeader

-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
if ([tableView.dataSource tableView:tableView numberOfRowsInSection:section] == 0) {
    return nil;
} else {

NSDate *today = [NSDate date ];
int todayInt = [dataHandler getDayNumber:today].intValue;

NSDate *date = [NSDate dateWithTimeIntervalSinceNow:(-(todayInt-section-1)*60*60*24)];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:[[NSLocale preferredLanguages] objectAtIndex:0]]];    
[dateFormatter setTimeStyle:NSDateFormatterNoStyle];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
NSString *formattedDateString = [dateFormatter stringFromDate:date];
    return formattedDateString;}

}

ViewForHeader

-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
if ([tableView.dataSource tableView:tableView numberOfRowsInSection:section] == 0) {
    return nil;
} else {

    UIView *headerView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 312, 30)];
    UILabel *title = [[UILabel alloc]initWithFrame:CGRectMake(4, 9, 312, 20)];
    UIView *top = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 312, 5)];
    UIView *bottom = [[UIView alloc]initWithFrame:CGRectMake(0, 5, 312, 1)];

    [top setBackgroundColor:[UIColor lightGrayColor]];
    [bottom setBackgroundColor:[UIColor lightGrayColor]];

    [title setText:[expenseTable.dataSource tableView:tableView titleForHeaderInSection:section]];
    [title setTextColor:[UIColor darkGrayColor]];
    UIFont *fontName = [UIFont fontWithName:@"Cochin-Bold" size:15.0];
    [title setFont:fontName];


    [headerView addSubview:title];
    [headerView addSubview:top];
    [headerView addSubview:bottom];

    return headerView;

}

}

heightForHeader

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {

NSLog(@"Height: %d",[tableView.dataSource tableView:tableView numberOfRowsInSection:section] == 0);
if ([tableView.dataSource tableView:tableView numberOfRowsInSection:section == 0]) {
    return 0;
} else {
    return 30;
}
}

numberOfRowsInSection

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
 {

int rows = 0;
for (Expense* exp in [dataHandler allMonthExpenses]) {
    if ([exp day].intValue == section) {
        rows++;
    }
}

return rows;
}

Geben Sie hier die Bildbeschreibung ein Sebastian

Sebastian Flückiger
quelle

Antworten:

57

Was ist, wenn in - tableView:viewForHeaderInSection:Sie, return nilwenn die Abschnittsanzahl 0 ist ?

BEARBEITEN : Sie können numberOfRowsInSectiondie Anzahl der Elemente im Abschnitt ermitteln.

EDIT : Wahrscheinlich sollten Sie nil auch in zurückgeben, titleForHeaderInSectionwenn numberOfRowsInSection0 ist.

EDIT : Haben Sie die folgende Methode implementiert?

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

EDIT : Swift 3 Beispiel

override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    switch section {
    case 0:
        if self.tableView(tableView, numberOfRowsInSection: section) > 0 {
            return "Title example for section 1"
        }
    case 1:
        if self.tableView(tableView, numberOfRowsInSection: section) > 0 {
            return "Title example for section 2"
        }
    default:
        return nil // when return nil no header will be shown
    }
    return nil
}
LuisEspinoza
quelle
Leider funktioniert es nicht. Ich habe die Frage mit neuem Code und einem neuen Screenshot aktualisiert.
Sebastian Flückiger
kein Fehler. Ich habe gerade die Frage bearbeitet. Jetzt ist der neue Code in und der neue Screenshot.
Sebastian Flückiger
Haben Sie übrigens numberOfRowsInSection implementiert?
LuisEspinoza
1
und was ist, wenn Sie die Größe der Abschnittsüberschrift in der Schreibfeder überprüfen? .. Wenn Sie 0 verwenden, erhalten Sie möglicherweise ein besseres Ergebnis, da Sie es im Code festlegen.
LuisEspinoza
2
Dies ist jetzt eine alte Frage, aber return nil;in titleForHeaderInSectionist ausreichend für mich (nachdem ich count > 0natürlich nach diesem Abschnitt
Patrick
135

Sie müssen tableView:heightForHeaderInSection:für die entsprechenden Abschnitte auf 0 setzen . Dies ist etwas, das sich vor kurzem geändert hat und mich an ein paar Stellen gebracht hat. Daraus UITableViewDelegatesteht ...

Vor iOS 5.0 haben Tabellenansichten die Höhe der Kopfzeilen für Abschnitte, in denen tableView: viewForHeaderInSection: eine Nullansicht zurückgegeben hat, automatisch auf 0 geändert. In iOS 5.0 und höher müssen Sie bei dieser Methode die tatsächliche Höhe für jeden Abschnittskopf zurückgeben.

Also musst du so etwas tun

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
    if ([tableView.dataSource tableView:tableView numberOfRowsInSection:section] == 0) {
        return 0;
    } else {
        // whatever height you'd want for a real section header
    }
}
DBD
quelle
Leider funktioniert es nicht. Ich habe die Frage mit neuem Code und einem neuen Screenshot aktualisiert.
Sebastian Flückiger
3
Statische Tabellen sind etwas anders. Dieser Code gilt für benutzerdefinierte Tabellenkopfansichten, nicht nur für a title. Wenn Sie a titlefestlegen, müssen Sie gegebenenfalls nilfür den Methodenaufruf zurückkehren tableView:titleForHeaderInSection:. Wenn Sie benutzerdefinierte Header-Ansichten verwenden, müssen Sie diese überschreiben viewForHeaderInSection. Wenn Sie das tun, sollte dieser Code funktionieren. Wenn nicht, würde ich weitere Informationen benötigen, um bei dem Problem zu helfen.
DBD
super ... vielen dank. früher gab ich eine UIViewelse { vw = [[UIView alloc]init]; [vw setHidden:YES]; }
Lücke
Ich habe Viewforheader in Abschnitt + über dem Code verwendet und in iOS 6 und sogar in der unteren Version perfekt gearbeitet. thnnxx Kumpel
Amrit Trivedi
Arbeitete für mich - ich bin auf ios6
Shirish Kumar
54

In meiner seltsamen Situation muss ich zurückkehren:

viewForHeaderInSection -> nil

viewForFooterInSection -> nil (Fußzeile nicht vergessen!)

heightForHeaderInSection -> 0,01 (nicht Null!)

heightForFooterInSection -> 0,01

nur in diesem Fall verschwinden leere Abschnitte vollständig

djdance
quelle
10
Ich habe es nur getan, indem ich headerHeight auf 0.01 gesetzt habe.
Akshit Zaveri
1
iOS 8.4 Ich konnte den Text immer noch mit 0,01 sehen, aber 0.0 hat eine Charm-Override-Funktion funktioniert. Rückgabe CGFloat (40.0)}
DogCoffee
Das funktioniert bei mir perfekt. Leider konnte ich das nirgendwo anders finden. Danke Alter.
Ruchi
Selbst in iOS 12.1 müssen Sie die Höhe noch auf 0.01... einstellen . IOS hat einige seltsame Fehler.
Supertecnoboff
10

Schauen Sie sich die Methode an -[UITableViewDelegate tableView:heightForHeaderInSection:]. Insbesondere der Hinweis, der der Dokumentation beigefügt ist:

Vor iOS 5.0 haben Tabellenansichten die Höhe der Kopfzeilen für Abschnitte, in denen tableView:viewForHeaderInSection: eine nilAnsicht zurückgegeben wurde, automatisch auf 0 geändert . In iOS 5.0 und höher müssen Sie bei dieser Methode die tatsächliche Höhe für jeden Abschnittskopf zurückgeben.

Sixten Otto
quelle
danke so mch jungs - ich werde dich in ein paar stunden auf den neuesten Stand bringen und alles akzeptieren und bewerten, was am besten funktioniert hat :-)
Sebastian Flückiger
2
Leider funktioniert es nicht. Ich habe die Frage mit neuem Code und einem neuen Screenshot aktualisiert.
Sebastian Flückiger
9

Ich weiß, dass dies eine alte Frage ist, aber ich möchte sie ergänzen. Ich bevorzuge den Ansatz, den titleHeaderWert auf Null zu setzen , anstatt den Wert heightForHeaderInSectionauf 0 zu setzen, da dies zu Problemen mit indexPath+1 führen kann, da der Header immer noch vorhanden, aber verborgen ist.

Wenn dies gesagt ist und Sie auf der Antwort von DBD aufbauen , können Sie titleForHeaderInSection:für Abschnitte ohne Zeilen wie folgt den Wert auf Null setzen :

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    if ([tableView.dataSource tableView:tableView numberOfRowsInSection:section] == 0) {
        return nil;
    } else {
        // return your normal return
    }
}
gav
quelle
7

Im Jahr 2015 mit iOS 8 und Xcode 6 hat Folgendes für mich funktioniert:

/* Return the title for each section if and only if the row count for each section is not 0. */

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

    if ([tableView.dataSource tableView:tableView numberOfRowsInSection:section] == 0) {
        return nil;
    }else{

    // here you want to return the title or whatever string you want to return for the section you want to display

    return (SomeObject*)someobjectArray[section].title;
    }
}
Ronaldoh1
quelle
5

Dies scheint der richtige Weg zu sein. Es wird korrekt animiert und funktioniert sauber ... wie von Apple beabsichtigt ...

Stellen Sie dem tableView-Delegaten die entsprechenden Informationen zur Verfügung

Wenn keine Elemente im Abschnitt vorhanden sind, geben Sie 0.0f in zurück:

-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section

..Auch zurück Null für:

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

Führen Sie die entsprechende Datenentfernung für tableView durch

  1. Anruf [tableView beginUpdates];
  2. Entfernen Sie Elemente aus Ihrer dataSource und verfolgen Sie, wo Elemente entfernt wurden.
  3. Rufen Sie deleteRowsAtIndexPathsmit den indexPaths der Zellen auf, die Sie entfernt haben.
  4. Wenn Ihre Datenquelle keine Elemente enthält (hier erhalten Sie nur den Header). Rufen Sie reloadSections:an, um diesen Abschnitt neu zu laden. Dadurch wird die richtige Animation ausgelöst und der Header ausgeblendet / verschoben / ausgeblendet.
  5. Rufen Sie abschließend [tableView endUpdates];an, um das Update abzuschließen.
Andres Canella
quelle
1
Vielen Dank für den Tipp zu reloadSections: :-) Mit iOS11 kann ich immer noch nichts zum Laufen bringen.
Etwas
Warum müssen wir anrufen reloadSections? Ich habe festgestellt, dass sich meine Kopfzeilen der Tabellenansicht überlappen, wenn ich sie nicht aufrufe (bis ich einen Bildlauf durchführe, wird die richtige Kopfzeile angezeigt).
Supertecnoboff
2

Swift 4.2

Setzen Sie heightForHeaderInSection auf Null. Wenn Sie eine benutzerdefinierte Schnittansicht haben, setzen Sie sie für Abschnitte ohne Zellen auf Null.

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

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

        return tableView.dataSource?.tableView(tableView, numberOfRowsInSection: section) == 0 ? nil: headerView(tableView: tableView, section: section)
    }
user550088
quelle