Jak ukryć nagłówek pierwszej sekcji w UITableView (styl zgrupowany)

108

Ponieważ projekt widoków tabel używających stylu zgrupowanego znacznie się zmienił w iOS 7, chciałbym ukryć (lub usunąć) nagłówek pierwszej sekcji. Jak dotąd nie udało mi się tego osiągnąć.

Nieco uproszczony mój kod wygląda następująco:

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

Jeśli zwrócę wysokość 0, pozostałe dwie metody nigdy nie zostaną wywołane z indeksem sekcji 0. Jednak pusty nagłówek sekcji jest nadal rysowany z domyślną wysokością. (W iOS 6 te dwie metody są wywoływane. Jednak widoczny wynik jest taki sam).

Jeśli zwrócę inną wartość, nagłówek sekcji otrzyma określoną wysokość.

Jeśli zwrócę 0,01, jest prawie poprawne. Jednak kiedy włączam w symulatorze "Niepoprawne kolory", oznacza to wszystkie komórki widoku tabeli (co wydaje się logiczną konsekwencją).

Odpowiedzi na pytanie UITableView: ukryj nagłówek z pustej sekcji wydają się wskazywać, że niektórym osobom udało się ukryć nagłówek sekcji. Ale może to dotyczyć stylu prostego (zamiast zgrupowanego).

Jak dotąd najlepszym kompromisem jest zwrócenie wysokości 0,5, co skutkuje nieco grubszą linią poniżej paska nawigacji. Byłbym jednak wdzięczny, gdyby ktoś wiedział, jak można całkowicie ukryć nagłówek pierwszej sekcji.

Aktualizacja

Według analizy caglara ( https://stackoverflow.com/a/19056823/413337 ) problem pojawia się tylko wtedy, gdy widok tabeli jest zawarty w kontrolerze nawigacyjnym.

Codo
źródło
Nie dostałem tej części => if (section == 0) return view; return nil; tj. zwracanie widoku, gdy jest to pierwsza sekcja i nil w przeciwnym razie?
Zen,
Pomysł polega na zwróceniu widoku o wysokości 0 dla pierwszej sekcji i zwróceniu nil dla wszystkich innych sekcji, aby widok tabeli używał dla nich domyślnego widoku nagłówka. Część zerowa ładnie działa; widok tabeli pokazuje nagłówek tych sekcji. Ale część dla sekcji 0 jest nieistotna, ponieważ metoda nigdy nie jest wywoływana with section == 0.
Codo,
1
Ta odpowiedź wydaje się krótka i słodka. stackoverflow.com/a/23955420/3965
Mr Rogers

Odpowiedzi:

154

Mam obejście, które wydaje mi się dość czyste. Więc odpowiadam na własne pytanie.

Ponieważ 0, ponieważ wysokość nagłówka pierwszej sekcji nie działa, zwracam 1. Następnie używam contentInset, aby ukryć tę wysokość pod paskiem nawigacji.

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

Szybki:

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
źródło
6
Użycie wysokości nagłówka 0,1f jest jeszcze lepsze do jego ukrycia.
Chuck Krutsinger
4
Próbowałem użyć 0.1f. W rezultacie rysunki nie są już wyrównane do pikseli, co powoduje rozmycie i zmniejsza wydajność. Po prostu wypróbuj to w symulatorze: ma opcję podkreślenia problematycznego wyrównania.
Codo
31
W rzeczywistości lepszą implementacją (rzadziej zepsuje się w przyszłości) jest użycie CGFLOAT_MINzamiast wartości zakodowanej na stałe. Innymi słowy, nie rób tego return 1.0flub 0.1fzamiast tego, return CGFLOAT_MINjeśli Apple kiedykolwiek zmieni minimalną dopuszczalną wartość, będziesz mieć kod do zmiany, jeśli zakodujesz wartość zwracaną na stałe. Ponadto nie wiesz już, czy używasz najmniejszej możliwej wartości. Używając zdefiniowanej stałej, masz gwarancję, że użyjesz najmniejszej możliwej wartości, a Twój kod przetrwa zmiany systemu operacyjnego.
Chris Ostmo,
11
@Chris: Obawiam się, że nie masz pomysłu. Nie zwracam bardzo małej wartości, ale wielokrotność rozmiaru piksela, aby rysunek pozostał wyrównany do pikseli (dla dobrej wydajności i wyrazistości). Następnie wyrównuję to za pomocą wstawki zawartości. Jest mało prawdopodobne, aby zmieniło się to w przyszłości, ponieważ jest to znaczna, widoczna odległość, a system operacyjny nie może tego zignorować.
Codo,
8
+1 Za niestosowanie ułamkowych wartości pikseli jako przesunięć interfejsu użytkownika.
Ricardo Sanchez-Saez
52

Oto jak ukryć nagłówek pierwszej sekcji w UITableView (styl zgrupowany).

Rozwiązanie Swift 3.0 i Xcode 8.0

  1. Delegat TableView powinien implementować metodę heightForHeaderInSection

  2. W ramach metody heightForHeaderInSection zwróć najmniejszą liczbę dodatnią. (nie zero!)

    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
źródło
6
zwrócenie CGFloat.leastNonzeroMagnitude zamiast 0 pomogło mi. Dzięki!
anoo_radha
Doskonała odpowiedź, dzięki
Pierre
Nawiasem mówiąc, CGFLOAT_MINdla objc jest identyczny jak CGFloat.leastNonzeroMagnitudew Swift
DawnSong
36

Odpowiedź była bardzo zabawna dla mnie i dla mojego zespołu i zadziałała jak urok

  • W programie Interface Builder po prostu przenieś widok tabeli pod inny widok w hierarchii widoków.

POWÓD:

Zauważyliśmy, że dzieje się tak tylko w przypadku pierwszego widoku w hierarchii widoków, jeśli ten pierwszy widok jest UITableView . Tak więc wszystkie inne podobne UITableViews nie mają tej irytującej sekcji, z wyjątkiem pierwszej. Próbowaliśmy przenieść widok UITableView z pierwszego miejsca w hierarchii widoków i wszystko działało zgodnie z oczekiwaniami.

Giorgos Ath
źródło
1
Czy nadal masz efekt matowego szkła na pasku nawigacyjnym podczas przewijania widoku tabeli?
Codo,
Trzeba będzie to rozmycie efekt podczas konfigurowania tableView odpowiednio. Musiałbyś contentInsetna przykład {0, 64, 0, 0}ustawić przesunięcie 64px od góry (pasek stanu plus pasek nawigacji). The tableView musi być przymocowany na górze ekranu, a nie topLayoutGuide (do niech dotrzeć pod paskiem nawigacyjnym)
Julian F. Weinert
Jeśli nie używasz ściągania do odświeżania, wyglądałoby to dobrze.
Michael
2
Łał. To zadziałało dla mnie w iOS 9 i po prostu mnie rozwaliło.
przydziel
To powinna być akceptowana odpowiedź. Taki dziwny błąd!
Oded Harth
25

Użyj tej sztuczki dla grupowego typu tableView

Skopiuj wklej poniższy kod dla widoku tabeli w metodzie viewDidLoad :

tableView.tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, tableView.bounds.size.width, 0.01f)];
Nitesh Borad
źródło
Nie próbowałem tego, ale podejrzewam, że to rozwiązanie ma tę samą wadę, co niektóre inne proponowane rozwiązania: rysunki nie są już wyrównane do pikseli, co powoduje rozmycie i zmniejsza wydajność. Symulator może to ujawnić: ma opcję podkreślenia problematycznego wyrównania. Jeśli jednak zaokrągli się w dół do 0, to rzeczywiście jest to dobre rozwiązanie.
Codo
Tak, myślę, że zaokrągla w dół do 0. Ponieważ używałem go wiele razy, ale nie znalazłem żadnego rozmycia na rysunkach.
Nitesh Borad
TableHeaderView i widok nagłówka sekcji? jaka jest różnica,
AsifHabib
Lub nieco krócej: _tableView.tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 1)].
mojuba
@AsifHabib: tableHeaderView jest umieszczane na górze wszystkich elementów tabeli. To widok nagłówka samej tabeli. Widok nagłówka sekcji to widok, który ma być umieszczony w każdej sekcji. Może istnieć wiele widoków nagłówków sekcji zgodnie z liczbą sekcji w tabeli. Ale będzie tylko jeden widok nagłówka tabeli.
Nitesh Borad
21

ten sposób jest OK.

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
źródło
2
To fajna odmiana mojego rozwiązania, z wyjątkiem tego, że używa wartości ułamkowych. W ten sposób tekst i obrazy nie są już wyrównane do pikseli, rysowanie jest spowolnione, a wynik może być rozmazany. Symulator ma opcję „Niewyrównane kolory”, aby ujawnić ten problem.
Codo
Działa dobrze dla ludzi takich jak ja, z wykorzystaniem komórek statyczne z containerView
Thibaut Noego
3
Swift 3> „CGFloat.min” został przemianowany na „CGFloat.leastNormalMagnitude”
rjobidon
6

Właśnie skopiowałem twój kod i spróbowałem. Działa normalnie (wypróbowane w symulatorze). Załączam widok wyniku. Chcesz takiego widoku, prawda? Albo źle zrozumiałem twój problem?

wprowadź opis obrazu tutaj

caglar
źródło
1
Tak, w zasadzie tego chcę, z wyjątkiem tego, że mój widok tabeli znajduje się w kontrolerze nawigacyjnym. Czy to może mieć znaczenie?
Codo,
2
Dodałem tableView do kontrolera nawigacji i twoja sytuacja się pojawia :) Myślę, że w iOS 7 ta poprawka wysokości nagłówka jest domyślnie w widoku tabeli w stylu grupowania. Zmieniając ramkę tableView, można ukryć pierwszy widok nagłówka (jak set x = 0 y = -40). Wiem jednak, że to rozwiązanie nie jest dobre.
caglar
1
Bardzo dziękuję za Twoją pracę. Wydaje się więc, że problem pojawia się tylko wtedy, gdy widok tabeli używa stylu zgrupowanego i jest zawarty w kontrolerze nawigacyjnym.
Codo
Próbując zmienić kontroler viewcontroller na tableviewcontroller, nie udało mi się naprawić problemu z nagłówkiem. Może brakuje mi czegoś, próbując go przekonwertować. (iOS 7.0.3 sim)
Evgeni Petrov
1
Ten problem pojawia się również w tej migawce! komórka 0 nie zaczyna się od x: 0,0f i y: 0,0f.
Burhanuddin Sunelwala
6

Swift3: heightForHeaderInSection działa z 0, musisz tylko upewnić się, że nagłówek jest ustawiony na clipsToBounds.

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

jeśli nie ustawisz clipsToBounds, ukryty nagłówek będzie widoczny podczas przewijania.

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

    header.clipsToBounds = true
}
h.martin
źródło
1
clipsToBound = true jest bardzo ważne, jeśli planujesz całkowicie ukryć widok nagłówka sekcji. Ustawienie jego wysokości na 0 / CGFLOAT_MIN nie wystarczy.
Altimac
5

Aktualizacja [19.09.17]: Stara odpowiedź nie działa już dla mnie w iOS 11. Dzięki Apple. Zrobili to:

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

Poprzednia odpowiedź:

Jak napisał w komentarzach Chrisa Ostomo, działały dla mnie:

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    return CGFLOAT_MIN; // to get rid of empty section header
}
Manindra Moharana
źródło
Podejrzewam, że zawartość widoku tabeli nie jest już wyrównana do pikseli, co powoduje rozmycie i zmniejsza wydajność. Symulator może to ujawnić: ma opcję podkreślenia problematycznego wyrównania. Jeśli jednak zaokrągli się w dół do 0, to rzeczywiście jest to dobre rozwiązanie.
Codo
Nie, nie zauważyłem żadnych problemów z zawartością. Ograniczenia wydawały się w porządku.
Manindra Moharana
1
Welp! Nie działa już w iOS 11! Moja poprawka trwała niecały tydzień .. 😞
Manindra Moharana
4

Oto jak pozbyć się nagłówka górnej sekcji w zgrupowanym UITableView w Swift:

tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: CGFloat.leastNormalMagnitude))
Harris
źródło
3

W Swift 4.2 i wielu wcześniejszych wersjach, zamiast ustawiać wysokość pierwszego nagłówka na 0, jak w innych odpowiedziach, możesz po prostu ustawić inne nagłówki na nil. Powiedzmy, że masz dwie sekcje i chcesz, aby tylko druga (tj. 1) Miała nagłówek. Ten nagłówek będzie miał tekst Foobar :

override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    return section == 1 ? "Foobar" : nil
}
JaneGoodall
źródło
3

Spróbuj tego, jeśli chcesz całkowicie usunąć cały nagłówek sekcji

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

func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
    return CGFloat.leastNormalMagnitude
}
Avinash
źródło
Właśnie tego potrzebuję. Proste i łatwe rozwiązanie. 1+
iGhost
0

Nie mogę jeszcze komentować, ale pomyślałem, że dodam, że jeśli masz UISearchControllerna kontrolerze UISearchBarjako swój tableHeaderView, ustawienie wysokości pierwszej sekcji na 0 heightForHeaderInSectioncali rzeczywiście działa.

Używam self.tableView.contentOffset = CGPointMake(0, self.searchController.searchBar.frame.size.height);tak, że pasek wyszukiwania jest domyślnie ukryty.

W rezultacie nie ma nagłówka dla pierwszej sekcji, a przewijanie w dół pokaże pasek wyszukiwania tuż nad pierwszym wierszem.

Raesu
źródło
0

Najłatwiej jest zdecydowanie wrócić nil, lub ""w func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String?odniesieniu do segmentu, w którym nie chcesz wyświetlać nagłówka.

Vilém Kurz
źródło
0

Wersja Swift: Swift 5.1
Przeważnie możesz ustawić wysokość w delegacie tableView w następujący sposób:

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
}

Czasami, gdy utworzyłeś UITableView z Xib lub Storyboard, odpowiedź up nie działa. możesz wypróbować drugie rozwiązanie:

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

Mam nadzieję, że to działa dla Ciebie!

mistdon
źródło