Настроить раздел заголовка UITableView


144

Я хочу настроить UITableViewзаголовок для каждого раздела. Пока я реализовал

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

этот UITabelViewDelegateметод. Я хочу получить текущий заголовок для каждого раздела и просто добавить его UILabelкак подпредставление.

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

Если это невозможно, мне нужно создать представление контейнера, которое является UIViewно, на этот раз мне нужно установить цвет фона по умолчанию, цвет тени и т. Д. Потому что, если вы внимательно посмотрите на заголовок раздела, он уже настроен.

Как я могу получить эти значения по умолчанию для каждого заголовка раздела?

Спасибо вам всем.


1
Что не так с использованием tableView:titleForHeaderInSection:?
— borrrden

Он возвращает NSString, мне нужно установить собственный шрифт, поэтому я не могу, если используюtableView:titleForHeaderInSection:
— limon

Или вы можете использовать изображения для имитации заголовков разделов по умолчанию. teehanlax.com/blog/ios-6-gui-psd-iphone-5
— Desdenova

@limon: Как реализовать заголовок раздела: stackoverflow.com/a/32261262/1457385
— shallowThought

Ответы:


291

Вы можете попробовать это:

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

это ваш bg color watever color, который вы хотите установить, вы можете
— Lochana Ragupathy

Вот в чем проблема, я уже сделал то, что вы написали. Но я не знаю цвета фона заголовка раздела по умолчанию, который выглядит серым. Но мне нужно, чтобы это был именно заголовок раздела по умолчанию.
— Limon

15
эй, давай,
— пользуйся

не забудьте также установить backgroundColor UILabel. Я знаю, что был немного сбит с толку, когда мое прошлое не стало для меня ясным.
— shulmey 07

3
что такое список в строке NSString * string = [list objectAtIndex: section]; кто-нибудь может мне сказать
— Ниша Гупта

45

Выбранный ответ с помощью tableView :viewForHeaderInSection:правильного.

Просто чтобы поделиться советом здесь.

Если вы используете раскадровку / xib, вы можете создать другую ячейку-прототип и использовать ее для своей «ячейки раздела». Код для настройки заголовка аналогичен тому, как вы настраиваете для ячеек строк.

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

14
с этим решением есть ряд ошибок. Во-первых, если вы реализуете «tableView (tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool», вы заметите, что заголовок раздела будет перемещаться вместе со строкой при скольжении. Чтобы этого избежать, вы должны вместо этого вернуть cell.contentView. Более серьезная проблема заключается в том, что при использовании этого решения приложение вылетает при длительном нажатии на заголовок раздела. Правильный способ - создать перо, расширяющее UITableViewHeaderFooterView, зарегистрировать его с табличным представлением и вернуть в этом методе. Протестировано на iOS8
— Качи,

@Kachi Решение используется viewForHeaderInSectionне так, canEditRowAtIndexPathкак вы упомянули. Я никогда не проверял сбой, который вы сказали, но не могли бы вы уточнить, как долгое нажатие вызывает сбой?
— samwize

1
Я имел в виду, что если вы реализуете это решение И реализуете canEditRowAtIndexPath, вы увидите, что заголовок также будет перемещаться вместе с самой верхней строкой, которую вы удаляете, если вы не вернете cell.contentView. См. Это сообщение SO: stackoverflow.com/questions/26009722/… Длительное нажатие вызывает сбой, потому что сообщение пытается отправить освобожденному объекту. См. Это сообщение SO: stackoverflow.com/questions/27622290/…
— Качи,

1
Пожалуйста, никогда не используйте UITableViewCellв качестве заголовка. Вам будет очень сложно отлаживать визуальные сбои - заголовок иногда исчезает из-за того, как ячейки удаляются из очереди, и вы будете часами искать, почему это так, пока не поймете, что UITableViewCellон не принадлежит UITableViewзаголовку.
— raven_raven

Использовать UITableViewCellв качестве заголовка просто неправильно.
— Alex Zavatone 08

31

Быстрая версия ответа Лочаны Теджас :

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
}

1
как сделать высоту метки динамической в ​​соответствии с текстом, который находится внутри представления?
— Pratik Shah

overrideКлючевое слово является излишним. Более того, рассмотрите возможность повторного использования представлений заголовков, а не их повторного создания.
— Вадим Булавин

17

Если вы используете вид заголовка по умолчанию, вы можете изменить текст только с помощью

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

Для Swift:

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

Если вы хотите настроить вид, вам нужно создать новый самостоятельно.


10

почему бы не использовать UITableViewHeaderFooterView ?


Вы можете использовать это только в том случае, если вы также не используете раздел - (UIView *) tableView: (UITableView *) tableView viewForHeaderInSection: (NSInteger).
— SAHM

1
Совершенно верный ответ. Кроме того, использование UITableViewHeaderFooterView выигрывает от повторного использования представлений, как и ячеек.
— Gregzo

6
@dmarsi Я не нашел свидетельств того, что они устарели.
— Fawkes

8

Если headerInSection не отображается, попробуйте это.

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

Это возвращает высоту заголовка данного раздела.


1
Не возражаете уточнить свой ответ?
— CinCout

Раздел заголовка не будет отображаться, если вы не укажете с помощью метода перехват «высоты» заголовка раздела. UITableView по умолчанию не показывает заголовки, если высота не указана. @CinCout
— theprojectabot

6

Swift 3 версия lochana и estemendoza отвечает:

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

}

Также имейте в виду, что вам ТАКЖЕ необходимо реализовать:

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

5

Попробуй это......

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
}

5

Это самое простое возможное решение. Следующий код можно использовать непосредственно для создания заголовка настраиваемого раздела.

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

ПРИМЕЧАНИЕ. SectionHeaderTableViewCell - это настраиваемая ячейка UITableViewCell, созданная в раскадровке.


SectionHeaderTableViewCell - использование необъявленного идентификатора
— Борис Гафуров

@BorisGafurov SectionHeaderTableViewCell - это просто пример имени, которое я дал своему UITableViewCell, который я создал в раскадровке.
— Аниш Кумар

5

Другие ответы хорошо воссоздают представление заголовка по умолчанию, но на самом деле не отвечают на ваш основной вопрос:

есть ли способ получить заголовок раздела по умолчанию?

Есть способ - просто реализовать tableView:willDisplayHeaderView:forSection:в своем делегате. Представление заголовка по умолчанию будет передано во второй параметр, и оттуда вы можете UITableViewHeaderFooterViewпреобразовать его в, а затем добавить / изменить подвиды по своему усмотрению.

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

Swift

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
}

Его не нужно разыгрывать. Вы можете просто добавить к просмотру то, что хотите. Фактически, создание нового объекта ничего не даст, если вы его не назначите view.
— Alex Zavatone

@AlexZavatone Верно, если вы просто добавляете просмотры, вам не нужно его транслировать. Это полезно, если вы хотите настроить некоторые представления по умолчанию, например текстовую метку.
— 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;
}

2

На вашем месте я бы создал метод, который возвращает UIView при наличии NSString. Например

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

В реализации этого метода создайте UIView, добавьте к нему UILabel со свойствами, которые вы хотите установить, и, конечно же, установите его заголовок на заданный.


Да, я могу это сделать, но мой вопрос в том, как получить фон заголовка раздела по умолчанию, значение тени, остальное легко реализовать.
— Limon

что вы имеете в виду по умолчанию фон заголовка раздела
— Lochana Ragupathy

1
Что ж, проще всего было бы использовать приложение Digital Color Meter, чтобы получить желаемые цвета. Взять их по коду было бы непросто, насколько я могу судить ...
— cpprulez

2

Решение @samwize в Swift (так что проголосуйте за него!). Великолепно использование того же механизма переработки также для разделов верхнего и нижнего колонтитула:

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

    return settingsHeaderSectionCell
}

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

Если вы хотите изменить шрифт textLabel в заголовке раздела, вы хотите сделать это в willDisplayHeaderView. Чтобы установить текст, вы можете сделать это в viewForHeaderInSection или titleForHeaderInSection. Удачи!


2

Полный пример 2019 для копирования и вставки

Сначала установите «Сгруппировано» на раскадровке: это должно произойти во время инициализации, вы не можете установить его позже, поэтому проще не забыть сделать это на раскадровке:

введите описание изображения здесь

Следующий,

Должен реализовать heightForHeaderInSection из-за ошибки Apple.

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

В Apple все еще существует ошибка - уже десять лет - когда она просто не отображает первый заголовок (т.е. индекс 0), если у вас нет heightForHeaderInSectionвызова.

Так что tableView.sectionHeaderHeight = 70просто не работает, он сломан .

Установка фрейма ничего не дает:

В viewForHeaderInSectionпросто создать UIView ().

Это бессмысленно / ничего не дает, если вы используете UIView (frame ...), поскольку iOS просто устанавливает размер представления, определяемый таблицей.

Итак, первая строка viewForHeaderInSectionбудет простой, let view = UIView()и это будет то представление, которое вы вернете.

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
}

Вот и все - все остальное - пустая трата времени.

Еще одна «привередливая» проблема Apple.


Используемое выше удобное расширение:

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

1

Волшебным образом добавить заголовок табличного представления быстро

Недавно попробовал это.

Мне нужен был один-единственный заголовок во всем UITableView.

Как будто я хотел UIImageView поверх TableView. Поэтому я добавил UIImageView поверх UITableViewCell, и он был автоматически добавлен как tableViewHeader. Теперь я подключаю ImageView к ViewController и добавляю Image.

Я был сбит с толку, потому что сделал что-то подобное впервые. Итак, чтобы прояснить мою путаницу, откройте XML-формат MainStoryBoard и обнаружите, что представление изображения было добавлено в качестве заголовка.

У меня это сработало. Спасибо xCode и swift.


1

вызовите этот метод делегата

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

return @"Some Title";
}

это даст возможность автоматически добавить заголовок по умолчанию с динамическим заголовком.

Вы можете использовать многоразовый и настраиваемый верхний / нижний колонтитул.

https://github.com/sourov2008/UITableViewCustomHeaderFooterSection


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


0

Если вы просто хотите добавить заголовок в заголовок tableView, не добавляйте представление. В swift 3.x код выглядит так:

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
}

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


0

Возвращаясь к исходному вопросу (4 года спустя), вместо того, чтобы перестраивать собственный заголовок раздела, iOS может просто позвонить вам (с помощью willDisplayHeaderView: forSection :) сразу после создания заголовка по умолчанию. Например, я хотел добавить кнопку графика на правом краю заголовка раздела:

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

0

Используйте tableView: willDisplayHeaderView:для настройки представления, когда оно будет отображаться.

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

Вот пример, который раскрашивает раздел заголовка на основе BOOL и добавляет в заголовок элемент детального текста.

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

0

Swift 4.2

В Swift 4.2 имя таблицы немного изменено.

    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
    }
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.