Подтвердить что ты не робот

Как использовать UITableViewHeaderFooterView?

Привет, я хочу использовать UITableHeaderFooterView в своем приложении, и я делаю это:

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    [_tableView registerClass:[M3CTableViewCell class] forCellReuseIdentifier:@"cell"];
    [_tableView registerClass:[M3CHeaderFooter class] forHeaderFooterViewReuseIdentifier:@"footer"];

}

- (UITableViewHeaderFooterView *)footerViewForSection:(NSInteger)section {
    M3CHeaderFooter * footer = [[M3CHeaderFooter alloc]initWithReuseIdentifier:@"footer"];
    footer.textLabel.text = @"Test";
    return footer;
}

Сделав это, я ничего не получаю в Footer. И этот метод даже не вызван, но я думаю, что этот метод является частью протокола UITableViewDelegate. Пожалуйста, помогите!

4b9b3361

Ответ 1

Использование новой функции iOS 6 для многоразового просмотра заголовка/нижнего колонтитула включает в себя два шага. Кажется, вы делаете только первый шаг.

Первый шаг: вы сообщаете таблице, какой класс следует использовать для представления заголовка раздела, зарегистрировав свой подклас UITableViewHeaderFooterView (я предполагаю, что ваш M3CHeaderFooter является подклассом UITableViewHeaderFooterView).

Второй шаг: скажите в таблице представление о том, какой вид использовать (и повторное использование) для раздела заголовка, реализуя метод делегирования tableView

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

Итак, в вашем представленииDidLoad вы реализуете что-то вроде этого:

    // ****** Do Step One ******
    [_tableView registerClass:[M3CHeaderFooter class] forHeaderFooterViewReuseIdentifier:@"TableViewSectionHeaderViewIdentifier"];

Затем вы должны реализовать метод представления вида таблицы View в классе, в котором вы создаете и отображаете представление в таблице:

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    return 40.0;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    static NSString *headerReuseIdentifier = @"TableViewSectionHeaderViewIdentifier";

    // ****** Do Step Two *********
    M3CHeaderFooter *sectionHeaderView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:headerReuseIdentifier];
   // Display specific header title
   sectionHeaderView.textLabel.text = @"specific title";   

    return sectionHeaderView;    
}

Теперь помните, что вам не нужно подклассифицировать UITableViewHeaderFooterView, чтобы использовать его. Перед iOS 6, если вы хотите иметь представление заголовка для раздела, вы должны реализовать вышеупомянутый метод делегата tableView и сообщить таблице, какой вид использовать для каждого раздела. Поэтому у каждого раздела был другой экземпляр UIView, который вы предоставили. Это означает, что если ваш tableView имел 100 разделов, а внутри метода делегата вы создали новый экземпляр UIView, то вы предоставили tableView 100 UIViews для 100 заголовков разделов, которые были отображены.

Используя новую функцию многоразового просмотра заголовка/нижнего колонтитула, вы создаете экземпляр UITableViewHeaderFooterView, и система повторно использует его для каждого отображаемого заголовка раздела.

Если вы хотите иметь повторно используемый UITableViewHeaderFooterView без подкласса, вы просто меняете свой viewDidLoad на это:

// Register the class for a header view reuse.
[_buttomTableView registerClass:[UITableViewHeaderFooterView class] forHeaderFooterViewReuseIdentifier:@"TableViewSectionHeaderViewIdentifier"];

а затем ваш метод делегирования:

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    return 40.0;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    static NSString *headerReuseIdentifier = @"TableViewSectionHeaderViewIdentifier";

   // Reuse the instance that was created in viewDidLoad, or make a new one if not enough.
    UITableViewHeaderFooterView *sectionHeaderView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:headerReuseIdentifier];
    sectionHeaderView.textLabel.text = @"Non subclassed header";

    return sectionHeaderView;

}

Надеюсь, это было достаточно ясно.

EDIT: При подклассификации заголовка вы можете реализовать код, похожий на следующий, если вы хотите добавить пользовательское представление в headerView:

        // Add any optional custom views of your own
    UIView *customView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 50.0, 30.0)];
    [customView setBackgroundColor:[UIColor blueColor]];

    [sectionHeaderView.contentView addSubview:customView];

Выполнение этого в подклассе, в отличие от метода viewForHeaderInSection: delegate (как указано ниже Matthias), обеспечит создание только одного экземпляра любых подзонов. Затем вы можете добавить любые свойства в подкласс, которые позволят вам получить доступ к вашему пользовательскому подзону.

Ответ 2

UITableViewHeaderFooterView - одно из немногих мест, которые я программно обрабатывал бы представление, а не использовал Storyboard или XIB. Поскольку вы не можете официально использовать внешний прокси-сервер, и нет никакого способа IB сделать это, не злоупотребляя UITableViewCells. Я делаю это по-старому и просто использую тег на ярлыке для извлечения пользовательских элементов.

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    UITableViewHeaderFooterView *headerView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:kSectionHeaderReuseIdentifier];
    if (headerView == nil) {
        [tableView registerClass:[UITableViewHeaderFooterView class] forHeaderFooterViewReuseIdentifier:kSectionHeaderReuseIdentifier];
        headerView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:kSectionHeaderReuseIdentifier];
    }

    UILabel *titleLabel = (UILabel *)[headerView.contentView viewWithTag:1];
    if (titleLabel == nil) {
        UIColor *backgroundColor = [UIColor blackColor];
        headerView.contentView.backgroundColor = backgroundColor;
        titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(10.0f, 0.0f, 300.0f, 44.0f)];
        titleLabel.textColor = [UIColor whiteColor];
        titleLabel.backgroundColor = backgroundColor;
        titleLabel.shadowOffset = CGSizeMake(0.0f, 0.0f);
        titleLabel.tag = 1;
        titleLabel.font = [UIFont systemFontOfSize:24.0f];
        [headerView.contentView addSubview:titleLabel];
    }

    NSString *sectionTitle = [self.sections objectAtIndex:section];
    if (sectionTitle == nil) {
        sectionTitle = @"Missing Title";
    }

    titleLabel.text = sectionTitle;

    return headerView;
}

Ответ 3

Это старый пост и имеет хорошие ответы, но я хотел поделиться другим обходом для очень близкой проблемы, которую я испытал.

Сначала я использовал:

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

С помощью специальной ячейки прототипа для моего заголовка. Подклассификация UITableViewCell как таковая

    static NSString *cellIdentifier = @"CustomHeaderCell";
CustomHeaderCell * cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

Однако при анимации ячеек TableView над заголовками разделов (что делает их в два раза выше) заголовок будет исчезать. Это, как уже отмечалось, связано с тем, что реализация обеспечивала представление, а не повторное использование.

Вместо того, чтобы отказаться от всего с помощью специальной ячейки прототипа, я применил UITableViewHeaderFooterWithIdentifier и установил его как прототипированный элемент содержимого cellView без подкласса UITableViewHeaderFooterWithIdentifier.

  static NSString *customHeaderViewIdentifier = @"CustomHeaderView";
UITableViewHeaderFooterView *headerView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:customHeaderViewIdentifier];

headerView = (UITableViewHeaderFooterView *)cell.contentView;

Я понимаю, что это создает два экземпляра представления заголовка (по крайней мере, я думаю, что это будет...), однако это позволяет вам сохранять преимущества настраиваемой ячейки прототипа, не делая все программно.

Полный код:

  // viewDidLoad
    [myTableView registerClass:[UITableViewHeaderFooterView class] forHeaderFooterViewReuseIdentifier:@"CustomHeaderView"];

// Implement your custom header
 -(UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
     static NSString *cellIdentifier = @"CustomHeaderCell";
    CustomHeaderCell * cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

    static NSString *customHeaderViewIdentifier = @"CustomHeaderView";
    UITableViewHeaderFooterView *headerView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:customHeaderViewIdentifier];

// do your cell-specific code here
// eg. cell.myCustomLabel.text = @"my custom text"

    headerView = (UITableViewHeaderFooterView *)cell.contentView;

return headerView;
}

Ответ 4

Есть несколько способов приблизиться к этому, но вот одно из решений в Swift: идея состоит в том, что мы имеем подкласс UITableViewHeaderFooterView, называемый SNStockPickerTableHeaderView; он выставляет метод под названием configureTextLabel(), который при вызове устанавливает шрифт и цвет текстовой метки. Мы называем этот метод только после того, как заголовок был установлен, т.е. От willDisplayHeaderView, и шрифт правильно настроен.

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

// MARK: UITableViewDelegate

func tableView(tableView:UITableView, willDisplayHeaderView view:UIView, forSection section:Int) {
  if let headerView:SNStockPickerTableHeaderView = view as? SNStockPickerTableHeaderView {
    headerView.configureTextLabel()
  }
}

func tableView(tableView:UITableView, viewForHeaderInSection section:Int) -> UIView? {
  var headerView:SNStockPickerTableHeaderView? = tableView.dequeueReusableHeaderFooterViewWithIdentifier(kSNStockPickerTableHeaderViewReuseIdentifier) as? SNStockPickerTableHeaderView
  if (headerView == nil) {
    // Here we get to customize the section, pass in background color, text 
    // color, line separator color, etc. 
    headerView = SNStockPickerTableHeaderView(backgroundColor:backgroundColor,
      textColor:primaryTextColor,
      lineSeparatorColor:primaryTextColor)
  }
  return headerView!
}

И вот пользовательский UITableViewHeaderFooterView:

import Foundation
import UIKit

private let kSNStockPickerTableHeaderViewLineSeparatorHeight:CGFloat = 0.5
private let kSNStockPickerTableHeaderViewTitleFont = UIFont(name:"HelveticaNeue-Light", size:12)

let kSNStockPickerTableHeaderViewReuseIdentifier:String = "stock_picker_table_view_header_reuse_identifier"

class SNStockPickerTableHeaderView: UITableViewHeaderFooterView {

  private var lineSeparatorView:UIView?
  private var textColor:UIColor?

  required init(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }

  // We must implement this, since the designated init of the parent class
  // calls this by default!
  override init(frame:CGRect) {
    super.init(frame:frame)
  }

  init(backgroundColor:UIColor, textColor:UIColor, lineSeparatorColor:UIColor) {
    super.init(reuseIdentifier:kSNStockPickerTableHeaderViewReuseIdentifier)
    contentView.backgroundColor = backgroundColor
    self.textColor = textColor
    addLineSeparator(textColor)
  }

  // MARK: Layout

  override func layoutSubviews() {
    super.layoutSubviews()
    let lineSeparatorViewY = CGRectGetHeight(self.bounds) - kSNStockPickerTableHeaderViewLineSeparatorHeight
    lineSeparatorView!.frame = CGRectMake(0,
      lineSeparatorViewY,
      CGRectGetWidth(self.bounds),
      kSNStockPickerTableHeaderViewLineSeparatorHeight)
  }

  // MARK: Public API

  func configureTextLabel() {
    textLabel.textColor = textColor
    textLabel.font = kSNStockPickerTableHeaderViewTitleFont
  }

  // MARK: Private

  func addLineSeparator(lineSeparatorColor:UIColor) {
    lineSeparatorView = UIView(frame:CGRectZero)
    lineSeparatorView!.backgroundColor = lineSeparatorColor
    contentView.addSubview(lineSeparatorView!)
  }
}

Вот результат, см. заголовок раздела для "Популярные акции":

                              enter image description here

Ответ 5

Я не могу комментировать сообщение Камерона Лоуэлла Палмера, но для ответа Кристофер Кинг есть простой способ обеспечить повторное использование без подкласса UITableViewHeaderFooterView и но все еще использует пользовательские подзаголовки.

Во-первых, НЕ регистрируйте класс для повторного использования вида заголовка.

Затем в tableView: viewForHeaderInSection: вам просто нужно создать UITableViewHeaderFooterView при необходимости:

-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    static NSString *kYourTableViewReusableHeaderIdentifier = @"ID";

    UILabel *titleLabel = nil;

    UITableViewHeaderFooterView *headerView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:kYourTableViewReusableHeaderIdentifier];

    if (headerView == nil) {

        headerView = [[UITableViewHeaderFooterView alloc] initWithReuseIdentifier:kYourTableViewReusableHeaderIdentifier];

        titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(...)];
        titleLabel.tag = 1;
        // ... setup titleLabel 

        [headerView.contentView addSubview:titleLabel];
    } else {
        // headerView is REUSED
        titleLabel = (UILabel *)[headerView.contentView viewWithTag:1];
    }

    NSString *sectionTitle = (...); // Fetch value for current section
    if (sectionTitle == nil) {
        sectionTitle = @"Missing Title";
    }

    titleLabel.text = sectionTitle;

    return headerView;
}

Ответ 6

Вот "быстрый и грязный" способ добиться этого. Он сделает маленькую синюю метку в заголовке. Я подтвердил, что это делает ОК в iOS 6 и iOS 7.

в UITableViewDelegate:

 -(void)viewDidLoad
{
...
    [self.table registerClass:[UITableViewHeaderFooterView class] forHeaderFooterViewReuseIdentifier:@"Header"];
...
}

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

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    UITableViewHeaderFooterView *header = [tableView dequeueReusableHeaderFooterViewWithIdentifier:@"Header"];

    UILabel *leftlabel = [[UILabel alloc] initWithFrame:CGRectMake(0., 0., 400., 34.)];
    [leftlabel setBackgroundColor:[UIColor blueColor]];

    [header.contentView addSubview:leftlabel];
    return header;
}

Ответ 7

В случае, если он исчерпан в подробных ответах выше, то, что люди, вероятно, отсутствуют (по сравнению со стандартным методом cellForRowAtIndexPath:), заключается в том, что вы должны зарегистрировать класс, используемый для заголовка раздела.

[tableView registerClass:[UITableViewHeaderFooterView class] forHeaderFooterViewReuseIdentifier:@"SectionHeader"];

Попробуйте добавить registerClass:forHeaderFooterViewReuseIdentifier: и посмотреть, начнет ли он работать.

Ответ 8

Одна из причин, по которой метод не может быть вызван, - это стиль таблицы. Стандарт vs Grouped обрабатывает верхние и нижние колонтитулы по-разному. Это может объяснить, почему он не вызван.

Ответ 9

  • Задайте свойство delegate экземпляра UITableView для ссылки на контроллер, который реализует следующие методы:

  • Метод, который возвращает вид нижнего колонтитула раздела:

    Запрос делегату для объекта представления для отображения в нижнем колонтитуле указанного раздела представления таблицы. - (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section

  • Высота представления в нижнем колонтитуле раздела:

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

    - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection: раздел (NSInteger)