在 UITableViewCell 内展开 UITextView
Posted
技术标签:
【中文标题】在 UITableViewCell 内展开 UITextView【英文标题】:Expanding UITextView inside UITableViewCell 【发布时间】:2014-02-19 16:32:58 【问题描述】:关于 SO 的问题有十几个类似的问题,但似乎没有就最佳方式达成共识。此外,我还没有找到任何适合我的解决方案。我的自定义 UITableViewCell 的不同之处在于我有两个标签,其中一个在它自己的视图中,还有一个文本视图。这三个都应该扩展到它们的内容。
我想知道是不是我的约束设置不正确,但我不确定我会调整什么。
这是我在 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 开始剪切/扩展。似乎自动布局不确定如何正确计算单元格的高度。
有什么想法吗?
这是我的Github project,里面有一些实验。重要文件是ViewControllers/RMTextViewTableViewController
和Cell/RMTextViewCell
。如果您运行它,请查看“带文本的动态单元格”。
【问题讨论】:
【参考方案1】:似乎这可能是一个 ios 错误,因为我希望 UITextView 的高度将作为 UILabel 包含在它位于单元格的 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;
【讨论】:
【参考方案2】:我也有同样的问题。 UITableViewCell 中的UILabel 计算正确,但UITableViewCell 中的UITextView 计算不正确。
所以只能手动计算高度:
CGSize textViewSize = [cell.textView sizeThatFits:CGSizeMake(cell.textView.frame.size.width, FLT_MAX)];
【讨论】:
如何添加单元格的其余部分,因为标签也可以是多行? 终于想通了。我将在未来的某个时候发布更多关于我如何进行计算的细节。谢谢。 你能发布这些细节 RyanJM 吗?我有同样的问题 同上,同样的问题,如果你能发布你的解决方案,那就太好了!【参考方案3】:我一直在寻找一种适用于 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;
【讨论】:
以上是关于在 UITableViewCell 内展开 UITextView的主要内容,如果未能解决你的问题,请参考以下文章
如何禁用为 UITableViewCell 的某些部分调用 DidSelect?
iOS 在点击时使用 AutoLayout 展开 UITableViewCell
在 Xamarin.iOS 中使用 UITableViewCell 展开 Segue
在 UITableViewCell 中选择后展开和折叠特定行