根据UILabel动态调整uitableViewCell的大小(带段落间距)

时间:2013-10-06 23:34:44

标签: objective-c uitableview

我有一个UITableView,它由JSON文件中的文本和图像填充。 TableView单元格当前正在为文本中没有包含很多换行符的“帖子”正确调整大小,但我无法通过4或5个换行符来计算“帖子”的正确高度。

获得身高的代码:

-(float)height :(NSMutableAttributedString*)string
{
  NSString *stringToSize = [NSString stringWithFormat:@"%@", string];

  CGSize constraint = CGSizeMake(LABEL_WIDTH - (LABEL_MARGIN *2), 2000.f);

  CGSize size = [stringToSize sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:contraint lineBreakMode:NSLineBreakByWordWrapping];

  return size.height;
}

如何在允许换行和空白的同时计算正确的尺寸?

修改

方法的其余部分,

TableView CellForRow内部:

-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *row = [NSString stringWithFormat:@"%i", indexPath.row];

float postTextHeight = [self height:postText];

NSString *height = [NSString stringWithFormat:@"%f", heightOfPostText + 70];

[_cellSizes setObject:height forKey:row];
}

表格单元格的高度:

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *imageHeightString = [NSString stringWithFormat:@"%@", [_cellSizes objectForKey:indexPath.row]];

float heightOfCell = [imageHeightString floatValue];

 if (heightOfCell == 0) {

    return 217;
};

return heightOfCell + 5;
}

4 个答案:

答案 0 :(得分:16)

更好你需要先计算高度,不要在方法中包括高度计算部分:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

最好用方法计算:

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

因为你从json获取数据,你很容易计算    在“heightForRowAtIndexPath”方法中。

下面的代码将给出计算文本高度的例子,改变它的要求。 希望这有助于你:)

// i am using an array 
- (void)viewDidLoad
{
   [super viewDidLoad]; 
   // Do any additional setup after loading the view, typically from a nib.

   UIFont *labelFont = [UIFont fontWithName:@"Noteworthy-Bold" size:20];
   NSDictionary *arialdict = [NSDictionary dictionaryWithObject:labelFont forKey:NSFontAttributeName];

   NSMutableAttributedString *message = [[NSMutableAttributedString alloc] initWithString:@"this is just the sample example of how to calculate the dynamic height for tableview cell which is of around 7 to 8 lines. you will need to set the height of this string first, not seems to be calculated in cellForRowAtIndexPath method." attributes:arialdict];

   array = [NSMutableArray arrayWithObjects:message, nil];
   NSMutableAttributedString *message_1 = [[NSMutableAttributedString alloc] initWithString:@"you will need to set the height of this string first, not seems to be calculated in cellForRowAtIndexPath method." attributes:arialdict];
  [array addObject:message_1];   
}

 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
 {
     return 2;
 }

 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
 {
     return 2;
 }


 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
   UITableViewCell *Cell = [self.aTableView dequeueReusableCellWithIdentifier:@"cell"];
   if(Cell == nil)
    {
       Cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"];
     }

     //dont include the height calculation part hear, becz heights are already set for all the cell 
    [Cell.textLabel sizeToFit];
    Cell.textLabel.attributedText = [array objectAtIndex:indexPath.row]; // dont calculate height hear it will be called after "heightForRowAtIndexPath" method
    Cell.textLabel.numberOfLines = 8;
    return Cell;
 }

  // put ur height calculation method i took some hardcoded values change it :)
  -(float)height :(NSMutableAttributedString*)string
 {
    /*
      NSString *stringToSize = [NSString stringWithFormat:@"%@", string]; 
  // CGSize constraint = CGSizeMake(LABEL_WIDTH - (LABEL_MARGIN *2), 2000.f);
     CGSize maxSize = CGSizeMake(280, MAXFLOAT);//set max height //set the constant width, hear MAXFLOAT gives the maximum height

     CGSize size = [stringToSize sizeWithFont:[UIFont systemFontOfSize:20.0f] constrainedToSize:maxSize lineBreakMode:NSLineBreakByWordWrapping];
return size.height; //finally u get the correct height
    */
     //commenting the above code because "sizeWithFont: constrainedToSize:maxSize: lineBreakMode: " has been deprecated to avoid above code use below

    NSAttributedString *attributedText = string;
    CGRect rect = [attributedText boundingRectWithSize:(CGSize){225, MAXFLOAT}
                           options:NSStringDrawingUsesLineFragmentOrigin
                              context:nil];//you need to specify the some width, height will be calculated
    CGSize requiredSize = rect.size;
    return requiredSize.height; //finally u return your height
}


- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
 {
     //whatever the height u need to calculate calculate hear only    
     CGFloat heightOfcell = [self height:[array objectAtIndex:indexPath.row]];
     NSLog(@"%f",heightOfcell);
     return heightOfcell;
 }

希望这有助于你:)

SWIFT 版本

class ViewController: UIViewController,UITableViewDataSource,UITableViewDelegate 
{

var messageArray:[String] = [] //array to holde the response form son for example 
override func viewDidLoad()
{
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    messageArray = ["One of the most interesting features of Newsstand is that once an asset downloading has started it will continue even if the application is suspended (that is: not running but still in memory) or it is terminated. Of course during while your app is suspended it will not receive any status update but it will be woken up in the background",
                    "In case that app has been terminated while downloading was in progress, the situation is different. Infact in the event of a finished downloading the app can not be simply woken up and the connection delegate finish download method called, as when an app is terminated its App delegate object doesn’t exist anymore. In such case the system will relaunch the app in the background.", 
                    " If defined, this key will contain the array of all asset identifiers that caused the launch. From my tests it doesn’t seem this check is really required if you reconnect the pending downloading as explained in the next paragraph.",
                    ]
}

func numberOfSectionsInTableView(tableView: UITableView) -> Int
{
    return 1;
}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
    return messageArray.count;
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
    var cell:UITableViewCell? = tableView.dequeueReusableCellWithIdentifier("CELL") as? UITableViewCell;
    if(cell == nil)
    {
        cell = UITableViewCell(style:UITableViewCellStyle.Default, reuseIdentifier: "CELL")
        cell?.selectionStyle = UITableViewCellSelectionStyle.None
    }
    cell?.textLabel.font = UIFont.systemFontOfSize(15.0)
    cell?.textLabel.sizeToFit()
    cell?.textLabel.text = messageArray[indexPath.row]
    cell?.textLabel.numberOfLines = 0
    return cell!;
}

func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
{
    var height:CGFloat = self.calculateHeightForString(messageArray[indexPath.row])
    return height + 70.0
}

func calculateHeightForString(inString:String) -> CGFloat
{
    var messageString = inString
    var attributes = [UIFont(): UIFont.systemFontOfSize(15.0)]
    var attrString:NSAttributedString? = NSAttributedString(string: messageString, attributes: attributes)
    var rect:CGRect = attrString!.boundingRectWithSize(CGSizeMake(300.0,CGFloat.max), options: NSStringDrawingOptions.UsesLineFragmentOrigin, context:nil )
    var requredSize:CGRect = rect
    return requredSize.height  //to include button's in your tableview

 }
}

答案 1 :(得分:1)

@Shan有一个很好的答案,但它对我来说并不完全有用。

这是我用来计算单元格高度的代码

-(float)height :(NSMutableAttributedString*)string
{
    CGRect rect = [string boundingRectWithSize:(CGSize){table.frame.size.width - 110, MAXFLOAT} options:NSStringDrawingUsesLineFragmentOrigin context:nil];
    return rect.size.height;
}

我执行-110因为这会在顶部和底部的侧面给出相等的空间。

希望这有帮助。

答案 2 :(得分:0)

实现此表视图委托方法:

-tableView:heightForRowAtIndexPath:

https://developer.apple.com/library/ios/documentation/uikit/reference/UITableViewDelegate_Protocol/Reference/Reference.html#//apple_ref/occ/intfm/UITableViewDelegate/tableView:heightForRowAtIndexPath

您将调用您的方法来确定高度,并根据需要使用一些额外的填充返回该值。

答案 3 :(得分:-1)

我建议的方法是设置实际标签的文本,并通过调用sizeToFit获取所需的高度。为此,您必须将标签的numberOfLines属性设置为0并设置所需的最大宽度。

将此技术用于表格视图时,您可以使用prototype cell method discussed here使用实际单元格计算高度。