Настроить раздел заголовка 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 ?

user836773
источник
Вы можете использовать это только в том случае, если вы также не используете раздел - (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 со свойствами, которые вы хотите установить, и, конечно же, установите его заголовок на заданный.

cpprulez
источник
Да, я могу это сделать, но мой вопрос в том, как получить фон заголовка раздела по умолчанию, значение тени, остальное легко реализовать.
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
    }
}
FlowGlen
источник
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
    }
Эсмаил
источник