如何动态计算自定义展开/可折叠UITableViewCell的高度

时间:2017-10-16 18:07:58

标签: ios objective-c uitableview custom-cell

我有一个有趣的场景。我有一些自定义的UITableViewCells设计在单独的xib文件中。其中一个有一个UIImageView,它将加载大小不恒定的图像,因此这意味着UIImageView的高度必须是灵活的。单元格还有一个UIView包含一些UILabel,UIView的大小是常量,比如100.我想展开并折叠didselectrowatindexpath事件上的单元格。要折叠单元格,我必须隐藏具有一些标签的UIView。请指导我在这方面实现目标。 另外我的问题是“当单元格展开和折叠时,如何计算行的高度。”感谢

编辑:这是我尝试过的。 。但是失败了

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    static DynamicTableViewCell *cell = nil;
    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{
        cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    });
    
    [self setUpCell:cell atIndexPath:indexPath];
    
    CGFloat cellHeight = [self calculateHeightForConfiguredSizingCell:cell];
    if(cellHeight >0) {
        if(cell.isExpanded) {
            
            return cellHeight;
        }
        else
        {
            return (cellHeight - detailViewHeight);      // cell.detailView.frame.size.height = 100
        }

    }
    else {
        return cellHeight;
    }
}

1 个答案:

答案 0 :(得分:0)

首先,由于性能原因,您不应该对您的单元格引用任何实例。

其次,您应该使用模型以正确的方式构建您的单元格。提供的代码根本不显示模型存储的使用情况。

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    // Say you have a array of models NSArray<YourModel *> *dataSource;

    YourModel *model = dataSource[indexPath.row]; // hope you have only one section.
}

第三,它是使用MVVM或VIPER或MVC等任何体系结构的好方法,因为如果您没有人,则可能在将来支持您的产品时遇到问题。因此,对于MVVM,YourModel就像ViewModel。

要定义动态高度单元格的状态,请使用属性isExpanded。这是一个好点,但它应该在另一个地方定义 - YourModel。如果你以正确的方式做到这一点,实际上你将知道没有细胞的细胞状态。

@interface YourModel ...
@property BOOL isExpanded;
@end

请确保在didSelect中正确更改状态:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    YourModel *model = dataSource[indexPath.row];
    model.isExpanded = !model.isExpanded; // inverse works like switch
    // Then relayout your row
    [tableView beginUpdates];
    // I commented next line because it might not be needed for you
    // Test it please
    // [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
    [tableView endUpdates]; 
}

回到heightForRow:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    // Say you have a array of models NSArray<YourModel *> *dataSource;

    YourModel *model = dataSource[indexPath.row]; // hope you have only one section.

    // It's better to extract next code to function or any class, but not in your YourModel.
    CGSize imageSize = [model.image doSizeCalulation]; // Use your algorithm to calculate image size
    CGSize shortText = [model.shortText sizeWithAttributes:@[/* font attributes */]];

    // If the cell is expanded then we should calculate height of text else height is zero.
    CGSize fullText = model.isExpanded ? [model.fullText sizeWithAttributes:@[/* font attributes */]]; : 0; 

    // just sum
    return imageSize.height + shortText.height + fullText.height;
}

实现此目的的另一种方法是使用UITableViewAutomaticDimension(只需在heightForRow方法中返回它)。在这种情况下,您应该正确设置约束,并在运行时根据isExpanded属性更改fullText的高度约束的常量。