在UITableViewCell中使用UITextView实现平滑自动调整大小

14

我在UITableViewCell的contentView中放置了一个UITextView,并允许单元格自动调整大小,以便输入的文本完全显示-我试图实现的是像本机iOS4联系人应用程序一样的自动调整大小的单元格-例如当textView的contentSize发生更改时-我调用reloadRowsAtIndexPaths并在委托的heightForRowAtIndexPath方法中提供新行的高度-这可以完成工作,但不像联系人应用程序那样平滑和流畅-我几乎可以肯定,苹果在该应用程序中使用了一些未记录的技巧来使单元格的contentView平稳地扩展和动画化,而不需要调用reloadRowsAtIndexPaths。我的问题是,您会建议如何实现这种功能?我希望在解释中没有遗漏任何细节。


你尝试过使用UIView的动画吗?我从未尝试过用它们来做这件事,但那可能会起作用。 - Jukurrpa
是的,我尝试了一些针对内部内容的UIView动画,它使过程更加平滑,但我想知道是否有一种方法可以不使用reloadRowsAtIndexPaths,似乎没有公开的方法可以实现。 - justadreamer
2个回答

16

尝试使用下面的代码,它会很有帮助。您不必使用任何reloadRowsAtIndexPaths之类的重新加载函数。

// textview代理

- (void)textViewDidChange:(UITextView *)textView {
    if (contentView.contentSize.height > contentRowHeight) {

    contentRowHeight = contentView.contentSize.height;

    [theTableView beginUpdates];
    [theTableView endUpdates];

    [contentView setFrame:CGRectMake(0, 0, 300.0, contentView.contentSize.height)];
    }
}

// tableview委托

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

    if (indexPath.row == 0)
        height = kTitleRowHeight;
    else 
        height = contentRowHeight;

    return height;
}

这是UITableViewCell的属性。UITextView被添加到这个属性中。[cell.contentView addSubview:textView]; - ohtwo
我在我的应用程序中使用此解决方案,在iPhone上工作100%,但在iPad上不起作用:当用户输入多行文本时,UITableViewCell会像预期的那样变高,但是UITextView实际上会向移动,以便第一行文本位于UITableViewCell的顶部之上 - 被隐藏了。有什么想法可以解决iPad上的这个问题吗? - Jason
PS 我已经在 https://dev59.com/em865IYBdhLWcg3wCqHI 发布了我的代码。 - Jason
@Jason:我的iPad应用程序按照你所描述的方式工作,直到我加入了contentView setFrame:...消息。请确保它存在。 - Daniel T.

12

我找到了解决这个问题的最佳方法。

首先,当然,您需要创建UITextView并将其添加到单元格的contentView中。我创建了一个名为“cellTextView”的UITextView实例变量。以下是我使用的代码:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"];

    if (!cellTextView) {
        cellTextView = [[UITextView alloc] initWithFrame:CGRectMake(5.0, 5.0, cell.bounds.size.width - 30.0, cell.bounds.size.height - 10.0)]; // I use these x and y values plus the height value for padding purposes.
    }
    [cellTextView setBackgroundColor:[UIColor clearColor]];
    [cellTextView setScrollEnabled:FALSE];
    [cellTextView setFont:[UIFont boldSystemFontOfSize:13.0]];
    [cellTextView setDelegate:self];
    [cellTextView setTextColor:[UIColor blackColor]];
    [cellTextView setContentInset:UIEdgeInsetsZero];
    [cell.contentView addSubview:cellTextView];

    return cell;
}

然后,在init方法中创建一个名为numberOfLines的int变量,并将其设置为1。接下来,在你的textViewDelegate的textViewDidChange方法中,使用以下代码:

然后,在 init 方法中创建一个 int 变量,名为 numberOfLines,并将其设为 1。之后,在你的 textViewDelegate 的 textViewDidChange 方法中,使用以下代码:

- (void)textViewDidChange:(UITextView *)textView
{
    numberOfLines = (textView.contentSize.height / textView.font.lineHeight) - 1;

    float height = 44.0;
    height += (textView.font.lineHeight * (numberOfLines - 1));

    CGRect textViewFrame = [textView frame];
    textViewFrame.size.height = height - 10.0; //The 10 value is to retrieve the same height padding I inputed earlier when I initialized the UITextView
    [textView setFrame:textViewFrame];

    [self.tableView beginUpdates];
    [self.tableView endUpdates];

    [cellTextView setContentInset:UIEdgeInsetsZero];
}    

最后,将此代码粘贴到您的heightForRowAtIndexPath方法中:

最后,将此代码粘贴到您的heightForRowAtIndexPath方法中:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    float height = 44.0;
    if (cellTextView) {
        height += (cellTextView.font.lineHeight * (numberOfLines - 1));
    }
    return height;
}

1
没错,这个很好用 +1。同时,通过将numberOfLines存储在一个NSArray中,索引为indexPath.row,textView.tag设置为indexPath.row,这样就可以使许多单元格中的多个UITextview随着每个单元格中文本大小的变化而改变。 - Rambatino
1
好的,让我重新思考一下我在这里做了什么:因此,对于每个单元格中的每个textView,在NSArray的每个元素中都有一个不同的“numberOfLines”整数变量。因此,定义您的数组(假设为两个不同uitableviewcells中的两个uitextviews)@[@numberOfLines1,@numberOfLines2];。现在,您可以访问每个不同的变量并更改其值,具体取决于您所在单元格的indexPath.row。 - Rambatino
@Ravin455 这样足够了吗?如果您有其他问题,请在此发布。 - Rambatino
@MarkRamotowski 好的,我现在明白了,但是如果你有动态数量的单元格和因此的TextView,那么你该怎么做呢?你会如何处理? - Souljacker
1
这取决于你的tableView是否有多个section,如果是的话,我建议为每个section使用一个单独的数组;如果不是,则一个数组就足够了。你需要一个方法来增加和减少数组,以便根据动态单元格数量进行调整,但只要你的数组是动态的,并且每个单元格都由数组中的有序值表示,那么你应该没问题。然后通过返回[yourArray[indexPath.row] intValue]来修改高度(使用heightForRowAtIndexPath)。 - Rambatino
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接