简体   繁体   English

具有动态高度iOS的UITableViewCell

[英]UITableViewCell with dynamic height iOS

I have implemented TableView with CustomCell in my app, 我在我的应用程序中使用CustomCell实现了TableView,

I want dynamic height of my UITableViewCell according to text length in UITableViewCell , 我希望我的动力高度UITableViewCell根据文本长度UITableViewCell

here is the snapshot of Customcell 这是Customcell的快照

: and here is the snapshot of my UITableView :这是我的UITableView的快照 : code snippet for heightForRowAtIndexPath heightForRowAtIndexPath代码段

#define FONT_SIZE 14.0f
#define CELL_CONTENT_WIDTH 320.0f
#define CELL_CONTENT_MARGIN 10.0f

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
{
    NSString *text = [DescArr objectAtIndex:[indexPath row]];
    CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 20000.0f);
    CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:UILineBreakModeWordWrap];
    CGFloat height = MAX(size.height, 100.0);
    return height; 
}

As you can see in the 2nd image, height for cell is fixed, it doesn't change with it's text (content) size. 正如您在第二张图片中看到的那样,单元格的高度是固定的,它不会随着文本(内容)大小而变化。

Where am I making mistake? 我哪里弄错了? How can I make aa label or a cell to update its size according to its contents/text? 如何根据其内容/文本制作标签或单元格以更新其大小?

Please, Look HERE - Dynamic Table View Cell Height and Auto Layout tutorial. 请看这里 - 动态表视图单元格高度和自动布局教程。

What you need: 你需要什么:

  • set required constraint on elements in cell (make shure that all done correctly, if no - you can get a lot of problem). 为单元格中的元素设置必需的约束(使shure全部正确完成,如果没有 - 你可以得到很多问题)。 Also make shure that you set IntrinsicSize to PlaceHolder value 还要确保将IntrinsicSize设置为PlaceHolder值

在此输入图像描述

  • add few method for calculating size of cell 添加几种计算细胞大小的方法

Methods: 方法:

//this will calculate required height for your cell
-(CGFloat)heightForBasicCellAtIndexPath:(NSIndexPath *)indexPath {
      static UIYourClassCellName *sizingCell = nil;
      //create just once per programm launching
      static dispatch_once_t onceToken;
      dispatch_once(&onceToken, ^{
      sizingCell = [self.tableView dequeueReusableCellWithIdentifier:@"identifierOfCell"];
});
  [self configureBasicCell:sizingCell atIndexPath:indexPath];
  return [self calculateHeightForConfiguredSizingCell:sizingCell];
}
//this method will calculate required height of cell
- (CGFloat)calculateHeightForConfiguredSizingCell:(UITableViewCell *)sizingCell {
      [sizingCell setNeedsLayout];
      [sizingCell layoutIfNeeded];
      CGSize size = [sizingCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
      return size.height;
}

And call 并致电

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
  return [self heightForBasicCellAtIndexPath:indexPath];
}

Configuration of cell 细胞的配置

- (void)configureBasicCell:(RWBasicCell *)cell atIndexPath:(NSIndexPath *)indexPath {
    //make some configuration for your cell
}

After all operation i got next (text inside cell only as placeholder): 在接下来的所有操作之后(单元格内的文本仅作为占位符):

在此输入图像描述

The following code worked fine for me.Try with this 以下代码对我来说很好。试试这个

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

    CGFloat lRetval = 10;
    CGSize maximumLabelSize = CGSizeMake(231, FLT_MAX);
    CGSize expectedLabelSize;


    CGFloat numberoflines = [thirdcellText length]/17.0;

    if (indexPath.section == 0) {
        expectedLabelSize = [firstcellText sizeWithFont:[UIFont systemFontOfSize:16.0]
                                      constrainedToSize:maximumLabelSize
                                          lineBreakMode:NSLineBreakByWordWrapping];
        lRetval = expectedLabelSize.height;
    }
    else if(indexPath.section == 1)
    {
        expectedLabelSize = [secondcellText sizeWithFont:[UIFont systemFontOfSize:16.0]
                                       constrainedToSize:maximumLabelSize
                                           lineBreakMode:NSLineBreakByWordWrapping];
        lRetval = expectedLabelSize.height;
    }
    else if (indexPath.section == 2)
    {
        expectedLabelSize = [thirdcellText sizeWithFont:[UIFont systemFontOfSize:16.0]
                                       constrainedToSize:CGSizeMake(231, numberoflines*17.0)
                                           lineBreakMode:NSLineBreakByWordWrapping];
        lRetval = expectedLabelSize.height-128.0;
    }

    UIImage *factoryImage = [UIImage imageNamed:NSLocalizedString(@"barcode_factory_reset.png", @"")];

    CGFloat height = factoryImage.size.height;

    if (lRetval < height) {
        lRetval = height+15.0;
    }

    return lRetval;
}

Try to add the following code in your customcell class autolayout method 尝试在customcell类autolayout方法中添加以下代码

textview.frame = frame;
CGRect frame1 = textview.frame;
frame1.size.height = textview.contentSize.height-2;
textview.frame = frame1;


textview.contentSize = CGSizeMake(textview.frame.size.width, textview.frame.size.height);

labelPtr.frame = CGRectMake(CGRectGetMinX(imageView.frame)+CGRectGetMaxX(imageView.frame)+5.0, textview.frame.size.height+10.0, 140, 16.0);
[labelPtr setNeedsDisplayInRect:labelPtr.frame];

Try to set the label properties like the following 尝试设置如下的标签属性

labelPtr = [[UILabel alloc] initWithFrame:CGRectZero];
labelPtr.backgroundColor =[UIColor clearColor];
[labelPtr setNeedsLayout];
[labelPtr setNeedsDisplay];
[self.contentView addSubview:labelPtr];

A'm looking for a long time how to determinate cell height properly, - looks like - it's a best solution, boundingRectWithSize and constrainedToSize often incorrectly calculated text height, you need to create UILabel than use sizeThatFits function, see below 我正在寻找很长时间如何正确确定单元格高度, - 看起来像 - 这是一个最好的解决方案,boundingRectWithSize和constrainedToSize经常错误地计算文本高度,你需要创建UILabel而不是使用sizeThatFits函数,见下文

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

    UILabel  * label = [[UILabel alloc] initWithFrame:CGRectMake(8, 5, celllabelWidth, 9999)];
    label.numberOfLines=0;
    label.font = [UIFont fontWithName:fontName size:textSize];
    label.text = @"celllabelTextHere";

    CGSize maximumLabelSize = CGSizeMake(celllabelWidth, 9999);
    CGSize expectedSize = [label sizeThatFits:maximumLabelSize];
    return expectedSize.height;
}

I saw a lot of solutions but all was wrong or uncomplet. 我看到了很多解决方案,但都是错误的或不完整的。 You can solve all problems with 5 lines in viewDidLoad and autolayout. 您可以在viewDidLoad和autolayout中解决5行的所有问题。 This for objetive C: 这对于客观C:

_tableView.delegate = self;
_tableView.dataSource = self;
self.tableView.estimatedRowHeight = 80;//the estimatedRowHeight but if is more this autoincremented with autolayout
self.tableView.rowHeight = UITableViewAutomaticDimension;
[self.tableView setNeedsLayout];
[self.tableView layoutIfNeeded];
self.tableView.contentInset = UIEdgeInsetsMake(20, 0, 0, 0) ;

For swift 2.0: 对于swift 2.0:

 self.tableView.estimatedRowHeight = 80
 self.tableView.rowHeight = UITableViewAutomaticDimension      
 self.tableView.setNeedsLayout()
 self.tableView.layoutIfNeeded()
 self.tableView.contentInset = UIEdgeInsetsMake(20, 0, 0, 0)

Now create your cell with xib or into tableview in your Storyboard With this you no need implement nothing more or override. 现在使用xib创建您的单元格或在Storyboard中创建tableview使用此功能,您无需再执行任何操作或覆盖。 (Don forget number os lines 0) and the bottom label (constrain) downgrade "Content Hugging Priority -- Vertical to 250" (不要忘记数字os行0)和底部标签(约束)降级“内容拥抱优先级 - 垂直到250”

在此输入图像描述 在此输入图像描述

You can donwload the code in the next url: https://github.com/jposes22/exampleTableCellCustomHeight 您可以在下一个网址中下载代码: https//github.com/jposes22/exampleTableCellCustomHeight

References: http://candycode.io/automatically-resizing-uitableviewcells-with-dynamic-text-height-using-auto-layout/ 参考文献: http//candycode.io/automatically-resizing-uitableviewcells-with-dynamic-text-height-using-auto-layout/

This is very simple now 现在这很简单
Use below steps 使用以下步骤

  1. Set constraint to your Label (If using custom cell) 将约束设置为您的标签(如果使用自定义单元格)
  2. Number of line must be 0 行数必须为0
  3. Setup few properties of UITableView 设置UITableView的一些属性

self.tableView.estimatedRowHeight = 100.0;
self.tableView.rowHeight = UITableViewAutomaticDimension;

Enjoy:) 请享用:)
For more detail you can check 有关详细信息,请查看
www.raywenderlich.com www.raywenderlich.com
stackoverflow.com stackoverflow.com

Could you try this; 你能试试吗?

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
    {
     int topPadding = cell.yourLabel.frame.origin.x;
     int bottomPadding = cell.frame.size.heigth-(topPadding+cell.yourLabel.frame.size.height);
     NSString *text = [DescArr objectAtIndex:[indexPath row]];
     CGSize maximumSize = CGSizeMake(cell.yourLabel.frame.size.width, 9999);
     CGSize expectedSize = [text sizeWithFont:yourCell.yourLabel.font constrainedToSize:maximumSize lineBreakMode:yourCell.yourLabel.lineBreakMode];

     return topPadding+expectedSize.height+bottomPadding;
}

Refer this link you are using Autolayout 请参阅此链接,您正在使用Autolayout

else you can use below approach 否则你可以使用以下方法

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


NewsVCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];

if (cell == nil)
{

    cell = [[NewsVCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"];

}

cell.titleCell.numberOfLines = 0;
cell.descriptionCell.numberOfLines = 0;

cell.titleCell.font = [UIFont systemFontOfSize:12.0f];
cell.descriptionCell.font = [UIFont systemFontOfSize:12.0f];

cell.descriptionCell.textColor = [UIColor lightGrayColor];


CGSize maximumLabelSize;

if([UIDevice currentDevice].userInterfaceIdiom==UIUserInterfaceIdiomPad || [[[UIDevice currentDevice] model] isEqualToString:@"iPad Simulator"])
{
    maximumLabelSize = CGSizeMake(768, 10000);

}
else
{
    maximumLabelSize = CGSizeMake(270, 10000);

}

NSString *newsTitle =  [[feeds objectAtIndex:indexPath.row] objectForKey: @"title"];

NSString *descriptionsText = [[feeds objectAtIndex:indexPath.row] objectForKey: @"description"];


CGSize expectedTitleLabelSize = [newsTitle sizeWithFont: cell.titleCell.font constrainedToSize:maximumLabelSize lineBreakMode:cell.titleCell.lineBreakMode];

CGSize expectedDescriptionLabelSize = [descriptionsText sizeWithFont:cell.descriptionCell.font constrainedToSize:maximumLabelSize lineBreakMode:cell.descriptionCell.lineBreakMode];

NSLog(@"cellForRowAtIndexPath :indexpath.row %d: height expectedTitleLabelSize:%f , indexpath.row height expectedDescriptionLabelSize:%f",indexPath.row,expectedTitleLabelSize.height,expectedDescriptionLabelSize.height);



if (newsTitle.length > 0)
{

    cell.titleCell.frame = CGRectMake(20.0f, 10.0f, 270.0f ,expectedTitleLabelSize.height+20.0f);

}
else
{
     cell.titleCell.frame = CGRectMake(20.0f, 10.0f, 270.0f ,expectedTitleLabelSize.height-20.0f);
}


if (descriptionText.length > 0)
{
    cell.descriptionCell.frame =  CGRectMake(20.0f, 10.0f + cell.titleCell.frame.size.height, 270.0f, expectedDescriptionLabelSize.height+20.0f);

}
else
{
    cell.descriptionCell.frame =  CGRectMake(20.0f, cell.titleCell.frame.size.height, 270.0f, 0.0f);

}


  cell.descriptionCell.frame =  CGRectMake(20.0f, 10.0f + cell.titleCell.frame.size.height, 270.0f, expectedDescriptionLabelSize.height+20.0f);

cell.titleCell.text = newsTitle;
cell.descriptionCell.text = descriptionsText;

NSLog(@"indexpath.row %d :title %@ ",indexPath.row,newsTitle);

NSLog(@"indexpath.row %d :description %@",indexPath.row,descriptionsText);

return cell;

 }

pragma mark - UITableViewDelegate pragma mark - UITableViewDelegate

   - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
 {
float totalHeight = 0.0f;

UILabel *labelTitle;


CGSize maximumLabelSize;


if([UIDevice currentDevice].userInterfaceIdiom==UIUserInterfaceIdiomPad || [[[UIDevice currentDevice] model] isEqualToString:@"iPad Simulator"])
{
    labelTitle = [[UILabel alloc]initWithFrame:CGRectMake(0.0f, 0.0f, 692.0f, 20.0f)];  // iPad
    maximumLabelSize = CGSizeMake(768.0f, 10000.0f);

}
else
{
    labelTitle = [[UILabel alloc]initWithFrame:CGRectMake(0.0f, 0.0f, 270.0f, 20.0f)];
    maximumLabelSize = CGSizeMake(270.0f, 10000.0f);

}



labelTitle.font = [UIFont systemFontOfSize:12.0f];


NSString *newsTitle;
NSString *newsDescription;

  //  cell.titleCell.text = [[feeds objectAtIndex:indexPath.row] objectForKey: @"title"];
  //   cell.descriptionCell.text = [[feeds objectAtIndex:indexPath.row] objectForKey: @"description"];



    newsTitle = [[feeds objectAtIndex:indexPath.row] objectForKey: @"title"];

    newsDescription = [[feeds objectAtIndex:indexPath.row] objectForKey: @"description"];

NSLog(@"indexpath.row %d :newsDescription.length %d",indexPath.row,newsDescription.length);
CGSize expectedTitleLabelSize;
CGSize expectedDescriptionLabelSize;


if (newsTitle.length > 0)
{
    expectedTitleLabelSize = [newsTitle sizeWithFont:labelTitle.font constrainedToSize:maximumLabelSize lineBreakMode:labelTitle.lineBreakMode];
    totalHeight = totalHeight + 20.0f;
}
else
{
    expectedTitleLabelSize = CGSizeMake(0.0f, 0.0f);
    totalHeight = -20.0f;
}

if (newsDescription.length > 0)
{
    expectedDescriptionLabelSize = [newsDescription sizeWithFont:labelTitle.font constrainedToSize:maximumLabelSize lineBreakMode:labelTitle.lineBreakMode];
    totalHeight = totalHeight + 20.0f;

}
else
{
    expectedDescriptionLabelSize = CGSizeMake(0.0f, 0.0f);
    totalHeight = -20.0f;
}


//  NSLog(@"question: %f title:%f",expectedQuestionLabelSize.height,expectedTitleLabelSize.height);

totalHeight = expectedDescriptionLabelSize.height + expectedTitleLabelSize.height + 30.0f+20.0f;




return totalHeight;

 }

如果要将最大高度限制为100 pt,则必须在MAX上使用MIN

CGFloat height = fmin(size.height, 100.0);

To set automatic dimension for row height & estimated row height, ensure following steps to make, auto dimension effective for cell/row height layout. 要设置行高和估计行高的自动尺寸,请确保执行以下步骤,自动尺寸对单元格/行高度布局有效。

  • Assign and implement tableview dataSource and delegate 分配并实现tableview dataSource和delegate
  • Assign UITableViewAutomaticDimension to rowHeight & estimatedRowHeight UITableViewAutomaticDimension分配给rowHeight和estimatedRowHeight
  • Implement delegate/dataSource methods (ie heightForRowAt and return a value UITableViewAutomaticDimension to it) 实现delegate / dataSource方法(即heightForRowAt并向其返回值UITableViewAutomaticDimension

- -

@IBOutlet weak var table: UITableView!

override func viewDidLoad() {
    super.viewDidLoad()

    // Don't forget to set dataSource and delegate for table
    table.dataSource = self
    table.delegate = self

    // Set automatic dimensions for row height
    // Swift 4.2 onwards
    table.rowHeight = UITableView.automaticDimension
    table.estimatedRowHeight = UITableView.automaticDimension


    // Swift 4.1 and below
    table.rowHeight = UITableViewAutomaticDimension
    table.estimatedRowHeight = UITableViewAutomaticDimension

}



// UITableViewAutomaticDimension calculates height of label contents/text
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    // Swift 4.2 onwards
    return UITableView.automaticDimension

    // Swift 4.1 and below
    return UITableViewAutomaticDimension
}

For label instance in UITableviewCell 对于UITableviewCell中的标签实例

  • Set number of lines = 0 (& line break mode = truncate tail) 设置行数= 0(&换行模式=截断尾部)
  • Set all constraints (top, bottom, right left) with respect to its superview/ cell container. 设置相对于其superview / cell容器的所有约束(顶部,底部,右侧)。
  • Optional : Set minimum height for label, if you want minimum vertical area covered by label, even if there is no data. 可选 :如果您希望标签覆盖最小垂直区域,即使没有数据,也可以设置标签的最小高度。

在此输入图像描述

I needed a dynamic table view cell height based on the amount of text to be displayed in that cell. 我需要一个基于要在该单元格中显示的文本量的动态表格视图单元格高度。 I solved it in this way: 我用这种方式解决了它:

    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        if (!isLoading)
        {

            if ([self.conditionsDataArray count]>0)
            {
                Conditions *condition =[self.conditionsDataArray objectAtIndex:indexPath.row];
                int height;
                UITextView *textview = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, 236, 0)];   //you can set your frame according to your need
                textview.text  = condition.comment;
                textview.autoresizingMask = UIViewAutoresizingFlexibleHeight;
                [tableView addSubview:textview];
                textview.hidden = YES;
                height = textview.contentSize.height;
                NSLog(@"TEXT VIEW HEIGHT %f", textview.contentSize.height);
                [textview removeFromSuperview];
                [textview release];
                return height;
       }
       return 55;  //Default height, if data is in loading state
}

Notice that the Text View has been added as Subview and then made hidden, so make sure you add it as SubView otherwise it's height will not be considered. 请注意,文本视图已添加为子视图,然后隐藏,因此请确保将其添加为SubView,否则将不考虑其高度。

I just wrote about this problem and the approach I finally chose. 我刚刚写了这个问题以及我最终选择的方法。 You can read about it here: Dynamic UITableView Cell Height Based on Contents 你可以在这里阅读它: 基于内容的动态UITableView单元格高度

Basically, I created a UITableView subclass that handles all this for both default and custom cells. 基本上,我创建了一个UITableView子类,它为默认和自定义单元格处理所有这些。 It probably needs tweaking, but I have used it as is with good result. 它可能需要调整,但我已经使用它,结果很好。

You can grab the code here: https://github.com/danielsaidi/DSTableViewWithDynamicHeight 你可以在这里获取代码: https//github.com/danielsaidi/DSTableViewWithDynamicHeight

Hope it helps (...and if it didn't, I apologize and would love to hear why not) 希望它有所帮助(......如果没有,我道歉,并希望听到为什么不)

Try This, It worked like a charm! 试试吧,它就像一个魅力! for me, 为了我,

In viewDidLoad write this code, 在viewDidLoad中写这段代码,

-(void)viewDidLoad 
{
[super viewDidLoad];
 self.tableView.estimatedRowHeight = 100.0; // for example. Set your average height
 self.tableView.rowHeight = UITableViewAutomaticDimension;
}

In cellForRowAtIndexPath write this code, 在cellForRowAtIndexPath中编写此代码,

 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
 {
  static NSString *CellIdentifier = @"Cell";
  UITableViewCell *cell = [tableView 
  dequeueReusableCellWithIdentifier:CellIdentifier];
 if (cell == nil) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] ;
  }
    cell.textLabel.numberOfLines = 0; // Set label number of line to 0
    cell.textLabel.text=[[self.arForTable objectAtIndex:indexPath.row] valueForKey:@"menu"];
    [cell.textLabel sizeToFit]; //set size to fit 
    return cell;
 }

Hopes so this will help for some one . 希望这对某些人有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM