Adjust height UITableViewCell after cellForRowAtIndexPath - objective-c

I can't set the height of my UITableViewCell according to my constrains.
I have in each cell on my UITableView a UILabel where the height is not fixed and depends of the height of this UILabel.
I tried to set the frame on the cell after I update the label's content but nothing happens. Please find my code below:
//On my controller
- (UITableViewCell *)tableView:(UITableView *)tView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"CommentCell";
CommentCell *commentCell = [tView dequeueReusableCellWithIdentifier:CellIdentifier];
if (commentCell == nil) {
commentCell = [[CommentCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
Comment *comment;
if (commentsArray.count > indexPath.row) {
comment = [commentsArray objectAtIndex:indexPath.row];
}
[commentCell setComment:comment];
[commentCell setCommonFields];
currentCellheight = commentCell.contentLabel.frame.size.height + 40;
DDLogInfo(#"Current Cell Height: %f", currentCellheight);
return commentCell;
}
//On my custom Cell (CommentCell.m)
-(void)setCommonFields {
if (self.comment != nil) {
self.contentLabel.text = self.comment.content;
self.contentLabel.numberOfLines = 0;
CGSize maximumLabelSize = CGSizeMake(self.contentLabel.frame.size.width, FLT_MAX);
CGRect expectedLabelRect = [self.contentLabel.text boundingRectWithSize:maximumLabelSize options:NSStringDrawingUsesLineFragmentOrigin attributes:nil context:nil];
CGRect newFrame = self.contentLabel.frame;
newFrame.size.height = expectedLabelRect.size.height;
self.contentLabel.frame = newFrame;
}
}
I tried also to set the height thanks to the heightForRowAtIndexPath method but this method is called before cellForRowAtIndexPath where my label is updated.
I don't have much more idea to solve this problem.
Thank you in advance.

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"indexPath.row :%ld",(long)indexPath.row);
CGSize contsize={260.00f,3000.00f};
UIFont *font=[UIFont fontWithName:#"Helvetica-Bold" size:15.0];
NSString *strt11=#"hellllllooooooooooooooooooo hellllllooooooooooooooooooo hellllllooooooooooooooooooo";
CGSize fontSize=[strt11 sizeWithFont:font constrainedToSize:contsize lineBreakMode:NSLineBreakByWordWrapping];
NSLog(#"fontSize indexPath :%f",fontSize.height);
if (fontSize.height>22)
return fontSize.height+50.0f;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:#"reuse"];
if(cell==nil)
{
cell=[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"reuse"];
UILabel *lblcomment=[[UILabel alloc] initWithFrame:CGRectMake(55,23, 160,20)];
[lblcomment setBackgroundColor:[UIColor clearColor]];
[lblcomment setTag:72];
[lblcomment setTextColor:[UIColor grayColor]];
[lblcomment setNumberOfLines:0];
[lblcomment setFont:[UIFont fontWithName:#"Helvetica" size:15.0]];
[lblcomment setText:#"Its rude day on goin...Its rude day on goin...Its rude day on goin..."];
[cell addSubview:lblcomment];
}
UILabel *lblcomment=(UILabel *)[cell viewWithTag:72];
CGSize contsize={260.00f,3000.00f};
UIFont *font=[UIFont fontWithName:#"Helvetica-Bold" size:15.0];
NSString *strt11=#"hellllllooooooooooooooooooo hellllllooooooooooooooooooo hellllllooooooooooooooooooo";
CGSize fontSize=[strt11 sizeWithFont:font constrainedToSize:contsize lineBreakMode:NSLineBreakByWordWrapping];
float h=20;
NSLog(#"re %f",fontSize.height);
if (fontSize.height>22.0f){
h=fontSize.height+7.0;
NSLog(#"heigtaaaaa %f",h);
}
[lblcomment setFrame:CGRectMake(55,23,260,h)];
NSString *strDecodeComment=#""hellllllooooooooooooooooooo hellllllooooooooooooooooooo hellllllooooooooooooooooooo";
[lblcomment setText:strDecodeComment];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
return cell;
}

Thanks to Rohit's answer, please find my working code:
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
NSString *content=((Comment *)[commentsArray objectAtIndex:indexPath.row]).content;
CGSize maximumLabelSize = CGSizeMake(234.00f, FLT_MAX);
CGRect expectedLabelRect = [content boundingRectWithSize:maximumLabelSize options:NSStringDrawingUsesLineFragmentOrigin attributes:nil context:nil];
if (expectedLabelRect.size.height > 41) {
return expectedLabelRect.size.height + 81;
}
else
return 81;
}

Related

Dynamically change cell height programmatically

I've tried plenty of answers on SO but nothing really worked. I'm probably doing something wrong so I need someone to point out what I'm doing wrong..
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
NSLog(#"text : %#", self.cell.comment.text);
NSString *text = self.cell.comment.text;
CGFloat width = self.cell.frame.size.width;
UIFont *font = [UIFont fontWithName:#"HelveticaNeue" size:15];
NSAttributedString *attributedText =
[[NSAttributedString alloc] initWithString:text
attributes:#{NSFontAttributeName: font}];
CGRect rect = [attributedText boundingRectWithSize:(CGSize){width, CGFLOAT_MAX}
options:NSStringDrawingUsesLineFragmentOrigin
context:nil];
CGSize size = rect.size;
CGFloat height = ceilf(size.height);
return height;
}
I get "NSInvalidArgumentException" with reason "NSConcreteAttributedString initWithString:: nil value" because self.cell.comment.text isn't getting anything by the time I set cell height but it does come through just not when heightForRowAtIndexPath gets called.
Many people have commented on that answer that this method works just fine so I guess I'm missing something?
Edit
I'm setting self.cell.comment.text here -
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object{
static NSString *simpleTableIdentifier = #"cell";
self.cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (self.cell == nil) {
self.cell = [[CommentCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
// Configure the cell
self.cell.comment.text = [object objectForKey:#"comment"];
[self.cell.comment sizeToFit];
return self.cell;}
Your problem as you already comment is that function heightForRowAtIndexPath is called before cells are populated.
For every cell that become visible it first call
get height of this cell
populate cell
So you know that
a) your text is not yet populated on the cell
b) some other text might be inside, because apple use reusable cells, so UITableView can grab some cell (with different text) and try to resize it and then populate it.
In your case it will grab some other text, resize cell to its size and then populate it with some other text that is (probably) different size then previous text.
But inside cell populations you set text from some business logic (maybe array?), and you can get same text in this method.
if cell population you call
cell.comment.text = [self.someArray getObjectAtIndex:index.row];
you call this in your heightForRowAtIndexPath method.
NSString *text = [self.someArray getObjectAtIndex:index.row];
I see your edit just call :
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
NSLog(#"text : %#", self.cell.comment.text);
NSString *text = [object objectForKey:#"comment"];;
CGFloat width = self.cell.frame.size.width;
UIFont *font = [UIFont fontWithName:#"HelveticaNeue" size:15];
NSAttributedString *attributedText =
[[NSAttributedString alloc] initWithString:text
attributes:#{NSFontAttributeName: font}];
CGRect rect = [attributedText boundingRectWithSize:(CGSize){width, CGFLOAT_MAX}
options:NSStringDrawingUsesLineFragmentOrigin
context:nil];
CGSize size = rect.size;
CGFloat height = ceilf(size.height);
return height;
}
ADDITION :
Tel say you would like to have cells like this :
-------------------------
| bla bla bla |
------------------------
| second longer text |
| over more line |
------------------------
You need to have texts bla bla and "second longer text over more line" somewhere saved.
Let say you have array with size 2.
NSArray * myTextArray = #[#"bla bla", #"second longer text over more line"];
and when populating cells
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object{
static NSString *simpleTableIdentifier = #"cell";
self.cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (self.cell == nil) {
self.cell = [[CommentCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
// Configure the cell
self.cell.comment.text = [myTextArray objectAtIndex:indexPath.row];
[self.cell.comment sizeToFit];
return self.cell;
}
because heightForRowAtIndexPath is called before cellForRowAtIndexPath we need to check text from business (array) side and not visual.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
NSLog(#"text : %#", self.cell.comment.text); // -> this is null because cell is not populated yet.
NSString *text = [myTextArray objectAtIndex:indexPath.row]; -> this is same text as we will take when populating cell and is not random.
CGFloat width = self.cell.frame.size.width;
UIFont *font = [UIFont fontWithName:#"HelveticaNeue" size:15];
NSAttributedString *attributedText =
[[NSAttributedString alloc] initWithString:text
attributes:#{NSFontAttributeName: font}];
CGRect rect = [attributedText boundingRectWithSize:(CGSize){width, CGFLOAT_MAX}
options:NSStringDrawingUsesLineFragmentOrigin
context:nil];
CGSize size = rect.size;
CGFloat height = ceilf(size.height);
return height;
}
EXAMPLE :
#import "ViewController.h"
#interface ViewController ()
#property NSArray * myArray;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.myArray = #[#"Some short text",#"Some longer text that take some more space throw more lines",#"bfusdbfjdsfjs fj yfsdy fgsydu fyudsfy fyudsyu fdsy fuysdyuf ydsug fyu sdgyfgsuyff ius fhs fiusdhi ufdshu uifsd ufsdh hfiuds uifdsh fsduih ufdshu hfsd ifshui"];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 3;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
NSString *text = self.myArray[indexPath.row];
CGFloat width = 300;
UIFont *font = [UIFont fontWithName:#"HelveticaNeue" size:15];
NSAttributedString *attributedText =
[[NSAttributedString alloc] initWithString:text
attributes:#{NSFontAttributeName: font}];
CGRect rect = [attributedText boundingRectWithSize:(CGSize){width, CGFLOAT_MAX}
options:NSStringDrawingUsesLineFragmentOrigin
context:nil];
CGSize size = rect.size;
CGFloat height = ceilf(size.height);
return height;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *simpleTableIdentifier = #"cell";
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
// Configure the cell
cell.textLabel.text = self.myArray[indexPath.row];
cell.textLabel.numberOfLines = 0;
return cell;
}
this example works.
In heightForRowAtIndexPath:
For width, I think you can fix it, and don't need this line:
CGFloat width = self.cell.frame.size.width;
For the comment text
NSString *text = self.cell.comment.text;
Try this
NSString *text = [object objectForKey:#"comment"];
Spent all day trying to figure this out and finally found out that the solution was super simple, I just needed to know how to use Parse better.
Thanks to Marko, I've learned how UITableView really works and that's great but the solution to my problem was a bit different.
As everyone suggested my problem was assuming that heightForRowAtIndexPath would get called after all cells are populated but I did not need an array to save objects or make any change. Parse apparently saves all retrieved objects before heightForRowAtIndexPath gets called and they're all in self.objects.
self.cell.comment.text = [self.objects objectAtIndex:indexPath.row];
And as Andy passionately suggested, I'm now using Auto-size UITableViewCell.
In your PFQueryTableViewController
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
PFObject *object = [self.objects objectAtIndex:indexPath.row];
if (object) {
NSString *commentString = [self.objects[indexPath.row] objectForKey:#"comment"];
NSLog(#"commentString : %#",commentString);
CommentCell *cell = [[CommentCell alloc] init];
cell.textLabel.text = commentString;
[cell setNeedsLayout];
[cell layoutIfNeeded];
self.height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
self.height += 1;
}
return self.height;}
In your CustomCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
self.textLabel.lineBreakMode = NSLineBreakByWordWrapping;
self.textLabel.numberOfLines = 0;
self.textLabel.translatesAutoresizingMaskIntoConstraints = NO;
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-6-[bodyLabel]-6-|" options:0 metrics:nil views:#{ #"bodyLabel": self.textLabel }]];
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-6-[bodyLabel]-6-|" options:0 metrics:nil views:#{ #"bodyLabel": self.textLabel }]];
}
return self;}
- (void)layoutSubviews{
[super layoutSubviews];
[self.contentView setNeedsLayout];
[self.contentView layoutIfNeeded];
self.textLabel.preferredMaxLayoutWidth = CGRectGetWidth(self.textLabel.frame);}
This definitely works.

UICollectionView Header Issue, Headers doubling up

My header view in my UICollectionViews seem to double up when scrolling.
Header 1 scrolls up -> Header 2 is now in Header 1 location.
Scroll down and Header 1 now shows Header 1 and Header 2. Here's my code:
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
if ([kind isEqualToString:UICollectionElementKindSectionHeader]) {
UICollectionReusableView *reusableview = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:#"header" forIndexPath:indexPath];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(134, 2, 53, 16)];
label.font = [UIFont fontWithName:#"HelveticaNeue" size:10];
label.text = [NSString stringWithFormat:#"Hole %i", indexPath.section + 1];
[reusableview addSubview:label];
return reusableview;
}
return nil ;
}
I have no idea how to solve this.
You can try this
UILabel *_label;
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
if ([kind isEqualToString:UICollectionElementKindSectionHeader]) {
UICollectionReusableView *reusableview = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:#"header" forIndexPath:indexPath];
if(_label)
{
[_label removeFromSuperView];
}
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(134, 2, 53, 16)];
label.font = [UIFont fontWithName:#"HelveticaNeue" size:10];
label.text = [NSString stringWithFormat:#"Hole %i", indexPath.section + 1];
[reusableview addSubview:label];
_label=label;
return reusableview;
}
return nil ;
}
Try this sample
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView
viewForSupplementaryElementOfKind:(NSString *)kind
atIndexPath:(NSIndexPath *)indexPath {
// You can make header an ivar so we only ever create one
if (!header) {
header = [collectionView dequeueReusableSupplementaryViewOfKind:kind
withReuseIdentifier:#"ident"
forIndexPath:indexPath];
CGRect bounds;
bounds = [header bounds];
UIImageView *imageView;
imageView = [[UIImageView alloc] initWithFrame:bounds];
[imageView setImage:[UIImage imageNamed:#"header-background"]];
// Make sure the contentMode is set to scale proportionally
[imageView setContentMode:UIViewContentModeScaleAspectFill];
// Clip the parts of the image that are not in frame
[imageView setClipsToBounds:YES];
// Set the autoresizingMask to always be the same height as the header
[imageView setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
// Add the image to our header
[header addSubview:imageView];
}
return header;
}
[reusableView makeObjectsPerformSelector:#selector(removeFromSuperview)];

SDWebImage not showing randomly in UITableViewCell

Hello I have a script that downloads an image and dynamically sets the UITableView height after it finishes the download, but some images randomly do not show , the curious think is that when i change back and forth the tab the images suddenly appear . in the options argument i am passing SDWebImageRetryFailed.
Any idea would be more than welcome , thanks.
#interface NeobuggyFrontPageViewController()
{
UIImageView *adBanner;
NSArray *news ;
NSMutableData *imageData;
NSURLConnection *connection;
UIImage *neoImage;
NSString *category;
RSSItem *item;
FrontPageViewNewsCell *cell ;
CGRect newFrame;
__block CGRect descFrame;
float newWidth , newHeight;
__block float blockHeight;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
item = [news objectAtIndex:[indexPath row]];
cell = [tableView dequeueReusableCellWithIdentifier:#"FrontPageNewsCell"];
[[cell newsTitle] setText:[item title]];
[[cell newsVideo] setAlpha:0.0];
if ([item newsImageURL]){
descFrame = [[cell newsBody] frame];
[[cell newsImage] setImageWithURL:[item newsImageURL] placeholderImage:[UIImage imageNamed:#"placeholderImage.png"] options:SDWebImageRetryFailed completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType){
if (image) {
CGRect newsImageFrame = [[cell newsImage] frame];
float downImageWidth = image.size.width;
float downImageHeight = image.size.height;
float newsImageWidth = 304.00; //imageViewSize.size.width;
if (downImageWidth > newsImageWidth) {
float scaleFactor = newsImageWidth / downImageWidth;
newWidth = downImageWidth * scaleFactor;
newHeight = downImageHeight * scaleFactor;
} else {
newWidth = downImageWidth;
newHeight = downImageHeight;
}
newFrame = CGRectMake(newsImageFrame.origin.x, newsImageFrame.origin.y, newWidth, newHeight);
[[cell newsImage] setFrame:newFrame]; //asigno el nuevo frame a la imagen .
float newOriginY = newFrame.origin.y + newFrame.size.height + 10.00;
descFrame = CGRectMake(cell.newsBody.frame.origin.x,
newOriginY,
304.00,
cell.newsBody.frame.size.height);
blockHeight = newHeight;
}
NSLog(#"image %# cached ? %u", image ,cacheType);
if (error) {
NSLog(#"Error: %#",error);
}
}];
} else if([item newsVideoURL]) {
[[cell newsImage] setAlpha:0.0];
[[cell newsVideo] setAlpha:1.0];
[[cell newsVideo] loadRequest:[NSURLRequest requestWithURL:[item newsVideoURL]]];
float newOriginY = cell.newsVideo.frame.origin.y + cell.newsVideo.frame.size.height + 10.00;
descFrame = CGRectMake(cell.newsBody.frame.origin.x, newOriginY, 304, cell.newsBody.frame.size.height);
blockHeight = cell.newsVideo.frame.size.height;
}
[[cell newsImage] setNeedsDisplay];
NSString *desc = [[NSString alloc] initWithString:[item description]];
[[cell newsBody] setFrame:descFrame];
desc = [desc htmlToString:desc];
[[cell newsBody] setText:desc];
[[cell newsBody] setNumberOfLines:0];
[[cell newsBody] sizeToFit];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
return cell;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
cell = (FrontPageViewNewsCell *)[self tableView:tableView cellForRowAtIndexPath:indexPath];
CGSize descHeight = [[[cell newsBody] text] sizeWithFont:[[cell newsBody] font] constrainedToSize:cell.newsBody.frame.size lineBreakMode:[[cell newsBody] lineBreakMode]];
CGSize titleHeight = [[[cell newsTitle] text] sizeWithFont:[[cell newsTitle] font] constrainedToSize:cell.newsTitle.frame.size lineBreakMode:[[cell newsTitle] lineBreakMode]];
newHeight = cell.newsImage.frame.size.height;
if (blockHeight == 0) {
[tableView reloadData];
} else {
float ch = titleHeight.height + blockHeight + descHeight.height + 70;
[self setCellHeight:ch];
}
return _cellHeight;
}
Partially solved although solution less than ideal. Since i only needed to show 10 cells I prevented the reuse of the UITableViewCell
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
item = [news objectAtIndex:[indexPath row]];
NSString *identifier = [NSString stringWithFormat:#"Cell %d", indexPath.row];
UINib *nib = [UINib nibWithNibName:#"FrontPageViewNewsCell" bundle:nil];
[[self tableView] registerNib:nib forCellReuseIdentifier:identifier];
cell = [tableView dequeueReusableCellWithIdentifier:identifier];
// cell = [tableView dequeueReusableCellWithIdentifier:#"FrontPageNewsCell"];
still interested in finding a solution reusing cell
Thanks,

Changing the size of a UITableViewCell based on the size of a subview

How can I scale UITableViewCells based on the amount of content in them? In my cells I use three labels which represent a forum. The labels are named "alias", "date", and "comments". The third label, comments, can be any number of rows. Therefore, I need my cells to become dynamically size, depending on the amount of text in the "comments" label. Here is my code:
- (BOOL)textFieldShouldReturn:(UITextField *)pTextField
{
[self setLoadingState:YES];
[pTextField resignFirstResponder];
NSUserDefaults *userStorage = [NSUserDefaults standardUserDefaults];
NSString *alias = [self urlEncode:[userStorage objectForKey:#"alias"]];
NSString *email = [self urlEncode:[userStorage objectForKey:#"email"]];
NSString *who = [self getUniqueDeviceId];
NSString *comment = [self urlEncode:[pTextField text]];
comment = [comment stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
who = [who stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
if([self isBlank:comment])
{
[self setLoadingState:NO];
pTextField.text = #"";
return NO;
}
if([self isBlank:alias])
{
[self showMessagePopup:NSLocalizedString(#"MessageMustChooseAlias", nil)];
return NO;
}
[self.forumThreadDataProvider startSendPost:self.taskId : self.forumThreadId : alias : who : email : comment];
pTextField.text = #"";
return YES;
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.items count];
}
- (UITableViewCell *)tableView:(UITableView *)pTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"ForumthreadCell";
UITableViewCell *cell = [pTableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
Feedback *item = [self.items objectAtIndex:indexPath.row];
UILabel *aliasLabel = (UILabel *)[cell viewWithTag:1];
UILabel *commentLabel = (UILabel *)[cell viewWithTag:2];
UILabel *dateLabel = (UILabel *)[cell viewWithTag:3];
[aliasLabel setText:item.alias];
[commentLabel setText:item.comment];
[dateLabel setText:[self.dateFormatter stringFromDate:[NSDate dateWithTimeIntervalSince1970:(double)item.time]]];
commentLabel.numberOfLines = 0;
[commentLabel sizeToFit];
return cell;
}
Ive tryed already myself with the following code-example but it failed big-TIME:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell* cell = [tableView cellForRowAtIndexPath:indexPath];
if (cell) {
UILabel *commentLabel = (UILabel *)[cell viewWithTag:2];
return commentLabel.frame.size.height;
}
else
return 30;
}
Check this tutorial for how to set dynamically set cell height,
Basically you need to use methods like this to calculate the height of Laebl,
- (CGFloat)RAD_textHeightForSystemFontOfSize:(CGFloat)size {
//Calculate the expected size based on the font and linebreak mode of the label
CGFloat maxWidth = [UIScreen mainScreen].bounds.size.width - 50;
CGFloat maxHeight = 9999;
CGSize maximumLabelSize = CGSizeMake(maxWidth,maxHeight);
CGSize expectedLabelSize = [self sizeWithFont:[UIFont systemFontOfSize:size] constrainedToSize:maximumLabelSize lineBreakMode:UILineBreakModeWordWrap];
return expectedLabelSize.height;
}
Then you need to implement the heightForRowAtIndexPath method,
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *label = [self.aNote length] == 0 ? kDefaultNoteLabel : self.aNote;
CGFloat height = [label RAD_textHeightForSystemFontOfSize:kTextViewFontSize] + 20.0;
return height;
}

how to create dynamic TableCells for Tableview in ios

What I want to achieve is something like this. its kind of Facebook or twitter functionality where you have a tableview in which you have a Thread and the thread contains different number of articles. the number of articles varies in each row. So basically Its like i'm sending a post on facebook and people respond to that post and those posts are added under that particular Thread(I'm just concern about the How to display it every thing else is been taken care).here is the picture
I know how to create cell and all but I don't know how to set its size dynamically. any tutorial or any piece of advise to achieve this??
Any Help is appreciated..
thanks
Perhaps this will help you. I am sending you my code, I am using a Custom Cell , which having an Emial on first index, PhoneNumber on second index and Address on third index (in your case Article). I am dynamically changing the height of Address label in CellForRowAtIndexPath ,,, and also cell height in heightForRowAtIndexPath mehthod. Here is my code.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *identifier = #"FeedCell";
FeedDetailCell *cell = (FeedDetailCell*)[tableView dequeueReusableCellWithIdentifier:identifier];
if (cell==nil) {
cell = (FeedDetailCell*)[[[NSBundle mainBundle] loadNibNamed:#"FeedDetail" owner:nil options:nil] objectAtIndex:0];
}
[tableView setSeparatorColor:[UIColor grayColor]];
switch (indexPath.section) {
case 0:
if (indexPath.row == 0) {
cell.nameLabel.text = #"Telephone";
[cell.detailLabel setText:[_feedDictionary valueForKey:#"mobile"]];
}
else {
cell.nameLabel.text = #"Mobile";
[cell.detailLabel setText:[_feedDictionary valueForKey:#"iPhone"]];
}
break;
case 1:
cell.nameLabel.text = #"E-mail";
[cell.detailLabel setText:[_feedDictionary valueForKey:#"Email"]];
break;
case 2:
cell.nameLabel.text = #"address";
[cell.detailLabel setText:[_feedDictionary valueForKey:#"address"]];
CGSize size = [[_feedDictionary valueForKey:#"address"] sizeWithFont:[UIFont systemFontOfSize:14.0]
constrainedToSize:CGSizeMake(200.0, 400.0) lineBreakMode:UILineBreakModeWordWrap];
CGRect frm = cell.detailLabel.frame;
frm.size.height = size.height;
[cell.detailLabel setFrame:frm];
default:
break;
}
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == 2) {
NSString *address = [_feedDictionary valueForKey:#"address"];
CGSize recommendedSize = [address sizeWithFont:[UIFont systemFontOfSize:14] constrainedToSize:CGSizeMake(320, INT_MAX)];
return 44 + recommendedSize.height;
}
else {
return 44;
}
}
You can use this for dynamic cell height
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath;
you can use switch cases and check indexPath.row and indexPath.section to return the required height
take a custom UITableViewCell ,
in .h file
#interface PartnerCell : UITableViewCell {
UILabel *user_name,*lbldate,*lbldesc;
LoadImage *img_trade;
UIImageView *partnerimage;
}
#property (nonatomic, strong) UILabel *user_name,*lbldate,*lbldesc;
#property (nonatomic, strong) LoadImage *img_trade;
#property (nonatomic, strong) UIImageView *partnerimage;
#end
in .m file,
#import "PartnerCell.h"
#implementation PartnerCell
#synthesize user_name,lbldate,lbldesc;
#synthesize img_trade,partnerimage;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
[self setSelectionStyle:UITableViewCellSelectionStyleNone];
user_name = [[UILabel alloc] initWithFrame:CGRectMake(75,8,200,15)];
[user_name setBackgroundColor:[UIColor clearColor]];
user_name.font = [UIFont fontWithName:#"Arial-BoldMT" size:15];
[user_name setTextColor:[UIColor colorWithRed:70/255.00f green:70/255.00f blue:70/255.00f alpha:1.0]];
[self addSubview:user_name];
lbldate = [[UILabel alloc] initWithFrame:CGRectMake(75,28,200,15)];
[lbldate setBackgroundColor:[UIColor clearColor]];
lbldate.font = [UIFont fontWithName:#"Arial" size:14];
[lbldate setTextColor:[UIColor darkGrayColor]];
[self addSubview:lbldate];
lbldesc = [[UILabel alloc] initWithFrame:CGRectMake(75,45,170,35)];
[lbldesc setBackgroundColor:[UIColor clearColor]];
lbldesc.font = [UIFont fontWithName:#"Arial" size:13];
lbldesc.numberOfLines = 2;
[lbldesc setTextColor:[UIColor darkGrayColor]];
[self addSubview:lbldesc];
img_trade = [[LoadImage alloc] initWithFrame:CGRectMake(3, 5, 54, 55)];
img_trade.userInteractionEnabled = YES;
[self addSubview:img_trade];
}
return self;
}
in main table view class write this code,
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifier = [NSString stringWithFormat:#"%#",[[Partarray objectAtIndex:indexPath.row-1] valueForKey:#"part_id"]];
cell = (PartnerCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell=nil;
if (cell == nil)
{
cell = [[PartnerCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
//cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:[Partarray objectAtIndex:indexPath.row]] autorelease];
cell.selectionStyle= UITableViewCellSelectionStyleGray;
cell.backgroundColor = [UIColor clearColor];
cell.user_name.frame=CGRectMake(75,8,340,15);
cell.lbldate.frame=CGRectMake(75,28,340,15);
cell.lbldesc.frame=CGRectMake(75,45,340,35);
cell.user_name.text = #"user name";
cell.lbldate.text = #"date";
cell.lbldesc.text = #"description";
}
return cell;
}
take condition and add number of objects based on that condition.