Dostosuj sekcję nagłówka UITableView

141

Chcę dostosować UITableViewnagłówek dla każdej sekcji. Do tej pory wdrożyłem

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

ta UITabelViewDelegatemetoda. Chcę uzyskać bieżący nagłówek dla każdej sekcji i po prostu dodać go UILabeljako widok podrzędny.

Jak dotąd nie jestem w stanie tego zrobić. Ponieważ nie mogłem znaleźć niczego, aby uzyskać domyślny nagłówek sekcji. Pierwsze pytanie, czy istnieje sposób na uzyskanie domyślnego nagłówka sekcji ?

Jeśli nie jest to możliwe, muszę utworzyć widok kontenera, który jest UIViewale, tym razem muszę ustawić domyślny kolor tła, kolor cienia itp. Ponieważ, jeśli dokładnie przyjrzysz się nagłówkowi sekcji, jest on już dostosowany.

Jak mogę uzyskać te domyślne wartości dla każdego nagłówka sekcji?

Dziękuję wam wszystkim.

limon
źródło
1
Co jest złego w używaniu tableView:titleForHeaderInSection:?
borrrden
Zwraca a NSString, muszę ustawić niestandardową czcionkę, więc nie mogę, jeśli używamtableView:titleForHeaderInSection:
Limon
Możesz też użyć obrazów, aby naśladować domyślne nagłówki sekcji. teehanlax.com/blog/ios-6-gui-psd-iphone-5
Desdenova
@limon: Jak zaimplementować nagłówek sekcji: stackoverflow.com/a/32261262/1457385
shallowThought

Odpowiedzi:

288

Możesz spróbować tego:

 -(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;
}
Lochana Ragupathy
źródło
to jest twój kolor bg, jaki kolor chcesz ustawić, możesz
Lochana Ragupathy
To jest problem, już zrobiłem to, co napisałeś. Ale nie znam domyślnego koloru tła nagłówka sekcji, który jest trochę szary. Ale potrzebuję, aby był to dokładnie domyślny nagłówek sekcji.
limon,
15
hej, chodź do użytku Cyfrowy kolorowy miernik
Lochana Ragupathy
upewnij się, że ustawiłeś również backgroundColor UILabel. Wiem, że byłem trochę zdezorientowany, kiedy moje tło nie było dla mnie jasne.
shulmey,
3
co to jest lista w linii NSString * string = [lista objectAtIndex: sekcja]; każdy może mi powiedzieć
Nisha Gupta
45

Wybrana odpowiedź za pomocą tableView :viewForHeaderInSection:jest poprawna.

Po prostu podziel się wskazówką tutaj.

Jeśli używasz storyboard / xib, możesz utworzyć kolejną prototypową komórkę i użyć jej jako „komórki sekcji”. Kod służący do konfigurowania nagłówka jest podobny do sposobu konfigurowania komórek wierszy.

- (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;
}
samwize
źródło
14
w tym rozwiązaniu jest wiele błędów. Pierwszą z nich jest fakt, że jeśli zaimplementujesz "tableView (tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool", zauważysz, że nagłówek sekcji będzie przesuwał się wraz z wierszem podczas przesuwania. Aby tego uniknąć, należy zamiast tego zwrócić cell.contentView. Większym problemem jest fakt, że w przypadku tego rozwiązania aplikacja ulegnie awarii po długim naciśnięciu nagłówka sekcji. Poprawnym sposobem jest utworzenie końcówki, która rozszerza UITableViewHeaderFooterView, zarejestrowanie jej w widoku tabeli i zwrócenie jej w tej metodzie. Testowane na iOS8
Kachi,
@Kachi Rozwiązaniem jest użycie viewForHeaderInSectionnie canEditRowAtIndexPathjak wspomniano. Nigdy nie weryfikuję awarii, o której mówiłeś, ale czy możesz wyjaśnić, jak długie naciśnięcie spowoduje awarię?
samwize
1
chodziło mi o to, że jeśli zaimplementujesz to rozwiązanie ORAZ zaimplementujesz canEditRowAtIndexPath, zobaczysz, że nagłówek przesunie się również z najwyższym wierszem, który usuwasz, jeśli nie zwrócisz cell.contentView. Zobacz ten post dotyczący SO: stackoverflow.com/questions/26009722/… Długie naciśnięcie powoduje awarię, ponieważ wiadomość próbuje zostać wysłana do zwolnionego obiektu. Zobacz ten wpis SO: stackoverflow.com/questions/27622290/ ...
Kachi
1
Nigdy nie używaj UITableViewCelljako widoku nagłówka. Będziesz bardzo trudno debugować wizualne usterki - nagłówek czasami znika z powodu tego, jak komórki są usuwane z kolejki i będziesz szukał przez wiele godzin, dlaczego tak jest, dopóki nie zorientujesz się, UITableViewCellże nie należy do UITableViewnagłówka.
raven_raven
Używanie UITableViewCelljako nagłówka jest po prostu niewłaściwe.
Alex Zavatone
31

Szybka wersja Lochana Tejas odpowiedź:

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
}
estemendoza
źródło
1
jak sprawić, by wysokość etykiety była dynamiczna zgodnie z tekstem znajdującym się wewnątrz widoku?
Pratik Shah
Słowo overridekluczowe jest zbędne. Co więcej, rozważ ponowne użycie widoków nagłówków zamiast ich ponownego tworzenia.
Vadim Bulavin,
17

Jeśli używasz domyślnego widoku nagłówka, możesz zmienić tylko tekst w nim za pomocą

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

Dla Swift:

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

Jeśli chcesz dostosować widok, musisz samodzielnie stworzyć nowy.

Mert
źródło
10

dlaczego nie użyć UITableViewHeaderFooterView ?

user836773
źródło
Możesz użyć tego tylko wtedy, gdy nie używasz również sekcji - (UIView *) tableView: (UITableView *) tableView viewForHeaderInSection: (NSInteger).
SAHM
1
Doskonale poprawna odpowiedź. Ponadto korzystanie z UITableViewHeaderFooterView korzysta z recyklingu widoku, podobnie jak w przypadku komórek.
Gregzo
6
@dmarsi Nie znalazłem żadnych dowodów na to, że są przestarzałe.
Fawkes
8

Jeśli headerInSection nie jest wyświetlany, możesz spróbować tego.

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

Zwraca wysokość nagłówka danej sekcji.

Kathen
źródło
1
Masz ochotę rozwinąć swoją odpowiedź?
CinCout
Sekcja nagłówka nie będzie wyświetlana, chyba że określisz za pomocą metody hook 'wysokość' nagłówka sekcji. UITableView domyślnie nie wyświetla nagłówków, jeśli nie określono wysokości. @CinCout
theprojectabot
6

Swift 3 wersja lochana i estemendoza odpowiedzi:

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

}

Pamiętaj również, że musisz TAKŻE zaimplementować:

override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return 100;
}
Adam
źródło
5

Spróbuj tego......

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
}
Gigi
źródło
5

Inne odpowiedzi dobrze sobie radzą z odtwarzaniem domyślnego widoku nagłówka, ale tak naprawdę nie odpowiadają na twoje główne pytanie:

czy istnieje sposób na uzyskanie domyślnego nagłówka sekcji?

Jest na to sposób - po prostu zaimplementuj tableView:willDisplayHeaderView:forSection:w swoim delegacie. Domyślny widok nagłówka zostanie przekazany do drugiego parametru, a stamtąd możesz go UITableViewHeaderFooterViewprzesłać do, a następnie dodać / zmienić podglądy według własnego uznania.

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

Szybki

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
}
Craig Brown
źródło
Nie musisz go rzucać. Możesz po prostu dodać to, co chcesz do widoku. W rzeczywistości utworzenie nowego obiektu nic nie da, dopóki go nie przypiszesz view.
Alex Zavatone
@AlexZavatone Zgadza się, nie musisz go przesyłać, jeśli tylko dodajesz widoki. Jest to pomocne, jeśli chcesz dostosować niektóre domyślne widoki, takie jak etykieta tekstowa.
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;
}
Boris Nikolic
źródło
4

To najłatwiejsze możliwe rozwiązanie. Poniższego kodu można użyć bezpośrednio do utworzenia niestandardowego nagłówka sekcji.

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

UWAGA: SectionHeaderTableViewCell to niestandardowy UITableViewCell utworzony w Storyboard.

Anish Kumar
źródło
SectionHeaderTableViewCell - użycie niezadeklarowanego identyfikatora
Boris Gafurov
@BorisGafurov SectionHeaderTableViewCell to tylko przykładowa nazwa, którą nadałem mojemu UITableViewCell, który utworzyłem w scenorysie.
Anish Kumar
2

Na twoim miejscu stworzyłbym metodę, która zwraca UIView z podanym NSString, który ma zawierać. Na przykład

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

W implementacji tej metody utwórz UIView, dodaj do niego UILabel z właściwościami, które chcesz ustawić, i oczywiście ustaw jego tytuł na podany.

cpprulez
źródło
Tak, mogę to zrobić, ale moje pytanie brzmi: jak mogę uzyskać domyślne tło nagłówka sekcji, wartość cienia, reszta jest łatwa do zaimplementowania.
limon,
co masz na myśli jako domyślne tło nagłówka sekcji
Lochana Ragupathy
1
Cóż, najłatwiej byłoby użyć aplikacji Digital Color Meter, aby uzyskać żądane kolory. Biorąc je kodem byłoby trudne, o ile wiem ...
cpprulez
2

Rozwiązanie @ samwize w języku Swift (więc popieraj go!). Genialne użycie tego samego mechanizmu recyklingu również dla sekcji nagłówka / stopki:

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

    return settingsHeaderSectionCell
}
Javier Calatrava Llavería
źródło
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]];
    }
}

Jeśli chcesz zmienić czcionkę textLabel w nagłówku sekcji, chcesz to zrobić w willDisplayHeaderView. Aby ustawić tekst, możesz to zrobić w viewForHeaderInSection lub titleForHeaderInSection. Powodzenia!

John Ottenlips
źródło
2

Pełny przykład 2019 do skopiowania i wklejenia

Pierwszy zestaw „Zgrupowany” w scenorysie: musi to nastąpić w czasie początkowym, nie można tego ustawić później, więc łatwiej jest zapamiętać, aby zrobić to na scenorysie:

wprowadź opis obrazu tutaj

Kolejny,

Musi zaimplementować heightForHeaderInSection z powodu błędu Apple.

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

Wciąż istnieje błąd Apple - od dziesięciu lat - w którym po prostu nie wyświetla pierwszego nagłówka (tj. Indeksu 0), jeśli nie masz heightForHeaderInSection połączenia.

Więc tableView.sectionHeaderHeight = 70po prostu nie działa, jest zepsuty .

Ustawienie ramki nic nie daje:

W viewForHeaderInSection prostu utwórz UIView ().

To bezcelowe / nic nie osiągniesz, jeśli UIView (ramka ...) ponieważ iOS po prostu ustawia rozmiar widoku zgodnie z tabelą.

Więc pierwsza linijka viewForHeaderInSectionbędzie prosta let view = UIView()i to jest widok, do którego wracasz.

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
}

To wszystko - wszystko inne to strata czasu.

Kolejny „kapryśny” problem Apple.


Użyte powyżej rozszerzenie wygody to:

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
    }
}
Fattie
źródło
1

Szybko dodaj magicznie nagłówek widoku tabeli

Ostatnio tego próbowałem.

Potrzebowałem jednego i tylko jednego nagłówka w całym UITableView.

Tak jak chciałem UIImageView na górze TableView. Więc dodałem UIImageView na górze UITableViewCell i automatycznie został dodany jako tableViewHeader. Teraz podłączam ImageView do ViewController i dodałem Image.

Byłem zdezorientowany, ponieważ zrobiłem coś takiego po raz pierwszy. Aby usunąć zamieszanie, otwórz format xml tablicy MainStoryBoard i stwierdziłem, że widok obrazu został dodany jako nagłówek.

U mnie zadziałało. Dzięki xCode i szybko.

Somir Saikia
źródło
1

wywołać tę metodę delegata

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

return @"Some Title";
}

da to szansę na automatyczne dodanie domyślnego nagłówka z dynamicznym tytułem.

Możesz użyć nagłówka / stopki wielokrotnego użytku i dostosowywalnego.

https://github.com/sourov2008/UITableViewCustomHeaderFooterSection

Shourob Datta
źródło
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
    }
}
flowGlen
źródło
0

Jeśli chcesz tylko dodać tytuł do nagłówka tableView, nie dodawaj widoku. W swift 3.x kod wygląda tak:

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
}

Możesz zaimplementować tablicę, aby pobrać tytuł dla nagłówków.

abhishek chakrabartti
źródło
0

Wracając do pierwotnego pytania (4 lata później), zamiast przebudowywać własny nagłówek sekcji, iOS może po prostu zadzwonić do Ciebie (z willDisplayHeaderView: forSection :) zaraz po utworzeniu domyślnego. Na przykład chciałem dodać przycisk wykresu na prawej krawędzi nagłówka sekcji:

- (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];
}
mackworth
źródło
0

Służy tableView: willDisplayHeaderView:do dostosowywania widoku, gdy ma on zostać wyświetlony.

Daje to tę zaletę, że można wziąć widok, który został już utworzony dla widoku nagłówka i rozszerzyć go, zamiast konieczności samodzielnego odtwarzania całego widoku nagłówka.

Oto przykład, który koloruje sekcję nagłówka na podstawie BOOL i dodaje element tekstowy szczegółu do nagłówka.

- (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];
}
Alex Zavatone
źródło
0

Swift 4.2

W Swift 4.2 nazwa tabeli została nieco zmieniona.

    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
    }
Esmaeil
źródło