I am having an app in which I have a Tableview and on that tableview\'s each row I am dynamically creating a custom tableview cell.
Below is the cod
Here we go:
UITableViewCell
subclass for all the cells in your view (such as FlowViewAbstractTableViewCell
)+ (CGFloat)sizeForCellWithComment:(Comment *)comment
. What you're doing is setting up a method to pass a model object into that each table view cell subclass can implement.FlowViewAbstractTableViewCell
. In your case, it looks like you could have ones called FlowViewTextCommentTableViewCell
and FlowViewPictureCommentTableViewCell
.+sizeForCellWithComment:
method. This will allow you to return a variable size based on the object you pass into the method.- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
for your UITableViewDelegate
. In this method you are going to figure out which cell class you want to use and which object to pass into that size method. For example:- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
Comment *commentForCell = [self.comments objectAtIndex:indexPath.row];
return [CommentTableViewCell sizeForComment:commentForCell].height;
}
This will allow you to return a variable cell height based on the object. I use variably sized table view cells all the time & love this pattern because I think it does the best job of hiding the implementation and following MVC.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *str = [arrComments objectAtIndex:indexPath.row];
UIFont *font = [UIFont fontWithName:@"Helvetica" size:14];
CGRect new = [str boundingRectWithSize:CGSizeMake(280, 999) options:NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName: font} context:nil];
CGSize size= new.size;
NSLog(@"%f",size.height);
if (size.height<20)
{
size.height=20;
//m= size.height;
}
NSLog(@"%f",size.height);
return size.height + 30;
}
Try this
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return [self.tableName.dataSource tableView:self.tableName cellForRowAtIndexPath:indexPath].contentView.frame.size.height;
}
And in your cellForRowAtIndexPath delegate if you are using label then first set number of lines to label as 0, then set label text and then add sizeTofit property of it. Like this
[cell.yourLabelName setNumberOfLines:0];
cell.yourLabelName.text = @"Your long or short text";
[cell.yourLabelName sizeToFit];
This will expand your label height as per the text in it.
After that you can set the size of your cell contentView like this.
cell.contentView.frame = CGRectMake(cell.contentView.frame.origin.x, cell.contentView.frame.origin.y, cell.contentView.frame.size.width,"Height of label" + cell.contentView.frame.size.height);
You can calculate the Height of Label using:
- (CGRect)heightOfLabel:(UILabel*)resizableLable
{
CGSize constrainedSize = CGSizeMake(resizableLable.frame.size.width , 9999);
NSDictionary *attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
[UIFont fontWithName:@"HelveticaNeue" size:11.0], NSFontAttributeName,
nil];
NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:@"textToShow" attributes:attributesDictionary];
CGRect requiredHeight = [string boundingRectWithSize:constrainedSize options:NSStringDrawingUsesLineFragmentOrigin context:nil
];
if (requiredHeight.size.width > self.resizableLable.frame.size.width) {
requiredHeight = CGRectMake(0,0, self.resizableLable.frame.size.width, requiredHeight.size.height);
}
return requiredHeight;
}
Call this method from TableView delegate method:
- (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
return [self heightOfLabel:cell.textLabel];
}
This video gives a great tutorial on using autolayout to dynamically size UITableViewCells. When I needed to do this for an application I ended up subclassing UITableViewCell and setting my constraints programmatically, and it worked like a charm.
You can use the following code to adjust the height dynamically. First you need to determine the height of the label and then adjust the height of the cell accordingly. I have been using this code in my chat application and works fine.
First, create the label and image view in cellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
/// Set Text Label
UILabel *lbl_myText = [[UILabel alloc]initWithFrame:CGRectZero];
[lbl_myText setLineBreakMode:NSLineBreakByWordWrapping];
lbl_myText.minimumScaleFactor = FONT_SIZE;
[lbl_myText setNumberOfLines:0];
lbl_myText.textAlignment = NSTextAlignmentLeft;
[lbl_myText setFont:[UIFont systemFontOfSize:FONT_SIZE]];
NSString *text = [arr_text objectAtIndex:indexPath.row];
CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE]];
// Checks if text is multi-line
if (size.width > lbl_myText.bounds.size.width)
{
CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 20000.0f); //// Here Width = Width you want to define for the label in its frame. The height of the label will be adjusted according to this.
//CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:NSLineBreakByWordWrapping];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;
CGRect textRect = [text boundingRectWithSize:constraint
options:NSStringDrawingUsesLineFragmentOrigin
attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:FONT_SIZE], NSParagraphStyleAttributeName: paragraphStyle.copy}
context:nil];
CGSize size = textRect.size;
[lbl_myText setText:text];
[lbl_myText setFrame:CGRectMake(cell.imgv_someoneImage.frame.size.width+8, CELL_CONTENT_MARGIN, CELL_CONTENT_WIDTH - cell.imgv_someoneImage.frame.size.width -(CELL_CONTENT_MARGIN * 2), MAX(size.height, 44.0f))];
}
else
{
lbl_myText.frame = CGRectMake(10, 0, cell.frame.size.width - cell.imgv_someoneImage.frame.size.width - 18,18);
lbl_myText.textAlignment = NSTextAlignmentLeft;
[lbl_myText setText:text];
}
//lbl_myText.backgroundColor = [UIColor greenColor];
[cell.contentView addSubview:lbl_myText];
/// Set Date Label
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"yyyy-MM-dd HH:mm"];
NSString *stringFromDate = [formatter stringFromDate:[arr_date objectAtIndex:indexPath.row]];
UILabel *lbl_myDate = [[UILabel alloc]initWithFrame:CGRectMake(cell.imgv_someoneImage.frame.size.width+8, lbl_myText.frame.size.height+10, cell.frame.size.width - cell.imgv_someoneImage.frame.size.width - 10 ,18)];
lbl_myDate.text = stringFromDate;
lbl_myDate.font = [UIFont fontWithName:@"Helvetica Neue" size:13.0];
lbl_myDate.textColor = [UIColor lightGrayColor];
lbl_myDate.textAlignment = NSTextAlignmentLeft;
[cell.contentView addSubview:lbl_myDate];
/// Set User Image
UIImageView *imgv_myImage = [[UIImageView alloc]initWithFrame:CGRectMake(0, lbl_myText.frame.origin.y, 63, 63)];
imgv_myImage.image = selectedUserUploadedImage;
[cell.contentView addSubview:imgv_myImage];
}
Here define some of the constants:
#define FONT_SIZE 15.0f
#define CELL_CONTENT_WIDTH 320.0f /// change this according to your screen size. This is just an example
#define CELL_CONTENT_MARGIN 10.0f
Now, after creating the labels, you will have to determine the height of the cell in heightForRowAtIndexPath:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellText = [arr_text objectAtIndex:indexPath.row];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"yyyy-MM-dd HH:mm"];
NSString *cellDate = [formatter stringFromDate:[arr_date objectAtIndex:indexPath.row]];
// NSString *text = [items objectAtIndex:[indexPath row]];
CGSize constraint = CGSizeMake(CELL_CONTENT_WIDTH - (CELL_CONTENT_MARGIN * 2), 20000.0f);
//CGSize labelsize = [cellText sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:NSLineBreakByWordWrapping];
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;
////for message label
CGRect textRect = [cellText boundingRectWithSize:constraint
options:NSStringDrawingUsesLineFragmentOrigin
attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:FONT_SIZE], NSParagraphStyleAttributeName: paragraphStyle.copy}
context:nil];
CGSize labelsize = textRect.size;
////for date label
CGRect datetextRect = [cellDate boundingRectWithSize:constraint
options:NSStringDrawingUsesLineFragmentOrigin
attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:FONT_SIZE], NSParagraphStyleAttributeName: paragraphStyle.copy}
context:nil];
CGSize datelabelsize = datetextRect.size;
//CGSize datelabelsize = [cellDate sizeWithFont:[UIFont systemFontOfSize:FONT_SIZE] constrainedToSize:constraint lineBreakMode:NSLineBreakByWordWrapping];
///combine the height
CGFloat height = MAX(labelsize.height + datelabelsize.height, 64.0f);
if(height == 64.0f)
{
return 74; /// label is of one line, return original/ static height of the cell
}
else
{
return height + 10; /// label is of multi-line, return calculated height of the cell + some buffer height
}
}