基于内容的dynamicUITableView单元格高度

我有一个UITableView填充自定义单元格(从UITableViewCellinheritance),每个单元格包含一个UIWebView ,根据它的内容自动resize。 这里的东西,我怎么能根据他们的内容(variableswebView )来改变UITableView单元格的高度。

解决scheme必须是dynamic的,因为用于填充UIWebViews的HTML从不断变化的提要中parsing。

我有一种感觉,我需要使用UITableView委托方法heightForRowAtIndexPath但从它的定义:

  - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { ;//This needs to be variable } 

我无法访问单元格或它的内容。 我可以在cellForRowAtIndexPath更改单元格的高度吗?

任何帮助将是伟大的。 谢谢。

注意

两年前我问过这个问题。 随着自动布局的介绍,iOS7的最佳解决scheme可以find:

http://t.co/PdUywcTjhu

而在iOS8上,这个function是在SDK中构build的

我发现dynamic高度的最好方法是预先计算高度并将其存储在某种types的集合中(可能是数组)。假定单元格大多包含文本,可以使用-[NSString sizeWithFont:constrainedToSize:lineBreakMode:]来计算高度,然后在heightForRowAtIndexPath:返回相应的值heightForRowAtIndexPath:

[编辑]如果内容不断变化,你可以实现一个方法,在提供新数据时更新高度数组。

这通常工作得很好:

Objective-C的:

 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { return UITableViewAutomaticDimension; } 

迅速:

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

我尝试了很多解决scheme,但是工作的一个就是这样,朋友build议:

 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { int height = [StringUtils findHeightForText:yourLabel havingWidth:yourWidth andFont:[UIFont systemFontOfSize:17.0f]]; height += [StringUtils findHeightForText:yourOtherLabel havingWidth:yourWidth andFont:[UIFont systemFontOfSize:14.0f]]; return height + CELL_SIZE_WITHOUT_LABELS; //important to know the size of your custom cell without the height of the variable labels } 

StringUtils.h类:

 #import <Foundation/Foundation.h> @interface StringUtils : NSObject + (CGFloat)findHeightForText:(NSString *)text havingWidth:(CGFloat)widthValue andFont:(UIFont *)font; @end 

StringUtils.m类:

 #import "StringUtils.h" @implementation StringUtils + (CGFloat)findHeightForText:(NSString *)text havingWidth:(CGFloat)widthValue andFont:(UIFont *)font { CGFloat result = font.pointSize+4; if (text) { CGSize size; CGRect frame = [text boundingRectWithSize:CGSizeMake(widthValue, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:font} context:nil]; size = CGSizeMake(frame.size.width, frame.size.height+1); result = MAX(size.height, result); //At least one row } return result; } @end 

它对我来说是完美的。 我有一个自定义单元格与固定大小的3个图像,2个固定大小的标签和2个variables标签。 像魅力一样工作。 希望它也适用于你。

最好的问候,亚历山大。

 self.tblVIew.estimatedRowHeight = 500.0; // put max you expect here. self.tblVIew.rowHeight = UITableViewAutomaticDimension; 

从twitter获取推文,然后将它们存储在CoreData中供脱机阅读时,这里是我用于dynamic单元格高度的代码。

这不仅显示如何获取单元格和数据内容,而且还显示如何dynamic地将UILabel的大小与填充

 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { Tweet *tweet = [self.fetchedResultsController objectAtIndexPath:indexPath]; NSString* text = tweet.Text; TweetTableViewCell *cell = (TweetTableViewCell*)[self tableView:tableView cellForRowAtIndexPath:indexPath]; //Set the maximum size CGSize maximumLabelSize = cell.tweetLabel.frame.size; CGPoint originalLocation = cell.tweetLabel.frame.origin; //Calculate the new size based on the text CGSize expectedLabelSize = [text sizeWithFont:cell.tweetLabel.font constrainedToSize:maximumLabelSize lineBreakMode:cell.tweetLabel.lineBreakMode]; //Dynamically figure out the padding for the cell CGFloat topPadding = cell.tweetLabel.frame.origin.y - cell.frame.origin.y; CGFloat bottomOfLabel = cell.tweetLabel.frame.origin.y + cell.tweetLabel.frame.size.height; CGFloat bottomPadding = cell.frame.size.height - bottomOfLabel; CGFloat padding = topPadding + bottomPadding; CGFloat topPaddingForImage = cell.profileImage.frame.origin.y - cell.frame.origin.y; CGFloat minimumHeight = cell.profileImage.frame.size.height + topPaddingForImage + bottomPadding; //adjust to the new size cell.tweetLabel.frame = CGRectMake(originalLocation.x, originalLocation.y, cell.tweetLabel.frame.size.width, expectedLabelSize.height); CGFloat cellHeight = expectedLabelSize.height + padding; if (cellHeight < minimumHeight) { cellHeight = minimumHeight; } return cellHeight; } 

我想这样的algorithm也适合你:

1)在cellForrowAtIndexPath你激活你的webviews加载和给他们标签等于indexPath.row

2)在webViewDidFinishLoading中,计算单元格内容的高度,然后用下面的键和值组成一个字典:key = indexPath.row value = height

3)调用[tableview reloadData]

4)在[tableview cellForRowAtIndexPath:indexPath]中为相应的单元格设置适当的高度

iOS中具有dynamic高度的单元格的大问题是表格vc必须在绘制单元格之前计算并返回每个单元格的高度。 在绘制单元格之前,它没有框架,因此没有宽度。 这会导致一个问题,如果你的单元格根据textLabel中的文本数量来改变它的高度,因为你不知道它的宽度。

我见过的一个常见解决scheme是人们为单元格宽度定义一个数值。 这是一个糟糕的做法,因为表格可以是普通的或分组的,使用iOS 7或iOS 6样式,可以在iPhone或iPad上显示,横向或纵向模式等。

我在iOS的iOS应用程序中努力解决这些问题,该应用程序支持iOS5 +以及多种方向的iPhone和iPad。 我需要一个方便的方法来实现这一点,并将逻辑从视图控制器中排除。 结果成为一个UITableViewController子类(以便它可以保持状态),支持默认单元格(默认和副标题样式)以及自定义单元格。

你可以抓住它在GitHub( https://github.com/danielsaidi/AutoSizeTableView )。 我希望这能帮助那些还在为这个问题而斗争的人。 如果你确实检查了一下,我很乐意听到你的想法,以及它是否适合你。

我总是在超级单元类的所有单元格中实现这一点,因为由于某种原因, UITableViewAutomaticDimension不能很好地工作。

 -(CGFloat)cellHeightWithData:(id)data{ CGFloat height = [[self contentView] systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height; [self fillCellWithData:data]; //set the label's text or anything that may affect the size of the cell [self layoutIfNeeded]; height = [[self contentView] systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height; return height+1; //must add one because of the cell separator } 

只需在你的-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath使用一个虚拟单元-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath用这个方法。

注意:这只适用于自动布局,但它也适用于iOS 7及更高版本。

pd:不要忘了勾选xib或storyboard上的“preferred width explicit”checkbox并设置静态宽度(在cmd + alt + 5菜单上)

Swift使用自定义单元格和标签。 设置UILabel的约束。 (顶部,左侧,底部,右侧)将UILabel的行设置为0

在ViewController的viewDidLoad方法中添加以下代码:

 tableView.estimatedRowHeight = 68.0 tableView.rowHeight = UITableViewAutomaticDimension 

//代表和数据源

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

我在UILabel有非常大的testing。 以上所有失败的工作,然后我创build类的string如下,并得到了确切的高度

 - (CGFloat)heightStringWithEmojifontType:(UIFont *)uiFont ForWidth:(CGFloat)width { // Get text CFMutableAttributedStringRef attrString = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0); CFAttributedStringReplaceString (attrString, CFRangeMake(0, 0), (CFStringRef) self ); CFIndex stringLength = CFStringGetLength((CFStringRef) attrString); // Change font CTFontRef ctFont = CTFontCreateWithName((__bridge CFStringRef) uiFont.fontName, uiFont.pointSize, NULL); CFAttributedStringSetAttribute(attrString, CFRangeMake(0, stringLength), kCTFontAttributeName, ctFont); // Calc the size CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(attrString); CFRange fitRange; CGSize frameSize = CTFramesetterSuggestFrameSizeWithConstraints(framesetter, CFRangeMake(0, 0), NULL, CGSizeMake(width, CGFLOAT_MAX), &fitRange); CFRelease(ctFont); CFRelease(framesetter); CFRelease(attrString); return frameSize.height + 10;}