【问题标题】:How to resize UITableViewCell to fit its content?如何调整 UITableViewCell 的大小以适应其内容?
【发布时间】:2013-10-06 16:24:47
【问题描述】:

我有一个UITableview 有多个可重复使用的 TableViewCells。 在一个单元格中,我有一个UITextView,它会调整自身大小以适应其内容。现在我“只是”必须调整 TableViewCell 的 contentView 的大小,这样我就可以阅读 while 文本。我已经试过了:

cell2.contentView.bounds.size.height = cell2.discriptionTextView.bounds.size.height; 

或者:

cell2.contentView.frame = CGRectMake(0, cell2.discriptionTextView.bounds.origin.y,     
cell2.discriptionTextView.bounds.size.width,     
cell2.discriptionTextView.bounds.size.height); 

在方法中:

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

但它不会起作用。

有人知道怎么做吗?

新代码:

    @implementation AppDetail

    CGFloat height;
    …

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

    cell2.TextView.text = self.text;
            [cell2.TextView sizeToFit];
            height = CGRectGetHeight(cell2.TextView.bounds);
     …
    }

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

        if (indexPath.row == 0) {
            return 143;
        }
        if (indexPath.row == 1) {
            return height;
        }

        return 0;
    }

【问题讨论】:

    标签: ios objective-c uitableview


    【解决方案1】:

    您只能在tableView:heightForRowAtIndexPath: 委托方法中调整 UITableViewCell 的大小。

    您必须估计在加载 tableView 时为每一行调用该方法时文本的大小。

    这就是我为解决问题所做的。

    -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
     {
         NSString * yourText = self.myArrayWithTextInIt[indexPath.row]; // or however you are getting the text
         return additionalSpaceNeeded + [self heightForText:yourText];
     }
    
     -(CGFloat)heightForText:(NSString *)text
     {
       NSInteger MAX_HEIGHT = 2000;
       UITextView * textView = [[UITextView alloc] initWithFrame: CGRectMake(0, 0, WIDTH_OF_TEXTVIEW, MAX_HEIGHT)];
       textView.text = text;
       textView.font = // your font
       [textView sizeToFit];
       return textView.frame.size.height;
      }
    

    编辑

    虽然我使用了这个解决方案一段时间,但我发现了一个更理想的解决方案,我建议使用它,因为它不需要分配整个 textView 即可工作,并且可以处理大于 2000 的文本。

    -(CGFloat)heightForTextViewRectWithWidth:(CGFloat)width andText:(NSString *)text
    {
        UIFont * font = [UIFont systemFontOfSize:12.0f];
    
        // this returns us the size of the text for a rect but assumes 0, 0 origin
        CGSize size = [text sizeWithAttributes:@{NSFontAttributeName: font}];
    
        // so we calculate the area
        CGFloat area = size.height * size.width;
    
        CGFloat buffer = whateverExtraBufferYouNeed.0f;
    
        // and then return the new height which is the area divided by the width
        // Basically area = h * w
        // area / width = h
        // for w we use the width of the actual text view
        return floor(area/width) + buffer;
    }
    

    【讨论】:

    • 你想做什么?调整 textView 或单元格的 contentView 大小?
    • 我上面展示的方法将允许您根据单元格中给定 textView 的 contentView 的大小来重新调整单元格本身的大小。您需要做的就是找到用于给定单元格的文本。
    • 你的回答不完整additionalSpaceNeeded是什么
    • 嘿,Al Pacino,这应该是不言自明的,additionalSpaceNeeded 是您在 textView 之外需要的任何额外空间。
    • 你如何改变宽度呢?
    【解决方案2】:

    正如@Rob Norback 所说,有一个东西叫UITableViewAutomaticDimension

    对于 Swift,动态调整 UITableViewCell 内容大小的最简单方法就是添加它。

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

    【讨论】:

    【解决方案3】:

    这是 iOS 7+ 的更新版本,更干净(没有额外的方法)

    -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
        {
            UIFont * font = [UIFont systemFontOfSize:15.0f];
            NSString *text = [getYourTextArray objectAtIndex:indexPath.row];
            CGFloat height = [text boundingRectWithSize:CGSizeMake(self.tableView.frame.size.width, maxHeight) options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading) attributes:@{NSFontAttributeName: font} context:nil].size.height;
    
            return height + additionalHeightBuffer;
        }
    

    【讨论】:

      【解决方案4】:

      您需要实现heightForRowAtIndexPath

      假设textView中要显示的数据存储在一个NSArray中。

      - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
       CGFloat cellheight = 30; //assuming that your TextView's origin.y is 30 and TextView is the last UI element in your cell
      
       NSString *text = (NSString *)[textArray objectAtIndex:indexpath.row];
       UIFont *font = [UIFont systemFontOfSize:14];// The font should be the same as that of your textView
       CGSize constraintSize = CGSizeMake(maxWidth, CGFLOAT_MAX);// maxWidth = max width for the textView
      
       CGSize size = [text sizeWithFont:font constrainedToSize:constraintSize lineBreakMode:UILineBreakModeWordWrap];
      
       cellHeight += size.height; //you can also add a cell padding if you want some space below textView
      
      }
      

      【讨论】:

      • 好的,我现在添加了你的代码,它可以工作,但只是你第二次查看 UIViewController。我创建了一个 CGFloat,然后将 UITextView 的高度分配给 CGFloat。然后我在上面发布的方法中返回创建的 CGFloat。我将在上面发布我的新代码。
      • 你应该知道的第一件事是你没有在'cellForRowAtIndexpath'中设置单元格的高度它应该在'heightForRowAtIndexpath'中完成第二件事是在'cellForRowAtIndexpath'之前调用'heightForRowAtIndexpath'。这意味着您必须在填充同一单元格之前计算单元格的高度。(在您开始填充单元格之前,应告知表格的高度
      • 注意:所有UILineBreakMode* 都已弃用,替换为NSLineBreakBy*
      • 你如何改变宽度呢?
      • 你可以把 UITableView 变小。
      【解决方案5】:

      我赞成this solution of Jure

      • 首先,将 textview 的约束设置为其父视图(在本例中为单元格的 contentView)固定。
      • 禁用textView.scrollEnabled
      • 设置

        table.rowHeight = UITableViewAutomaticDimension;
        tableView.estimatedRowHeight = 44;
        

        如果最后,您的代码不起作用,请改用它

        - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
            return UITableViewAutomaticDimension;
        }
        
        - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
            return 44;
        }
        
      • 像这样实现UITextViewDelegate

        - (void)textViewDidChange:(UITextView *)textView {
             CGPoint currentOffset = self.tableView.contentOffset;
             [UIView setAnimationsEnabled:NO];
             [self.tableView beginUpdates];
             [self.tableView endUpdates];
             [UIView setAnimationsEnabled:YES];
             [self.tableView setContentOffset:currentOffset animated:NO];
          }
        

      【讨论】:

      • 还有没有故事板的例子?
      【解决方案6】:

      这个线程已经有一段时间了,但是在 iOS 8 中引入了UITableViewAutomaticDimension。您必须像滚动视图一样从单元格的顶部到底部设置约束才能使其工作。但之后,只需将以下代码添加到viewDidLoad()

      tableView.rowHeight = UITableViewAutomaticDimension
      tableView.estimatedRowHeight = 122.0
      

      确保您的估计高度尽可能接近真实高度,否则您会得到一些错误的滚动。

      【讨论】:

        【解决方案7】:

        使用 UITableViewAutomaticDimension 将这两个方法添加到 ViewController 应该可以解决问题。当在具有可变长度文本的 UITableViewCell 中嵌入 UITextView 时,它对我有用。

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

        【讨论】:

          【解决方案8】:

          对于 UITableViewCell 中的 UILabel 子视图,我仅通过设置标签的约束(使用情节提要,Xcode 8.3.2)完成了标签的自动调整大小。

          这是有效的,因为显然标签和单元格的默认行为是 sizeToFit。 UITextView 也应该这样。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2021-05-21
            • 2012-07-22
            • 1970-01-01
            • 1970-01-01
            • 2015-05-16
            • 1970-01-01
            • 1970-01-01
            • 2016-10-28
            相关资源
            最近更新 更多