2012-04-23 157 views
21

我有一個填充了自定義單元格(從UITableViewCell繼承)的UITableView,每個單元格都包含一個基於其內容自動調整大小的UIWebView。這是事情,我如何根據其內容(變量webView)更改UITableView單元格的高度。基於內容的動態UITableView單元高度

該解決方案必須是動態的,因爲用於填充UIWebViews的HTML從不斷變化的提要中解析。

我有一種感覺,我需要使用UITableView委託方法heightForRowAtIndexPath但是從它的定義:

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

我無法訪問細胞或它的內容。我可以在cellForRowAtIndexPath中更改單元格的高度嗎?

任何幫助將是盛大的。謝謝。

注意

我在2年前問過這個問題。隨着汽車佈局的介紹爲iOS7的最佳解決方案,可以發現:

http://t.co/PdUywcTjhu

和iOS8上這個功能是內置在SDK

回答

17

最好的辦法,我已經找到了動態高度事先計算高度並將其保存某種形式的集合(可能是一個數組。)假設電池主要包含文本,你可以使用-[NSString sizeWithFont:constrainedToSize:lineBreakMode:]來計算高度,然後在heightForRowAtIndexPath:

[編輯返回相應的值]如果內容不斷chan你可以實現一種方法,在提供新數據時更新高度數組。

+0

謝謝,很好的解決方案,我將它的工作現在 – 2012-04-23 20:13:50

+0

「sizeWithFont」從iOS的7棄用而是使用「sizeWithAttributes」。 – 2017-07-19 12:42:39

2

這裏是我從twitter獲取推文,然後將它們存儲在CoreData中用於離線閱讀時用於動態單元格高度的代碼。

這不僅展示瞭如何讓電池和數據內容,又是如何動態地大小的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; 
} 
+7

從'heightForRowAtIndexPath'內調用'cellForRowAtIndexPath:'不是一個好主意。看看這個答案,而不是:http://stackoverflow.com/a/5254852/969967 – Anthony 2013-06-20 15:52:15

+1

This line: TweetTableViewCell * cell =(TweetTableViewCell *)[self tableView:tableView cellForRowAtIndexPath:indexPath];出隊reuresable行... – Lucas 2013-10-30 22:42:57

2

此外,我認爲這樣的算法會適合你:

1)的cellForRowAtIndexPath您激活網頁視圖用於加載,並給他們的標籤等於indexPath.row

2)webViewDidFinishLoading你計算單元格中的內容的高度,構成一個字典,鍵和值一樣這樣的:在鍵= indexPath.row值=高度

3)調用[tableview中reloadData]

4)[tableview中的cellForRowAtIndexPath:indexPath]中設置適當的高度爲對應小區

2

最大的問題與細胞iOS中的動態高度是表格vc必須在繪製單元格之前計算並返回每個單元格的高度。在繪製單元格之前,它沒有框架,因此沒有寬度。如果你的單元格根據textLabel中的文本數量來改變它的高度,這會導致一個問題,因爲你不知道它的寬度。

我見過的一個常見解決方案是人們爲單元格寬度定義一個數值。這是一種糟糕的做法,因爲表格可以是純文本或分組的,使用iOS 7或iOS 6樣式,可以在iPhone或iPad上顯示,橫向或縱向模式等。

我在iOS應用程序中遇到了這些問題我的,它支持iOS5 +以及多個方向的iPhone和iPad。我需要一種方便的方法來實現這一點,並將邏輯從視圖控制器中排除。結果變成了一個支持默認單元格(Default和Subtitle style)以及自定義單元格的UITableViewController子類(以便它可以保持狀態)。

您可以在GitHub上獲取它(https://github.com/danielsaidi/AutoSizeTableView)。我希望它能幫助那些仍然在爲這個問題而奮鬥的人。如果你確實檢查了一下,我很樂意聽到你的想法,以及它是否適合你。

4

我嘗試了許多解決方案,但工作的一個是這樣的,一個朋友建議:

- (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個可變標籤。像魅力一樣工作。希望它也適用於你。

最好的問候,亞歷山大。

22

這通常工作得很好:

的Objective-C:

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

斯威夫特:

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

正是我所需要的。 – adrian1kat 2015-04-09 05:05:01

+5

這不會在ios9中工作 – Bangalore 2015-11-16 05:53:48

+2

它可以與ios9一起使用,您可能需要在tableview函數**「estimatedHeightForRowAtIndexPath」中提供最大估計高度** – LuAndre 2016-02-19 05:57:02

0

我始終貫徹這在我所有的細胞在超級電池類,因爲對於一些原因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此方法。

注意:這隻適用於自動佈局,但它也適用於ios 7及更高版本。

PD:不要忘記檢查的XIB或情節串連圖板爲「優選的寬度顯式」的複選框,並設置靜態寬度(在CMD + ALT + 5菜單)

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

夫特 使用自定義單元格和標籤。設置UILabel的約束。(頂部,左邊,底部,右側)的UILabel的集線爲0

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

tableView.estimatedRowHeight = 68.0 
tableView.rowHeight = UITableViewAutomaticDimension 

//代表&數據源

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

我在UILabel中進行了非常大的測試。以上所有失敗的工作,然後我創建類別的字符串如下,並得到確切的高度

- (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;} 
0

這是我的一個很好的解決方案之一。它爲我工作。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
    cell.textLabel.text = [_nameArray objectAtIndex:indexPath.row]; 
    cell.textLabel.numberOfLines = 0; 
    cell.textLabel.lineBreakMode = NSLineBreakByWordWrapping; 
} 

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

我們需要將這些變化2。

1)cell.textLabel.numberOfLines = 0; 
    cell.textLabel.lineBreakMode = NSLineBreakByWordWrapping; 

2)return UITableViewAutomaticDimension; 
相關問題