Resize Custom cell with a UILabel on it based on content text from JSON file

前端 未结 3 1824
借酒劲吻你
借酒劲吻你 2021-01-24 04:47

I\'m parsing a JSON string into a custom table view cell. How can I resize the label\'s height to fit the content text and also resize the cell to fit it\'s content.

Th

相关标签:
3条回答
  • 2021-01-24 05:23

    If you want the cell to resize based on the content of the JSON you have to change the following method:

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

    You're setting the height of each cell to 124px. What you should do instead it's to:

    1. Get the size of the string rendered with the specified constraints.
    2. Reset the frame of the label that contains the string
    3. Return the right size for the cell in tableView:heightForRowAtIndexPath:

    Hope it helps! Cheers

    0 讨论(0)
  • 2021-01-24 05:30

    Use this to a dynamic sized cell:

    Start by defining the following:

    #define FONT_SIZE 13.0f 
    #define CELL_CONTENT_WIDTH 290.0f 
    #define CELL_CONTENT_MARGIN 19.0f 
    
    1. Implement the following helper method;

       -(CGSize)frameForText:(NSString*)text sizeWithFont:(UIFont*)font constrainedToSize:(CGSize)size  {
      
      NSMutableParagraphStyle * paragraphStyle = [[NSMutableParagraphStyle defaultParagraphStyle] mutableCopy];
      paragraphStyle.lineBreakMode = NSLineBreakByCharWrapping;
      
      NSDictionary * attributes = @{NSFontAttributeName:font,
                                    NSParagraphStyleAttributeName:paragraphStyle
                                    };
      
      
      CGRect textRect = [text boundingRectWithSize:size
                                           options:NSStringDrawingUsesLineFragmentOrigin
                                        attributes:attributes
                                           context:nil];
      
      
      // This contains both height and width, but we really care about height.
      return textRect.size;
      }
      
    2. In your UITableViewDelegate Height method:

      - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
      {
      
      NSDictionary *movie = [self.movies objectAtIndex:indexPath.row];
      
              NSString *text = [movie objectForKey:@"message"];        
      
              CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 20000.0f);
      
              CGSize size = [self frameForText:text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint];
      
              CGFloat height = MAX(size.height, 14.0f);
      
              return height + CELL_CONTENT_MARGIN;
      
      
      }
      
    3. Set the frame and text in your UITableViews cellForRowAtIndexPath:

      - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
      static NSString *simpleTableIdentifier = @"PostsObject";
      
      PostsObject *cell = (PostsObject *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
      if (cell == nil)
      {
          NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"PostsObject" owner:self options:nil];
          cell = [nib objectAtIndex:0];
          cell.selectionStyle = UITableViewCellSelectionStyleNone;
          UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"background.png"]];
      
          self.tableView.backgroundView = imageView;
      }
      
      NSDictionary *movie = [self.movies objectAtIndex:indexPath.row];
      
      NSString *text = [movie objectForKey:@"message"];
      
      
          CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 20000.0f);
      
      
          CGSize size = [self frameForText:text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint];
      
          cell.txtLabel.text = text;
          cell.txtLabel.frame = CGRectMake(CELL_CONTENT_MARGIN, CELL_CONTENT_MARGIN, CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), MAX(size.height, 14.0f));
      
      cell.published.text = [movie objectForKey:@"published"];
      
      return cell;
      }
      
    0 讨论(0)
  • 2021-01-24 05:31

    This Is a full code for resizing the cell's height according to the text length for each indexPath:

    The .h file:

    #import <UIKit/UIKit.h>
    
    @interface ViewController : UIViewController <UITableViewDataSource, UITableViewDelegate> {
        IBOutlet UITableView *_tableView;
        UIActivityIndicatorView *_activityIndicatorView;
        NSArray *_movies;
        CGFloat cellTextWidth;
        CGFloat cellHeightExceptText;
    }
    @property (nonatomic, retain) UIFont *fontForCellText;
    @property (nonatomic, retain) UITableView *tableView;
    @property (nonatomic, retain) UIActivityIndicatorView *activityIndicatorView;
    @property (nonatomic, retain) NSArray *movies;
    
    @end
    

    The .m file:

    #import "ViewController.h"
    #import "AFNetworking.h"
    #import "ParseFeedCell.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    @synthesize tableView = _tableView, activityIndicatorView = _activityIndicatorView, movies = _movies;
    @synthesize fontForCellText;
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
    
        NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"ParseFeedCell" owner:self options:nil];
        ParseFeedCell *cell = [nib objectAtIndex:0];
        fontForCellText = cell.title.font;
        cellTextWidth = cell.title.frame.size.width;
        cellHeightExceptText = cell.frame.size.height - cell.title.frame.size.height;
    
        [self.navigationController setNavigationBarHidden:YES];
    
        self.tableView.separatorColor = [UIColor clearColor];
    
        // Setting Up Activity Indicator View
        self.activityIndicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
        self.activityIndicatorView.hidesWhenStopped = YES;
        self.activityIndicatorView.center = self.view.center;
        [self.view addSubview:self.activityIndicatorView];
        [self.activityIndicatorView startAnimating];
        self.tableView.separatorColor = [UIColor clearColor];
    
        // Initializing Data Source
        //self.movies = [[NSArray alloc] init];
    
        NSURL *url = [[NSURL alloc] initWithString:@"your-website.com/json_file?name=Name"];
        NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
    
        AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
            self.movies = [[NSArray alloc] initWithArray:JSON];
            [self.activityIndicatorView stopAnimating];
            [self.tableView reloadData];
    
        } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
            NSLog(@"Request Failed with Error: %@, %@", error, error.userInfo);
        }];
    
        [operation start];
    }
    
    // Table View Data Source Methods
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
        if (self.movies && self.movies.count) {
            return self.movies.count;
        } else {
            return 0;
        }
    }
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        static NSString *simpleTableIdentifier = @"ParseFeedCell";
    
        ParseFeedCell *cell = (ParseFeedCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
        if (cell == nil)
        {
            NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"ParseFeedCell" owner:self options:nil];
            cell = [nib objectAtIndex:0];
            cell.selectionStyle = UITableViewCellSelectionStyleNone;
    
        }
    
        NSDictionary *movie = [self.movies objectAtIndex:indexPath.row];
        NSString *strText = [movie objectForKey:@"message"];
    
        CGRect rect = cell.title.frame;
        rect.size.height = [self getHeightForText:strText];
        cell.title.frame = rect;
        cell.title.text = strText;
        cell.arrow.center = CGPointMake(cell.arrow.frame.origin.x, rect.origin.y + rect.size.height/2);
        cell.published.text = [movie objectForKey:@"published"];
        return cell;
    }
    
    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        NSDictionary *movie = [self.movies objectAtIndex:indexPath.row];
        NSString *strText = [movie objectForKey:@"message"];
    
        CGFloat cellHeight = cellHeightExceptText + [self getHeightForText:strText];
    
        return cellHeight;
    }
    
    - (CGFloat)getHeightForText:(NSString *)strText
    {
        CGSize constraintSize = CGSizeMake(cellTextWidth, MAXFLOAT);
        CGSize labelSize = [strText sizeWithFont:fontForCellText constrainedToSize:constraintSize lineBreakMode:NSLineBreakByWordWrapping];
        NSLog(@"labelSize.height = %f",labelSize.height);
        return labelSize.height;
    }
    

    Make sure that the Autolayout for your custom cell "ParseFeedCell" is off (Not Checked):

    Autolayout

    Also change the number of Lines of the text UILabel to 999999 so it's not limited to lines. I am sure that with a bit of research you can find a way to know how many lines the text is and assign the lines to the UILabel programatically.

    0 讨论(0)
提交回复
热议问题