2

我有一个应用程序,它显示一个 TableView,顶部有两个相对静态的单元格,然后是一系列包含标签和分段控件的自定义单元格。这些单元格的高度需要根据标签中的文本数量而变化。

我在 cellForRowAtIndexPath 中计算所需的单元格高度,将值存储在数组中,然后在 heightForRowAtIndexPath 中使用该数组中的值。但是,似乎首先调用了 heightForRowAtIndexPath,因此我所有的行高都是 0/nil。

当在配置单元格之前需要知道单元格高度时,如何根据单元格的特定内容指定行高?

来自 cellForRowAtIndexPath 的片段:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSInteger currentIndex = indexPath.item;
    if (indexPath.item == 0){
        static NSString *CellIdentifier = @"MeasurementCell";
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
        [self.cellHeightList insertObject:[NSNumber numberWithInt:44] atIndex:currentIndex];
        return cell;
    } else if (indexPath.item == 1){
        if (self.dataController.isScoreAvailable){
            static NSString *CellIdentifier = @"ScoreCell";
            UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
            [self.cellHeightList insertObject:[NSNumber numberWithInt:46] atIndex:currentIndex];
            return cell;
        } else {
            static NSString *CellIdentifier = @"ScoreCell";
            UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
            cell.accessoryType = UITableViewCellAccessoryNone;
            [self.cellHeightList insertObject:[NSNumber numberWithInt:0] atIndex:currentIndex];
            return cell;
        }
    } else if (indexPath.item > 1){
        NSInteger labelWidth = [UIScreen mainScreen].applicationFrame.size.width - 140; //80 for segment + 3*20 for margins & spacing
        CGSize maxSize = CGSizeMake(labelWidth, MAXFLOAT);
        CGSize labelSize;

        static NSString *CellIdentifier = @"QuestionCell";
        InterviewQuestionCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
        InterviewQuestion *questionAtIndex = [self.dataController objectInListAtIndex:(indexPath.item-2)];
        cell.questionLabel.text = questionAtIndex.questionText;
        labelSize = [cell.questionLabel.text sizeWithFont:[UIFont systemFontOfSize:12.0] constrainedToSize:maxSize lineBreakMode:NSLineBreakByWordWrapping];
        CGRect labelFrame = CGRectMake(0, 0, labelWidth, labelSize.height);
        cell.questionLabel.frame = labelFrame;
        cell.questionLabel.numberOfLines = 0;
        cell.answerControl.selectedSegmentIndex = questionAtIndex.answer;
        cell.answerControl.tag = indexPath.item;
        [self.cellHeightList insertObject:[NSNumber numberWithInt:labelSize.height] atIndex:currentIndex];
        return cell;
    }
    return nil;
}

来自 heightForRowAtIndexPath 的代码:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSInteger currentIndex = indexPath.item;
    return [[self.cellHeightList objectAtIndex:currentIndex] integerValue];
}

谢谢你!

4

3 回答 3

2

首先确保不要在 indexPath 上使用“item”,而是使用“row”。我认为 UICollectionView 使用了 Item,而不是 UITableView。其次,您需要以某种方式计算单元格的大小,而无需手头有单元格。您的 tableView 具有一定的宽度,因此您可以基于此计算必要的高度。将此计算放在 heightForRowAtIndexPath: 中:(如果这很密集,请将其缓存)。

具体来说,不要将以下代码放在 cellForRowAtIndexPath 中,而是放在 heightForRowAtIndexPath: 中:

NSInteger labelWidth = [UIScreen mainScreen].applicationFrame.size.width - 140;
CGSize maxSize = CGSizeMake(labelWidth, MAXFLOAT);
CGSize labelSize;

此外,不使用 UIScreen,只需使用 tableView 的宽度,它会使您的代码不那么紧密耦合。

于 2013-09-07T13:25:50.047 回答
1
You can use autolayout and set the height based on the content in the content view 
you need to set 

//swift

     override func viewDidLoad() 
        {
             self.tableView.estimatedRowHeight = 180  
        }

    // return  UITableViewAutomaticDimension 
      override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat 
        {
            return UITableViewAutomaticDimension
        }



//Objective C

        - (void)viewDidLoad
        {
            [super viewDidLoad];
            self.tableview.estimatedRowHeight = 180.0 ;

        }

        -(float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        //constraint for autolayout for ios8+
        return UITableViewAutomaticDimension;
    }
于 2016-02-06T12:23:02.417 回答
0

我使用 Joride 的回答作为一个很好的起点,然后将标签高度功能提取到一个单独的函数中。我想我会再抽象一个缺口,然后从该函数返回标签的实际 CGSize,以便我可以从 heightForRowAtIndexPath 和 cellForRowAtIndexPath 中干净地调用它。我在下面包含了我的更新代码。

cellForRowAtIndexPath:

   - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        NSInteger currentIndex = indexPath.row;
        if (currentIndex == 0){
            static NSString *CellIdentifier = @"MeasurementCell";
            UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
            [[cell textLabel] setText:@"Eating"];
            [self.cellHeightList insertObject:[NSNumber numberWithInt:44] atIndex:currentIndex];
            return cell;
        } else if (currentIndex == 1){
            if (self.dataController.isScoreAvailable){
                static NSString *CellIdentifier = @"ScoreCell";
                UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
                [[cell textLabel] setText:@"Score"];
                [[cell detailTextLabel] setText:@"Score short description"];
                [self.cellHeightList insertObject:[NSNumber numberWithInt:46] atIndex:currentIndex];
                return cell;
            } else {
                static NSString *CellIdentifier = @"ScoreCell";
                UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
                [[cell textLabel] setText:@""];
                [[cell detailTextLabel] setText:@""];
                cell.accessoryType = UITableViewCellAccessoryNone;
                [self.cellHeightList insertObject:[NSNumber numberWithInt:0] atIndex:currentIndex];
                return cell;
            }
        } else if (currentIndex > 1){
            NSInteger labelWidth = [UIScreen mainScreen].applicationFrame.size.width - 140;
            CGSize maxSize = CGSizeMake(labelWidth, MAXFLOAT);

            static NSString *CellIdentifier = @"QuestionCell";
            InterviewQuestionCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
            InterviewQuestion *questionAtIndex = [self.dataController objectInListAtIndex:(currentIndex-2)];
            cell.questionLabel.text = questionAtIndex.questionText;
            CGSize labelSize = [cell.questionLabel.text sizeWithFont:[UIFont systemFontOfSize:12.0] constrainedToSize:maxSize lineBreakMode:NSLineBreakByWordWrapping];
            CGRect labelFrame = CGRectMake(0, 0, labelWidth, labelSize.height);
            cell.questionLabel.frame = labelFrame;
            cell.questionLabel.numberOfLines = 0;
            cell.answerControl.selectedSegmentIndex = questionAtIndex.answer;
            cell.answerControl.tag = indexPath.item;
            [self.cellHeightList insertObject:[NSNumber numberWithInt:labelSize.height] atIndex:currentIndex];
            return cell;
        }
        return nil;
    }

heightForRowAtIndexPath:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSInteger currentIndex = indexPath.row;
    if (currentIndex == 0){
        return 44;
    } else if (currentIndex == 1){
        if (self.dataController.isScoreAvailable){
            return 46;
        } else {
            return 0;
        }
    } else if (currentIndex > 1){
        return [self getRowHeightForRow:currentIndex];
    }
    return 0;
}

新的 getRowHeightForRow 函数:

- (NSInteger)getRowHeightForRow:(NSInteger)currentRow{
    NSInteger labelWidth = [UIScreen mainScreen].applicationFrame.size.width - 140; //80 for segment + 3*20 for margins & spacing
    CGSize maxSize = CGSizeMake(labelWidth, MAXFLOAT);
    InterviewQuestion *questionAtIndex = [self.dataController objectInListAtIndex:(currentRow-2)];
    NSString *questionText = questionAtIndex.questionText;
    CGSize labelSize = [questionText sizeWithFont:[UIFont systemFontOfSize:12.0] constrainedToSize:maxSize lineBreakMode:NSLineBreakByWordWrapping];
    return labelSize.height;

}
于 2013-09-09T11:59:54.810 回答