Динамическая высотаForHeaderInSection - PullRequest
5 голосов
/ 05 марта 2012

Как я могу изменить высоту раздела заголовка в соответствии с представлением, которое я добавляю?
heightForHeaderInSection вызывается до viewForHeaderInSection, и я не знаю размер представления, пока не создам его.

Ответы [ 4 ]

12 голосов
/ 30 августа 2012

Вы можете следить за этим:

  1. Создание свойства для headerView (NSArray, если несколько представлений заголовка).
  2. Создайте представление в самом "heightForHeaderInSection".
  3. Присвойте свой вид собственности.
  4. возвращает высоту вашего вида в "heightForHeaderInSection".
  5. В «viewForHeaderInSection» вернуть это свойство.
3 голосов
/ 14 апреля 2016

Это также работает:

  1. Переопределить estimatedHeightForHeaderInSection, вернуть CGFloat, что угодно, но не 0.

  2. СоздатьCGFloat свойство для сохранения высоты для представления заголовка.

    var sectionHeaderViewHeight:CGFloat = 10.0 
    

    (Значение не важно, но никогда не устанавливается на 0.0, если вы сделаете это, viewForHeaderInSection никогда не будет вызываться, выникогда не будет иметь представление заголовка раздела!)

  3. Переопределить heightForHeaderInSection и вернуть это свойство.

    override func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return sectionHeaderViewHeight
    }
    
  4. Создать представление заголовка вviewForHeaderInSection

    override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
         let headerView = UIView()
         //configuration your view
         //.....
    
         return headerView
    }
    
  5. Это ключевой шаг : добавьте этот код перед возвратом headerView.

    self.tableView.beginUpdates()
    sectionHeaderViewHeight = //The value you would like to set
    self.tableView.endUpdates()
    

Это выглядит так:

override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
   let headerView = UIView()
   //configuration your view
   //.....
   //----Key Steps:----
   self.tableView.beginUpdates()
   sectionHeaderViewHeight = //The value you would like to set
   self.tableView.endUpdates()
   //----Key Steps----
   return headerView
}

var sectionHeaderViewHeight:CGFloat = 10.0 
override func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return sectionHeaderViewHeight
}
3 голосов
/ 08 апреля 2012

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

Например, у меня есть логика, которую я использую для определения размера UILabel, который я помещаю в свой заголовок, основываясь на размере текста. Поэтому я извлек это из моего viewForHeaderInSection и переместил его в свой собственный метод sizeForHeaderLabelInSection, который я использую для определения размера элемента управления меткой):

- (CGSize)tableView:(UITableView *)tableView sizeForHeaderLabelInSection:(NSInteger)section
{
    NSString *text = [self tableView:tableView titleForHeaderInSection:section];

    CGSize constraint = CGSizeMake(self.view.frame.size.width - kSectionTitleLeftMargin - kSectionTitleRightMargin, kMaxSectionTitleHeight);
    return [text sizeWithFont:[self fontForSectionHeader] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];
}

Затем я изменил стандарт heightForHeaderInSection, чтобы использовать этот метод, добавив, конечно, мой верхний и нижний поля вокруг моей UILabel:

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{    
    return [self tableView:tableView sizeForHeaderLabelInSection:section].height + kSectionTitleTopMargin + kSectionTitleBottomMargin;
}

А затем я изменил стандарт viewForHeaderInSection, чтобы также использовать этот sizeForHeaderLabelInSection:

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    CGSize size = [self tableView:tableView sizeForHeaderLabelInSection:section];

    UIView* headerView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, size.width + kSectionTitleLeftMargin + kSectionTitleRightMargin, size.height + kSectionTitleTopMargin + kSectionTitleBottomMargin)];
    //headerView.contentMode = UIViewContentModeScaleToFill;

    // Add the label
    UILabel *headerLabel = [[UILabel alloc] initWithFrame:CGRectMake(kSectionTitleLeftMargin, 
                                                                     kSectionTitleTopMargin, 
                                                                     size.width, 
                                                                     size.height)];
    // put stuff to set up my headerLabel here...

    [headerView addSubview:headerLabel];

    // Return the headerView
    return headerView;
}

Ясно, как вы это делаете, полностью зависит от вас и от того, чего вы пытаетесь достичь. Но я думаю, что вы добьетесь успеха, если вы переключите свое мышление с «как мне определить размер того представления, которое я создал в viewForHeaderInSection», на «как я могу переместить код, который я использовал для определения размера в viewForHeaderInSection в некоторый общий метод, который может использовать мой heightForSectionInHeader.

1 голос
/ 27 апреля 2017

Для принудительного вызова метода heightForHeaderInSection вам просто нужно вызвать оба метода beginUpdates / endUpdates UITableView.

Сначала создайте и инициализируйте переменную высоту и верните ее

var height: CGFloat = 160.0

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

Затем добавьте метод, который обновит высоту сечения новым значением

func updateHeaderHeight(newHeight: CGFloat) {
    tableView.beginUpdates()
    height = newHeight
    tableView.endUpdates()
}
...