How to resize UITableViewCell to fit its content?

前端 未结 8 730
有刺的猬
有刺的猬 2020-12-08 05:34

I have a UITableview with multiple reusable TableViewCells. In one cell I have a UITextView, that resizes itself to fit its content. Now I \"just\

相关标签:
8条回答
  • 2020-12-08 05:34

    You can only resize a UITableViewCell in tableView:heightForRowAtIndexPath: delegate method.

    You have to estimate what the size of the text will be when that method is called for every row when the tableView is loaded.

    This is what I did to solve the problem.

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

    EDIT

    While I used this solution for a while, I found a more optimal one that I would recommend using as it doesn't require allocating an entire textView in order to work, and can handle text greater than 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;
    }
    
    0 讨论(0)
  • 2020-12-08 05:37

    You need you implement heightForRowAtIndexPath.

    Say that the data that is to be displayed in the textView is stored in a 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
    
    }
    
    0 讨论(0)
  • 2020-12-08 05:37

    This thread has been quite a while, but in iOS 8 UITableViewAutomaticDimension was introduced. You have to set constraints from the top to the bottom of the cell like a scroll view to make this work. But after that, just add the following code to viewDidLoad():

    tableView.rowHeight = UITableViewAutomaticDimension
    tableView.estimatedRowHeight = 122.0
    

    Make sure your estimated height is as close as possible to the real thing otherwise you'll get some buggy scrolling.

    0 讨论(0)
  • 2020-12-08 05:40

    I favor this solution of Jure

    • First, set constraints of textview to be pinned with its superview (cell's contentView in this case).
    • Disable textView.scrollEnabled
    • Set

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

      If finally, your code not works, then use this instead

      - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
          return UITableViewAutomaticDimension;
      }
      
      - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
          return 44;
      }
      
    • Implement UITextViewDelegate like this:

      - (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];
        }
      
    0 讨论(0)
  • 2020-12-08 05:41

    As @Rob Norback said, There is something called UITableViewAutomaticDimension.

    For Swift, The easiest way to resize content from UITableViewCell on the fly is to just add this.

    override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        return UITableViewAutomaticDimension
    }
    
    override func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
         return UITableViewAutomaticDimension
    }
    
    0 讨论(0)
  • 2020-12-08 05:49

    Adding these two methods to the ViewController with UITableViewAutomaticDimension should do the trick. It has worked for me when embedding a UITextView inside of a UITableViewCell with variable length text.

    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        return UITableViewAutomaticDimension;
    }
    
    - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        return UITableViewAutomaticDimension;
    }
    
    0 讨论(0)
提交回复
热议问题