Как реализовать пользовательские верхние и нижние колонтитулы представления табличного представления с раскадровкой - PullRequest
172 голосов
/ 10 февраля 2012

Без использования раскадровки мы могли бы просто перетащить UIView на холст, выложить его, а затем установить его в методах делегатов tableView:viewForHeaderInSection или tableView:viewForFooterInSection.

Как мыВыполните это с помощью StoryBoard, где мы не можем перетащить UIView на холст

Ответы [ 16 ]

381 голосов
/ 09 июля 2012

Просто используйте ячейку-прототип в качестве заголовка раздела и / или нижнего колонтитула.

  • добавьте дополнительную ячейку и поместите в нее нужные элементы.
  • установить идентификатор для чего-то определенного (в моем случае SectionHeader)
  • реализует метод tableView:viewForHeaderInSection: или tableView:viewForFooterInSection:
  • используйте [tableView dequeueReusableCellWithIdentifier:], чтобы получить заголовок
  • реализовать метод tableView:heightForHeaderInSection:.

(see screenhot)

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

Редактировать: Как изменить заголовок заголовка (прокомментированный вопрос):

  1. Добавить метку в ячейку заголовка
  2. установить метку метки на определенный номер (например, 123)
  3. В вашем методе tableView:viewForHeaderInSection: получите ярлык, вызвав:
    UILabel *label = (UILabel *)[headerView viewWithTag:123]; 
  1. Теперь вы можете использовать метку для установки нового заголовка:
    [label setText:@"New Title"];
89 голосов
/ 20 мая 2015

Я знаю, что этот вопрос был для iOS 5, но для будущих читателей, обратите внимание, что эффективную iOS 6 теперь мы можем использовать dequeueReusableHeaderFooterViewWithIdentifier вместо dequeueReusableCellWithIdentifier.

Так что в viewDidLoadпозвоните либо registerNib:forHeaderFooterViewReuseIdentifier:, либо registerClass:forHeaderFooterViewReuseIdentifier:.Затем в viewForHeaderInSection позвоните tableView:dequeueReusableHeaderFooterViewWithIdentifier:.Вы не используете прототип ячейки с этим API (это либо представление на основе NIB, либо представление, созданное программным способом), но это новый API для устаревших верхних и нижних колонтитулов.

52 голосов
/ 07 ноября 2015

В iOS 6.0 и выше все изменилось с новым dequeueReusableHeaderFooterViewWithIdentifier API.

Я написал руководство (протестировано на iOS 9), которое можно обобщить следующим образом:

  1. Подкласс UITableViewHeaderFooterView
  2. Создайте Nib с представлением подкласса и добавьте 1 представление контейнера, которое содержит все другие представления в верхнем / нижнем колонтитуле
  3. Зарегистрировать перо в viewDidLoad
  4. Реализация viewForHeaderInSection и использование dequeueReusableHeaderFooterViewWithIdentifier для возврата верхнего / нижнего колонтитула
22 голосов
/ 04 июня 2014

Я получил его в iOS7, используя прототип ячейки в раскадровке.У меня есть кнопка в моем пользовательском представлении заголовка раздела, которая вызывает переход, который настроен в раскадровке.

Начните с Решение Tieme

Как указывает pedro.mпроблема в том, что при нажатии заголовка раздела выбирается первая ячейка в разделе.

Как указывает Пол Фон, это исправлено, возвращая contentView ячейки вместо всей ячейки.

Однако, как отмечает Хонс, длительное нажатие на заголовок раздела приведет к сбою приложения..

Решение состоит в том, чтобы удалить любые жесты-распознаватели из 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; }

Если вы не используете жесты в представлениях заголовков разделов, кажется, этот небольшой хак для этого и сделал.

13 голосов
/ 12 апреля 2012

Если вы используете раскадровки, вы можете использовать ячейку прототипа в табличном представлении для компоновки представления заголовка.Установите уникальный идентификатор и viewForHeaderInSection. Вы можете удалить из него ячейку с этим идентификатором и привести ее к UIView.

11 голосов
/ 27 февраля 2015

Если вам нужна Swift Реализация этого, следуйте инструкциям на принятом ответе, а затем в вашем UITableViewController реализуйте следующие методы:

override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    return tableView.dequeueReusableCell(withIdentifier: "CustomHeader")
}

override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return 75
}
9 голосов
/ 11 февраля 2012

Решение, которое я придумал, в основном такое же решение, которое использовалось до появления раскадровок.

Создайте новый пустой файл класса интерфейса.Перетащите UIView на холст и расположите его по своему усмотрению.

Загрузите перо вручную, назначьте соответствующий раздел верхнего / нижнего колонтитула в методах делегирования viewForHeaderInSection или viewForFooterInSection.

Я надеялся, что Apple упроститэтот сценарий с раскадровками и продолжал искать лучшее или более простое решение.Например, пользовательские заголовки и нижние колонтитулы таблицы просто добавить.

5 голосов
/ 08 сентября 2015

Когда вы возвращаете contentView ячейки, у вас будет 2 проблемы:

  1. сбой, связанный с жестами
  2. вы не используете повторно ContentView (каждый раз при вызове viewForHeaderInSection высоздание новой ячейки)

Решение:

Класс оболочки для верхнего / нижнего колонтитула таблицы.Это просто контейнер, унаследованный от UITableViewHeaderFooterView, который содержит ячейку внутри

https://github.com/Magnat12/MGTableViewHeaderWrapperView.git

Зарегистрируйте класс в вашем UITableView (например, в viewDidLoad)

- (void)viewDidLoad {
    [super viewDidLoad];
    [self.tableView registerClass:[MGTableViewHeaderWrapperView class] forHeaderFooterViewReuseIdentifier:@"ProfileEditSectionHeader"];
}

В вашем 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;
}
2 голосов
/ 24 мая 2016

У меня были проблемы в сценарии, когда заголовок никогда не использовался повторно, даже когда я делал все правильные шаги.

Так что в качестве подсказки всем, кто хочет достичь ситуации показа пустых секций (0 строк)) имейте в виду, что:

dequeueReusableHeaderFooterViewWithIdentifier не будет повторно использовать заголовок, пока вы не вернете хотя бы одну строку

Надеюсь, это поможет

2 голосов
/ 03 апреля 2012

Раньше я делал лениво для создания представлений верхнего / нижнего колонтитула:

  • Добавление контроллера произвольной формы для верхнего / нижнего колонтитула раздела в раскадровку
  • Обработка всего содержимого заголовка в контроллере вида
  • В контроллере табличного представления представлен изменяемый массив контроллеров представления для верхних / нижних колонтитулов раздела, заполненных [NSNull null]
  • В viewForHeaderInSection / viewForFooterInSection, если контроллер представления еще не существует, создайте его с раскадровками instantiateViewControllerWithIdentifier, запомните его в массиве и верните представление контроллеров представления
...