So verbergen Sie den Header des ersten Abschnitts in UITableView (gruppierter Stil)

108

Da sich das Design von Tabellenansichten mit dem gruppierten Stil mit iOS 7 erheblich geändert hat, möchte ich den Header des ersten Abschnitts ausblenden (oder entfernen). Bisher habe ich es nicht geschafft.

Etwas vereinfacht sieht mein Code folgendermaßen aus:

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

Wenn ich eine Höhe von 0 zurückgebe, werden die beiden anderen Methoden niemals mit dem Abschnittsindex 0 aufgerufen. Es wird jedoch weiterhin ein leerer Abschnittskopf mit der Standardhöhe gezeichnet. (In iOS 6 werden die beiden Methoden aufgerufen. Das sichtbare Ergebnis ist jedoch dasselbe.)

Wenn ich einen anderen Wert zurückgebe, erhält der Abschnittskopf die angegebene Höhe.

Wenn ich 0,01 zurückgebe, ist es fast richtig. Wenn ich jedoch im Simulator "Farbfehlausgerichtete Bilder" aktiviere, werden alle Zellen der Tabellenansicht markiert (was eine logische Konsequenz zu sein scheint).

Die Antworten auf die Frage UITableView: Header vor leerem Abschnitt ausblenden scheinen darauf hinzudeuten, dass es einigen Personen gelungen ist, den Header des Abschnitts auszublenden. Dies kann jedoch auch für den einfachen Stil gelten (anstelle des gruppierten Stils).

Der bisher beste Kompromiss ist die Rückgabe der Höhe 0,5, was zu einer etwas dickeren Linie unterhalb der Navigationsleiste führt. Ich würde mich jedoch freuen, wenn jemand weiß, wie der Header des ersten Abschnitts vollständig ausgeblendet werden kann.

Aktualisieren

Laut der Analyse von caglar ( https://stackoverflow.com/a/19056823/413337 ) tritt das Problem nur auf, wenn die Tabellenansicht in einem Navigationscontroller enthalten ist.

Codo
quelle
Ich habe diesen Teil nicht erhalten => if (section == 0) return view; return nil; dh eine Ansicht zurückgeben, wenn es der erste Abschnitt ist und sonst nichts?
Zen
Die Idee ist, eine Ansicht mit einer Höhe von 0 für den ersten Abschnitt und null für alle anderen Abschnitte zurückzugeben, sodass die Tabellenansicht die Standardheaderansicht für sie verwendet. Der Nullteil funktioniert gut; Die Tabellenansicht zeigt eine Kopfzeile für diese Abschnitte. Der Teil für Abschnitt 0 ist jedoch irrelevant, da die Methode niemals mit aufgerufen wird section == 0.
Codo
1
Diese Antwort scheint kurz und bündig zu sein. stackoverflow.com/a/23955420/3965
Mr Rogers

Antworten:

154

Ich habe eine Problemumgehung, die mir einigermaßen sauber erscheint. Also beantworte ich meine eigene Frage.

Da 0 als Höhe der Kopfzeile des ersten Abschnitts nicht funktioniert, gebe ich 1 zurück. Dann verwende ich das contentInset , um diese Höhe unter der Navigationsleiste auszublenden.

Ziel 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);
}

Schnell:

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)
}
Codo
quelle
6
Die Verwendung einer Headerhöhe von 0,1 f ist noch besser, um sie auszublenden.
Chuck Krutsinger
4
Ich habe versucht, 0.1f zu verwenden. Das Ergebnis ist jedoch, dass Zeichnungen nicht mehr an Pixeln ausgerichtet sind, was zu Unschärfen und Leistungseinbußen führt. Probieren Sie es einfach im Simulator aus: Es gibt eine Option, um problematische Ausrichtung hervorzuheben.
Codo
31
Tatsächlich besteht eine bessere Implementierung (die in Zukunft weniger wahrscheinlich ist) darin, CGFLOAT_MINanstelle eines fest codierten Werts zu verwenden. Mit anderen Worten, nicht return 1.0foder 0.1fstattdessen: return CGFLOAT_MINWenn Apple jemals den akzeptablen Mindestwert ändert, müssen Sie den Code ändern, wenn Sie den Rückgabewert fest codieren. Außerdem wissen Sie bereits nicht, ob Sie den kleinstmöglichen Wert verwenden. Wenn Sie die definierte Konstante verwenden, wird garantiert der kleinstmögliche Wert verwendet, und Ihr Code überlebt Änderungen am Betriebssystem.
Chris Ostmo
11
@ Chris: Ich fürchte, du hast die Idee nicht verstanden. Ich gebe keinen sehr kleinen Wert zurück, sondern ein Vielfaches der Größe eines Pixels, damit die Zeichnung pixelausgerichtet bleibt (für gute Leistung und Schärfe). Ich habe es dann mit dem Inhaltseinsatz versetzt. Es ist unwahrscheinlich, dass sich dies in Zukunft ändert, da es sich um eine beträchtliche, sichtbare Entfernung handelt, die das Betriebssystem nicht ignorieren könnte.
Codo
8
+1 Wenn keine gebrochenen Pixelwerte als UI-Offsets verwendet werden.
Ricardo Sanchez-Saez
52

So wird der erste Abschnittskopf in UITableView (gruppierter Stil) ausgeblendet.

Swift 3.0 & Xcode 8.0 Lösung

  1. Der Delegat von TableView sollte die Methode heightForHeaderInSection implementieren

  2. Geben Sie innerhalb der heightForHeaderInSection-Methode die am wenigsten positive Zahl zurück. (nicht Null!)

    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
    }
user3378170
quelle
6
Die Rückgabe von CGFloat.leastNonzeroMagnitude anstelle von 0 hat mir geholfen. Vielen Dank!
anoo_radha
Perfekte Antwort, danke
Pierre
Übrigens, CGFLOAT_MINdenn objc ist identisch mit CGFloat.leastNonzeroMagnitudein Swift
DawnSong
36

Die Antwort war sehr lustig für mich und mein Team und wirkte wie ein Zauber

  • Verschieben Sie im Interface Builder einfach die Tabellenansicht unter eine andere Ansicht in der Ansichtshierarchie.

GRUND:

Wir haben festgestellt, dass dies nur für die erste Ansicht in der Ansichtshierarchie geschieht, wenn diese erste Ansicht eine UITableView ist . Alle anderen ähnlichen UITableViews haben diesen nervigen Abschnitt außer dem ersten nicht. Wir haben versucht, UITableView von der ersten Stelle in der Ansichtshierarchie zu entfernen, und alles hat wie erwartet funktioniert.

Giorgos Ath
quelle
1
Haben Sie immer noch den Milchglaseffekt der Navigationsleiste, wenn Sie durch die Tabellenansicht scrollen?
Codo
Sie haben diesen Unschärfeeffekt , wenn Sie Ihre tableView entsprechend einrichten. Sie müßten die festlegen , contentInsetum zum Beispiel {0, 64, 0, 0}der 64px von oben (Statusleiste und Navigationsleiste) versetzt zu haben. Die tableView muss oben am Bildschirm angehängt werden, nicht die topLayoutGuide (damit sie unter die Navigationsleiste gelangt)
Julian F. Weinert
Wenn Sie Pull nicht zum Aktualisieren verwenden, sieht dies gut aus.
Michael
2
Beeindruckend. Dies funktionierte für mich in iOS 9 und hat mich einfach umgehauen.
Zuteilung
Dies sollte die akzeptierte Antwort sein. So ein komischer Bug!
Oded Harth
25

Verwenden Sie diesen Trick für den gruppierten Typ tableView

Kopieren Sie den folgenden Code für Ihre Tabellenansicht in die viewDidLoad- Methode:

tableView.tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, tableView.bounds.size.width, 0.01f)];
Nitesh Borad
quelle
Ich habe es nicht ausprobiert, aber ich vermute, dass diese Lösung den gleichen Nachteil hat wie einige der anderen vorgeschlagenen Lösungen: Zeichnungen sind nicht mehr auf Pixel ausgerichtet, was zu Unschärfen und Leistungseinbußen führt. Der Simulator kann dies anzeigen: Er hat die Option, problematische Ausrichtungen hervorzuheben. Wenn es jedoch auf 0 abrundet, ist es in der Tat eine gute Lösung.
Codo
Ja, ich denke, es wird auf 0 abgerundet. Weil ich es oft benutzt habe, aber in Zeichnungen keine Unschärfe gefunden habe.
Nitesh Borad
TableHeaderView und Section Header View? Was ist der Unterschied,
AsifHabib
Oder etwas kürzer : _tableView.tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 1)].
Mojuba
@AsifHabib: tableHeaderView steht über allen Tabellenelementen. Es ist die Header-Ansicht für die Tabelle selbst. Die Abschnittsüberschriftenansicht ist eine Ansicht, die auf jedem Abschnitt platziert werden soll. Es kann viele Abschnittsüberschriftenansichten geben, die der angegebenen Anzahl von Abschnitten in der Tabelle entsprechen. Es wird jedoch nur eine Tabellenkopfansicht geben.
Nitesh Borad
21

Dieser Weg ist in Ordnung.

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 {
        ...
    }
}
TonnyTao
quelle
2
Dies ist eine schöne Variante meiner Lösung, außer dass Bruchwerte verwendet werden. Auf diese Weise werden Text und Bilder nicht mehr auf Pixel ausgerichtet, das Zeichnen wird verlangsamt und das Ergebnis kann unscharf werden. Der Simulator verfügt über die Option "Falsch ausgerichtete Farbbilder", um dieses Problem aufzudecken.
Codo
Funktioniert gut für Leute wie mich, die statische Zellen mit einem containerView verwenden
thibaut noah
3
Swift 3> 'CGFloat.min' wurde in 'CGFloat.leastNormalMagnitude' umbenannt
rjobidon
6

Ich habe gerade Ihren Code kopiert und versucht. Es läuft normal (im Simulator ausprobiert). Ich habe die Ergebnisansicht angehängt. Du willst so eine Ansicht, oder? Oder habe ich dein Problem falsch verstanden?

Geben Sie hier die Bildbeschreibung ein

Caglar
quelle
1
Ja, das ist im Grunde das, was ich will, außer dass sich meine Tabellenansicht in einem Navigationscontroller befindet. Könnte das den Unterschied machen?
Codo
2
Ich habe tableView zum Navigationscontroller hinzugefügt und Ihre Situation wird angezeigt :) Ich denke, in iOS 7 wurde diese Headerhöhe standardmäßig in der gruppierten Tabellenansicht korrigiert. Durch Ändern des Frames von tableView kann die erste Header-Ansicht ausgeblendet werden (wie z. B. set x = 0 y = -40). Ich weiß jedoch, dass diese Lösung keine gute Lösung ist.
Caglar
1
Vielen Dank für Ihre Arbeit. Es scheint also, dass das Problem nur auftritt, wenn die Tabellenansicht den gruppierten Stil verwendet und in einem Navigationscontroller enthalten ist.
Codo
Beim Versuch, von viewcontroller zu tableviewcontroller zu wechseln, konnte ich das Problem mit dem Header nicht beheben. Vielleicht fehlt mir etwas, das versucht, es umzuwandeln. (iOS 7.0.3 sim)
Evgeni Petrov
1
Dieses Problem tritt auch in diesem Schnappschuss auf! Die 0. Zelle beginnt nicht bei x: 0.0f & y: 0.0f.
Burhanuddin Sunelwala
6

Swift3: heightForHeaderInSection funktioniert mit 0, Sie müssen nur sicherstellen, dass der Header auf clipsToBounds gesetzt ist.

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

Wenn Sie clipsToBounds nicht festlegen, wird beim Scrollen der versteckte Header angezeigt.

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

    header.clipsToBounds = true
}
h.martin
quelle
1
clipsToBound = true ist sehr wichtig, wenn Sie die Abschnittsüberschriftenansicht vollständig ausblenden möchten. Das Festlegen der Höhe auf 0 / CGFLOAT_MIN reicht nicht aus.
Altimac
5

Update [19.9.17]: Die alte Antwort funktioniert in iOS 11 nicht mehr für mich. Danke Apple. Folgendes tat:

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

Vorherige Antwort:

Wie in den Kommentaren von Chris Ostomo gepostet, hat Folgendes für mich funktioniert:

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    return CGFLOAT_MIN; // to get rid of empty section header
}
Manindra Moharana
quelle
Ich vermute, dass der Inhalt Ihrer Tabellenansicht nicht mehr auf Pixel ausgerichtet ist, was zu Unschärfen und Leistungseinbußen führt. Der Simulator kann dies anzeigen: Er hat die Option, problematische Ausrichtungen hervorzuheben. Wenn es jedoch auf 0 abrundet, ist es in der Tat eine gute Lösung.
Codo
Nein, ich habe keine inhaltlichen Probleme bemerkt. Einschränkungen schienen in Ordnung zu sein.
Manindra Moharana
1
Welp! Funktioniert nicht mehr in iOS 11! Mein Fix dauerte weniger als eine Woche. 😞
Manindra Moharana
4

So entfernen Sie den Header des oberen Abschnitts in einer gruppierten UITableView in Swift:

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

In Swift 4.2 und vielen früheren Versionen können Sie, anstatt die Höhe des ersten Headers wie in den anderen Antworten auf 0 zu setzen, einfach die anderen Header auf setzen nil. Angenommen, Sie haben zwei Abschnitte und möchten nur, dass der zweite (dh 1) einen Header enthält. Diese Überschrift enthält den Text Foobar :

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

Versuchen Sie dies, wenn Sie alle Abschnittsüberschriften vollständig entfernen möchten

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

func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
    return CGFloat.leastNormalMagnitude
}
Avinash
quelle
Das brauche ich nur. Eine einfache und unkomplizierte Lösung. 1+
iGhost
0

Ich kann noch keinen Kommentar abgeben, dachte aber, ich würde hinzufügen, dass das Einstellen der Höhe des ersten Abschnitts auf 0 in tatsächlich funktioniert , wenn Sie einen UISearchControllerauf Ihrem Controller UISearchBarals Ihren tableHeaderViewhaben heightForHeaderInSection.

Ich benutze, self.tableView.contentOffset = CGPointMake(0, self.searchController.searchBar.frame.size.height);damit die Suchleiste standardmäßig ausgeblendet ist.

Das Ergebnis ist, dass für den ersten Abschnitt keine Überschrift vorhanden ist. Wenn Sie nach unten scrollen, wird die Suchleiste direkt über der ersten Zeile angezeigt.

Raesu
quelle
0

Bei weitem am einfachsten ist es, zurückzukehren niloder ""in func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String?einen Abschnitt zu gelangen, in dem Sie keine Kopfzeile anzeigen möchten.

Vilém Kurz
quelle
0

Swift-Version: Swift 5.1
Meistens können Sie die Höhe in tableView-Delegaten wie folgt festlegen:

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
}

Wenn Sie UITableView mit Xib oder Storyboard erstellt haben, funktioniert die Antwort von up manchmal nicht. Sie können die zweite Lösung ausprobieren:

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

Hoffe es funktioniert bei dir!

Mistdon
quelle