在UITableViewCell中扩展UITextView

时间:2014-02-19 16:32:58

标签: ios objective-c uitableview

关于SO的十几个问题是相似的,但似乎没有就最佳方式达成共识。此外,我还没有找到任何适合我的解决方案。与我的自定义UITableViewCell不同的是,我有两个标签,其中一个是自己的视图,还有一个文本视图。所有这三个都应该扩展到它们的内容。

我想知道我的约束设置是否错误,但我不确定我会调整什么。

这是我在IB中的单元格。

cell in IB

内容视图为浅红色,顶部的额外视图为白色,内部带有标签。

文字更改后,我保存文字并更新tableView

-(void)textViewDidChange:(UITextView *)textView
{
    NSLog(@"row: %i", textView.tag);
    [self.textStrings setObject:textView.text atIndexedSubscript:textView.tag];
    [self.tableView beginUpdates];
    [self.tableView endUpdates];
}

对于tableView:heightForRowAtIndexPath:方法,我使用高速缓存值作为选定行以外的高度。在这种情况下,我正在创建一个新单元格,配置它,并使用systemLayoutSizeFittingSize:获取高度。这似乎是最常见的solution

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    // use cached height if there is one (and it isn't the selected row)
    if ([self.selectedRow integerValue] != indexPath.row && indexPath.row < [self.rowHeights count]){
        return [[self.rowHeights objectAtIndex:indexPath.row] floatValue];
    }

    static NSString *CellIdentifier = @"RMTextViewCell";
    RMTextViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    [self configureCell:cell forIndexPath:indexPath];

    [cell layoutIfNeeded];

    CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
    height += 1; // add 1 for border

    NSNumber *h = @(height);
    [self.rowHeights setObject:h atIndexedSubscript:indexPath.row];

    return height;
}

textView确实展开了,但当它转到多行时,顶部标签开始被剪裁。在某些版本中,我在文本更改时已经启动了textView剪辑/扩展。似乎autolayout不确定如何正确计算单元格的高度。

有什么想法吗?

这是我的Github project,里面有一些实验。重要文件为ViewControllers/RMTextViewTableViewControllerCell/RMTextViewCell。如果你运行它,请查看“带文本的动态单元格。”

3 个答案:

答案 0 :(得分:2)

似乎这可能是一个iOS错误,因为我希望UITextView的高度将被包含为UILabels,当它位于单元格的contentView中时,我们使用systemLayoutSizeFittingSize。无论如何,正如user501836所说,你可以手动计算textView的高度。然后,您需要将其添加到为contentView计算的高度。以下是我在tableView中计算单元格高度的示例:heightForRowAtIndexPath:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 
{

    CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;

    CGSize textViewSize = [[cell textView] sizeThatFits:CGSizeMake([[cell textView] frame].size.width, FLT_MAX)];

    height += textViewSize.height;

    return height;

}

答案 1 :(得分:1)

我有同样的问题。 UITabel在UITableViewCell计算中是正确的,但是UITableViewCell中的UITextView计算是不正确的。

因此,只能手动计算高度:

CGSize textViewSize = [cell.textView sizeThatFits:CGSizeMake(cell.textView.frame.size.width, FLT_MAX)];

答案 2 :(得分:0)

我一直在寻找适用于iOS7和iOS8的解决方案。基于jobb上面的答案,我添加了一些代码来处理使用UITextView.contextSize与UITextView.frame.size的轮换。

我还发现在xCode 6中,似乎systemLayoutSizeFittingSize是UITextView的textContainerInsets的一部分。所以我发现在将额外高度添加到systemLayoutSizeFittingSize之前将它们设置为零可以更好地设置间距。

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Get the cell once and save it in an NSDictionary. Thisupports cases with multiple cells types.
    CCTextViewCell *sizingCell = [self.offscreenCells objectForKey:CellIdentifier];
    if (!sizingCell) {
        sizingCell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
        [self.offscreenCells setObject:sizingCell forKey:CellIdentifier];
    }

    [self populateCellViewWithData:sizingCell atIndexPath:indexPath];

    sizingCell.bounds = CGRectMake(0.0f, 0.0f, CGRectGetWidth(tableView.bounds), CGRectGetHeight(sizingCell.bounds));
    [sizingCell setNeedsLayout];
    [sizingCell layoutIfNeeded];

    // UITextViews don't autosize well with systemLayoutSizeFittingSize.
    // We need to add the sum of the heights of the UITextViews without its textContainerInsets to the height.
    // We also need to set the textContainerInsets to zero so that systemLayoutSizeFittingSize give the right number.
    // So we do this first.
    CGFloat additionalUITextViewsHeight = 0;
    for (UIView *subVw in sizingCell.contentView.subviews) {
        if ([subVw isKindOfClass:[UITextView class]]) {
            UITextView *subTextView = (UITextView*) subVw;

            subTextView.textContainerInset = UIEdgeInsetsZero;
            CGSize textViewSize = [subTextView sizeThatFits:CGSizeMake(subTextView.contentSize.width, FLT_MAX)];
            additionalUITextViewsHeight += textViewSize.height;
        }
    }

    CGFloat height = [sizingCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height + additionalUITextViewsHeight;

    return height;
}