Jak zaimplementować niestandardowe nagłówki sekcji widoku tabeli i stopki za pomocą Storyboard
Bez użycia storyboardu możemy po prostu przeciągnąć UIView
Na płótno, rozłożyć je, a następnie ustawić w metodach delegowania tableView:viewForHeaderInSection
lub tableView:viewForFooterInSection
.
Jak możemy to osiągnąć za pomocą storyboardu, w którym nie możemy przeciągnąć UIView na płótno
15 answers
Wiem, że to pytanie dotyczyło iOS 5, ale z korzyścią dla przyszłych czytelników, zauważ, że skuteczny iOS 6 możemy teraz używać dequeueReusableHeaderFooterViewWithIdentifier
zamiast dequeueReusableCellWithIdentifier
.
Więc w viewDidLoad
zadzwoń albo registerNib:forHeaderFooterViewReuseIdentifier:
albo registerClass:forHeaderFooterViewReuseIdentifier:
. Następnie w viewForHeaderInSection
, wywołaj tableView:dequeueReusableHeaderFooterViewWithIdentifier:
. Nie używasz prototypu komórki z tym API (jest to Widok oparty na NIB lub widok utworzony programowo), ale jest to nowe API dla usuniętych nagłówków i stopek.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-20 20:18:21
Po prostu użyj prototypowej komórki jako nagłówka sekcji i / lub stopki.
- dodaj dodatkową komórkę i umieść w niej pożądane elementy.
- ustaw identyfikator na coś konkretnego (w moim przypadku SectionHeader)
- zaimplementuj metodę
tableView:viewForHeaderInSection:
lub metodętableView:viewForFooterInSection:
- użyj
[tableView dequeueReusableCellWithIdentifier:]
, aby uzyskać nagłówek - wdrożyć metodę
tableView:heightForHeaderInSection:
.
-(UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
static NSString *CellIdentifier = @"SectionHeader";
UITableViewCell *headerView = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (headerView == nil){
[NSException raise:@"headerView == nil.." format:@"No cells with matching CellIdentifier loaded from your storyboard"];
}
return headerView;
}
Edit: Jak zmienić tytuł nagłówka (skomentowane pytanie):
- Dodaj etykietę do komórki nagłówka
- ustaw znacznik etykiety na konkretny numer (np. 123)
- w metodzie
tableView:viewForHeaderInSection:
uzyskaj Etykietę wywołując:
UILabel *label = (UILabel *)[headerView viewWithTag:123];
- Teraz możesz użyć etykiety, aby ustawić nowy tytuł:
[label setText:@"New Title"];
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-14 12:07:14
W systemie iOS 6.0 i nowszym wiele się zmieniło dzięki nowemu API dequeueReusableHeaderFooterViewWithIdentifier
.
Napisałem przewodnik (testowany na iOS 9), który można podsumować jako taki:
- podklasa
UITableViewHeaderFooterView
- Utwórz Nib z widokiem podklasy i dodaj 1 widok kontenera, który zawiera wszystkie inne widoki w nagłówku / stopce
- Zarejestruj stalówkę w
viewDidLoad
- zaimplementuj
viewForHeaderInSection
i użyjdequeueReusableHeaderFooterViewWithIdentifier
, aby odzyskać nagłówek / stopkę
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-07 11:10:55
Działa w iOS7 używając prototypowej komórki w storyboardzie. Mam przycisk w moim niestandardowym widoku nagłówka sekcji, który wyzwala segue, który jest skonfigurowany w storyboardzie.
Zacznij od rozwiązania Tieme ' a
Jako pedrom zwraca uwagę, że problem polega na tym, że stuknięcie nagłówka sekcji powoduje wybranie pierwszej komórki w sekcji.Jak wskazuje Paul Von, naprawia się to zwracając zawartość komórki zamiast całości cell.
Jednak, jak podkreśla Hons, długie naciśnięcie nagłówka sekcji spowoduje awarię aplikacji.
Rozwiązaniem jest usunięcie gestureRecognizers z contentView.
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
static NSString *CellIdentifier = @"SectionHeader";
UITableViewCell *sectionHeaderView = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
while (sectionHeaderView.contentView.gestureRecognizers.count) {
[sectionHeaderView.contentView removeGestureRecognizer:[sectionHeaderView.contentView.gestureRecognizers objectAtIndex:0]];
}
return sectionHeaderView.contentView; }
Jeśli nie używasz gestów w widokach nagłówka sekcji, ten mały hack wydaje się to zrobić.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:17:55
Jeśli używasz storyboardów, możesz użyć prototypowej komórki w widoku tableview do układania widoku nagłówka. Ustaw unikalny identyfikator i viewForHeaderInSection możesz usunąć komórkę z tym identyfikatorem i wrzucić ją do widoku UIView.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-12 08:46:54
Rozwiązanie, które wymyśliłem, jest w zasadzie tym samym rozwiązaniem używanym przed wprowadzeniem storyboardów.
Utwórz nowy, pusty plik klasy interfejsu. Przeciągnij Widok UIView na obszar roboczy, układ według potrzeb.
Załaduj stalówkę ręcznie, Przypisz do odpowiedniej sekcji nagłówka/stopki w metodach viewforheaderinsection lub viewforfooterinsection delegate.
Miałem nadzieję, że Apple uprościło ten scenariusz za pomocą storyboardów i nadal szukało lepszego lub prostszego rozwiązania. Na przykład niestandardowe nagłówki tabel i stopki są proste do dodania.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-11 15:58:19
Jeśli potrzebujesz szybkiej implementacji tego, postępuj zgodnie ze wskazówkami na zaakceptowanej odpowiedzi, a następnie w uitableviewcontroller zaimplementuj następujące metody:
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let cell = self.tableView.dequeueReusableCell(withIdentifier: "CustomHeader") as! CustomHeaderUITableViewCell
return cell
}
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 75
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-31 06:28:19
Gdy zwrócisz contentView komórki będziesz miał 2 Problemy:
- awaria związana z gestami
- nie używasz ponownie contentView (za każdym razem przy
viewForHeaderInSection
wywołaniu tworzysz nową komórkę)
Rozwiązanie:
Klasa Wrapper dla nagłówka tabeli\footer.
Jest to po prostu kontener, dziedziczony z UITableViewHeaderFooterView
, który przechowuje komórkę wewnątrz
Https://github.com/Magnat12/MGTableViewHeaderWrapperView.git
Zarejestruj klasę w UITableView (na przykład w viewDidLoad)
- (void)viewDidLoad {
[super viewDidLoad];
[self.tableView registerClass:[MGTableViewHeaderWrapperView class] forHeaderFooterViewReuseIdentifier:@"ProfileEditSectionHeader"];
}
W Twoim UITableViewDelegate:
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
MGTableViewHeaderWrapperView *view = [tableView dequeueReusableHeaderFooterViewWithIdentifier:@"ProfileEditSectionHeader"];
// init your custom cell
ProfileEditSectionTitleTableCell *cell = (ProfileEditSectionTitleTableCell * ) view.cell;
if (!cell) {
cell = [tableView dequeueReusableCellWithIdentifier:@"ProfileEditSectionTitleTableCell"];
view.cell = cell;
}
// Do something with your cell
return view;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-14 12:18:02
Aby leniwie tworzyć widoki nagłówka/stopki, wykonałem następujące czynności:
- Dodaj kontroler widoku freeform dla nagłówka / stopki sekcji do storyboardu
- Obsługa wszystkich rzeczy dla nagłówka w kontrolerze widoku
- w kontrolerze widoku tabeli podaj zmienną tablicę kontrolerów widoku dla nagłówków / stopek sekcji przepełnionych
[NSNull null]
- In viewForHeaderInSection / viewForFooterInSection jeśli kontroler widoku jeszcze nie istnieje, utwórz go za pomocą storyboardów instantiateViewControllerWithIdentifier, zapamiętaj go w tablicy i zwróć widok kontrolerów widoku
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-19 10:58:12
Aby kontynuowaćsugestię Damona , Oto jak zrobiłem nagłówek do wyboru, tak jak normalny wiersz ze wskaźnikiem ujawnienia.
Dodałem przycisk podklasowany z UIButton (nazwa podklasy "ButtonWithArgument") do prototypowej komórki nagłówka i usunąłem tekst tytułu (pogrubiony tekst "Title" to kolejna Etykieta UILabel w prototypowej komórce)
Następnie Ustaw przycisk do całego widoku nagłówka i dodaj wskaźnik ujawnienia z Avario ' s trick
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
static NSString *CellIdentifier = @"PersonGroupHeader";
UITableViewCell *headerView = (UITableViewCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(headerView == nil)
{
[NSException raise:@"headerView == nil, PersonGroupTableViewController" format:[NSString stringWithFormat:@"Storyboard does not have prototype cell with identifier %@",CellIdentifier]];
}
// https://stackoverflow.com/a/24044628/3075839
while(headerView.contentView.gestureRecognizers.count)
{
[headerView.contentView removeGestureRecognizer:[headerView.contentView.gestureRecognizers objectAtIndex:0]];
}
ButtonWithArgument *button = (ButtonWithArgument *)[headerView viewWithTag:4];
button.frame = headerView.bounds; // set tap area to entire header view
button.argument = [[NSNumber alloc] initWithInteger:section]; // from ButtonWithArguments subclass
[button addTarget:self action:@selector(headerViewTap:) forControlEvents:UIControlEventTouchUpInside];
// https://stackoverflow.com/a/20821178/3075839
UITableViewCell *disclosure = [[UITableViewCell alloc] init];
disclosure.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
disclosure.userInteractionEnabled = NO;
disclosure.frame = CGRectMake(button.bounds.origin.x + button.bounds.size.width - 20 - 5, // disclosure 20 px wide, right margin 5 px
(button.bounds.size.height - 20) / 2,
20,
20);
[button addSubview:disclosure];
// configure header title text
return headerView.contentView;
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 35.0f;
}
-(void) headerViewTap:(UIGestureRecognizer *)gestureRecognizer;
{
NSLog(@"header tap");
NSInteger section = ((NSNumber *)sender.argument).integerValue;
// do something here
}
ButtonWithArgument.h
#import <UIKit/UIKit.h>
@interface ButtonWithArgument : UIButton
@property (nonatomic, strong) NSObject *argument;
@end
ButtonWithArgument.m
#import "ButtonWithArgument.h"
@implementation ButtonWithArgument
@end
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:31:12
Powinieneś użyć rozwiązania Tieme jako bazy, ale zapomnij o viewWithTag:
i innych podejrzanych podejściach, zamiast tego spróbuj przeładować nagłówek (przeładowując tę sekcję).
Więc po usiadł swój niestandardowy widok nagłówka komórki z wszystkich fantazyjnych AutoLayout
rzeczy, po prostu dequeue go i zwraca contentView po skonfigurowaniu, jak:
-(UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
static NSString *CellIdentifier = @"SectionHeader";
SettingsTableViewCell *sectionHeaderCell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
sectionHeaderCell.myPrettyLabel.text = @"Greetings";
sectionHeaderCell.contentView.backgroundColor = [UIColor whiteColor]; // don't leave this transparent
return sectionHeaderCell.contentView;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:23
Miałem kłopoty w scenariuszu, w którym nagłówek nigdy nie został ponownie użyty, nawet wykonując wszystkie właściwe kroki.
Więc jako wskazówka dla wszystkich, którzy chcą osiągnąć sytuację Pokaż puste sekcje (0 wierszy) należy ostrzec, że:
DequeueReusableHeaderFooterViewWithidentifier nie użyje ponownie nagłówka, dopóki nie zwrócisz co najmniej jednego wiersza
Hope it helps
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-24 20:17:23
Co z rozwiązaniem, w którym nagłówek jest oparty na tablicy widoków:
class myViewController: UIViewController {
var header: [UILabel] = myStringArray.map { (thisTitle: String) -> UILabel in
let headerView = UILabel()
headerView.text = thisTitle
return(headerView)
}
Następny w delegacie:
extension myViewController: UITableViewDelegate {
func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
return(header[section])
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-12 03:55:24
Oto @Vitaliy Gozhenko ' s answer , in Swift.
Podsumowując, utworzysz UITableViewHeaderFooterView, który zawiera UITableViewCell. Ten UITableViewCell będzie "dequeuable" i możesz go zaprojektować w swoim storyboardzie.
-
Utwórz klasę UITableViewHeaderFooterView
class CustomHeaderFooterView: UITableViewHeaderFooterView { var cell : UITableViewCell? { willSet { cell?.removeFromSuperview() } didSet { if let cell = cell { cell.frame = self.bounds cell.autoresizingMask = [UIViewAutoresizing.FlexibleHeight, UIViewAutoresizing.FlexibleWidth] self.contentView.backgroundColor = UIColor .clearColor() self.contentView .addSubview(cell) } } }
-
Podłącz tableview z tą klasą w funkcji viewDidLoad:
self.tableView.registerClass(CustomHeaderFooterView.self, forHeaderFooterViewReuseIdentifier: "SECTION_ID")
-
Pytając o nagłówek sekcji, dequeue a CustomHeaderFooterView i wstawić do niego komórkę
func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { let view = self.tableView.dequeueReusableHeaderFooterViewWithIdentifier("SECTION_ID") as! CustomHeaderFooterView if view.cell == nil { let cell = self.tableView.dequeueReusableCellWithIdentifier("Cell") view.cell = cell; } // Fill the cell with data here return view; }
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:28
-
Dodaj komórkę w
StoryBoard
i ustawreuseidentified
-
Kod
class TP_TaskViewTableViewSectionHeader: UITableViewCell{ }
I
-
Użycie:
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { let header = tableView.dequeueReusableCell(withIdentifier: "header", for: IndexPath.init(row: 0, section: section)) return header }
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-22 08:43:12