Dynamic UITableViewCell Height with variable number of subviews - ios

I have a UITableViewCell that is populated dynamically with data retrieved from a remote source. It has a variable number of subviews based on the type of item being represented in the cell. I am dynamically calculating the size of the cell's contents by using a NSMutableAttributedString and the boundingRectWithSize: method. I take the returned values and calculate a combinedHeight variable that is stored in a NSMutableDictionary and associated with the indexPath of the cell. That all works fine, but when I attempt to use the values from the dictionary in the heightForRowAtIndexPath: method, it only uses the first set of visible cells, and after that everything is 0.
My question is how I can dynamically size the cell to contain all of the subviews. I am also adding a custom view to the cell's contentView that is smaller width than the cell so that I can achieve a unique style we are going for.
Here is my code:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (areFeedItemsLoaded && feedItems.count > 0 && indexPath.row < feedItems.count)
{
CGFloat height = [[_cellHeights objectForKey:[self keyForIndexPath:indexPath]] floatValue];
return MAX(90, height);
}
return 44;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell;
if (areFeedItemsLoaded)
{
if (feedItems.count == 0)
{
if (indexPath.row == 0)
{
cell = [EmptyTableViewCell getBlankCell:tableView];
}
else
{
EmptyTableViewCell *eCell = [EmptyTableViewCell getEmptyCell:tableView withHeaderText:#"No Recent Activity"];
[eCell setLinkText:#"Your team's activity on Hudl will appear here." withUrl:nil];
cell = eCell;
}
}
else if (indexPath.row < feedItems.count)
{
FeedItem *item = [feedItems objectAtIndex:indexPath.row];
cell = [self.tableView dequeueReusableCellWithIdentifier:FeedItemCellIdentifier forIndexPath:indexPath];
if (cell == nil)
{
cell = [[FeedItemTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:FeedItemCellIdentifier];
}
cell.clipsToBounds = YES;
cell.backgroundColor = [UIColor clearColor];
CGFloat combinedHeight = 8;
UIView *customContentView = [cell viewWithTag:customContentTagId];
if (customContentView == nil)
{
customContentView = [[UIView alloc] init];
customContentView.tag = customContentTagId;
customContentView.backgroundColor = [UIColor colorWithR:100 g:100 b:100 a:1];
[cell.contentView addSubview:customContentView];
}
customContentView.frame = CGRectMake(50, 0, 270, 70);
UIImageView *userImage = (UIImageView *)[cell viewWithTag:userImageTagId];
if (userImage == nil)
{
userImage = [[UIImageView alloc] init];
userImage.tag = userImageTagId;
[customContentView addSubview:userImage];
}
userImage.frame = CGRectMake(8, 8, 45, 45);
userImage.layer.cornerRadius = CGRectGetWidth(userImage.frame) / 2;
userImage.layer.masksToBounds = YES;
NSURL *imageUrl = item.imageSourceUrl;
[userImage setImageWithURL:imageUrl placeholderImage:[UIImage imageNamed:#"default-user.png"]];
CGFloat minX = CGRectGetMaxX(userImage.frame) + 8;
UILabel *titleLabel = (UILabel *)[cell viewWithTag:titleTagId];
if (titleLabel == nil)
{
titleLabel = [[UILabel alloc] init];
titleLabel.numberOfLines = 0;
titleLabel.textColor = [UIColor colorWithR:204 g:204 b:204 a:1];
titleLabel.font = [UIFont fontWithName:#"Helvetica" size:14];
titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
titleLabel.tag = titleTagId;
[customContentView addSubview:titleLabel];
}
NSString *title = [NSString stringWithFormat:#"%# %#", item.creatorName, item.title];
NSMutableAttributedString *titleText = [[NSMutableAttributedString alloc] initWithString:title];
[titleText addAttribute:NSForegroundColorAttributeName value:[UIColor colorWithR:204 g:204 b:204 a:1] range:NSMakeRange(0, title.length - 1)];
[titleText addAttribute:NSFontAttributeName value:[UIFont fontWithName:#"Helvetica-Bold" size:14] range:NSMakeRange(0, item.creatorName.length)];
[titleText addAttribute:NSFontAttributeName value:[UIFont fontWithName:#"Helvetica" size:15] range:NSMakeRange(item.creatorName.length + 1, title.length - item.creatorName.length - 1)];
titleLabel.attributedText = titleText;
CGFloat width = CGRectGetWidth(customContentView.frame) - (CGRectGetMaxX(userImage.frame) + 8) - 8;
width = MIN(width, 200);
CGSize titleSize = [titleText boundingRectWithSize:CGSizeMake(width, 10000) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading context:nil].size;
titleLabel.frame = CGRectMake(minX, CGRectGetMinY(userImage.frame), ceil(titleSize.width), ceil(titleSize.height));
combinedHeight += ceil(titleSize.height) + 8;
UIView *thumbnailsView = [cell viewWithTag:thumbnailTagId];
UILabel *descriptionLabel = (UILabel *)[cell viewWithTag:descriptionTagId];
if ([item.feedItemType intValue] == PlaylistFI || [item.feedItemType intValue] == PlaylistAndNotesFI)
{
if ([item.uris count] > 0)
{
if (thumbnailsView == nil)
{
thumbnailsView = [[UIView alloc] init];
thumbnailsView.tag = thumbnailTagId;
[customContentView addSubview:thumbnailsView];
}
else
{
for (UIView *view in thumbnailsView.subviews)
{
[view removeFromSuperview];
}
}
thumbnailsView.frame = CGRectMake(minX, CGRectGetMaxY(titleLabel.frame) + 8, width, 40);
combinedHeight += 48;
for (int i = 0; i < 3 && i < item.uris.count; i++)
{
NSURL *url = [item.uris objectAtIndex:i];
UIImageView *imageView = [[UIImageView alloc] init];
int x = i * 60 + i * 8;
imageView.frame = CGRectMake(x, 0, 60, 40);
[imageView setImageWithURL:url placeholderImage:[UIImage imageNamed:#"soft-dark-grad.png"]];
[thumbnailsView addSubview:imageView];
}
}
if (descriptionLabel == nil)
{
descriptionLabel = [[UILabel alloc] init];
descriptionLabel.tag = descriptionTagId;
descriptionLabel.font = [UIFont systemFontOfSize:14];
descriptionLabel.textColor = [UIColor colorWithR:204 g:204 b:204 a:1];
descriptionLabel.numberOfLines = 0;
descriptionLabel.lineBreakMode = NSLineBreakByWordWrapping;
[customContentView addSubview:descriptionLabel];
}
NSMutableAttributedString *descriptionText = [[NSMutableAttributedString alloc] initWithString:item.descriptionText];
[descriptionText addAttribute:NSFontAttributeName value:[UIFont fontWithName:#"Helvetica" size:14] range:NSMakeRange(0, item.descriptionText.length)];
descriptionLabel.attributedText = descriptionText;
CGSize descriptionSize = [descriptionText boundingRectWithSize:CGSizeMake(width, 10000) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading context:nil].size;
descriptionLabel.frame = CGRectMake(minX, CGRectGetMaxY(thumbnailsView.frame) + 8, ceil(descriptionSize.width), ceil(descriptionSize.height));
combinedHeight += ceil(descriptionSize.height) + 8;
}
else
{
if (thumbnailsView != nil)
{
[thumbnailsView removeFromSuperview];
}
if (descriptionLabel != nil)
{
[descriptionLabel removeFromSuperview];
}
}
UILabel *messageLabel = (UILabel *)[cell viewWithTag:messageTagId];
if ([item.feedItemType intValue] == MessageFI)
{
if (messageLabel == nil)
{
messageLabel = [[UILabel alloc] init];
messageLabel.tag = messageTagId;
messageLabel.font = [UIFont systemFontOfSize:14];
messageLabel.textColor = [UIColor colorWithR:204 g:204 b:204 a:1];
messageLabel.numberOfLines = 0;
messageLabel.lineBreakMode = NSLineBreakByWordWrapping;
[customContentView addSubview:messageLabel];
}
NSMutableAttributedString *messageText = [[NSMutableAttributedString alloc] initWithString:item.message];
[messageText addAttribute:NSFontAttributeName value:[UIFont fontWithName:#"Helvetica" size:14] range:NSMakeRange(0, item.message.length)];
CGSize messageSize = [messageText boundingRectWithSize:CGSizeMake(width, 10000) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading context:nil].size;
messageLabel.frame = CGRectMake(minX, CGRectGetMaxY(titleLabel.frame) + 8, ceil(messageSize.width), ceil(messageSize.height));
messageLabel.attributedText = messageText;
combinedHeight += ceil(messageSize.height) + 8;
}
else
{
if (messageLabel != nil)
{
[messageLabel removeFromSuperview];
}
}
if ([item.feedItemType intValue] == PlaylistFI || [item.feedItemType intValue] == PlaylistAndNotesFI ||
[item.feedItemType intValue] == ArticleFI)
{
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.selectionStyle = UITableViewCellSelectionStyleBlue;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
[_cellHeights setObject:#(combinedHeight) forKey:[self keyForIndexPath:indexPath]];
CGRect frame = customContentView.frame;
frame.size.height = MAX(70, combinedHeight);
customContentView.frame = frame;
}
else if (!requestFailed)
{
cell = [LoadingTableViewCell getLoadingCell:tableView];
}
else
{
cell = [ErrorTableViewCell getErrorCell:tableView];
}
}
else
{
cell = (indexPath.row == 0 || indexPath.row < feedItems.count) ? [EmptyTableViewCell getBlankCell:tableView] : [LoadingTableViewCell getLoadingCell:tableView];
}
return cell;
}
- (NSIndexPath *)keyForIndexPath:(NSIndexPath *)indexPath
{
if ([indexPath class] == [NSIndexPath class]) {
return indexPath;
}
return [NSIndexPath indexPathForRow:indexPath.row inSection:indexPath.section];
}

The issue with your code is the order in which the height is calculated. If you set a breakpoint in both methods you will see thattableView:heightForRowAtIndexPath: is actually called BEFORE tableView:cellForRowAtIndexPath:. This means that doing the calculations for the height when setting up the cell will not work (as the height will return 0 before it has been set).
Here is my suggestions:
Create a UITableViewCell subclass and move all of the initialization and setup logic you have piled intableView:cellForRowAtIndexPath: in that subclass.
once a cell is setup with whatever data properties may change its height, set the frame height of the cell internally because you will use it in the next step.
Then in order to calculate the height independently, use a method in the cell itself that looks something like this:
+ (CGFloat)heightForCellWithWithData:// use whatever parameters are usually set on a cell that might affect it's height
{
static dispatch_once_t once;
static CustomCellClass *sizingCell; // use your custom cell class here
dispatch_once(&once, ^{
sizingCell = [[self alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"sizingCell"];
});
// set cell data properties here
return sizingCell.frame.size.height;
}
Then to get the height you would just do:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (areFeedItemsLoaded && feedItems.count > 0 && indexPath.row < feedItems.count)
{
return [CustomCellClass heightForCellWithWithData:whateverData];
}
return 44;
}

Related

Overlapping Text in UITableViewHeaderFooterView

Here i mention the code what i wrote , In UITableViewHeaderFooterView while scrolling and second time that method is calling text was overlapping (How many time scrolling that much time text are adding), Here i mention the Screen shots : http://prntscr.com/9sgq7x
_imgViewUser.imageURL = [NSURL URLWithString:modelData.user_image_big];
_lblUserName.text = modelData.posted_by;
_lblTime.text = modelData.posted_time;
if ([modelData.commentArray count])
{
_imgViewUser.imageURL = [NSURL URLWithString:[[modelData.commentArray objectAtIndex:0] valueForKey:#"cmt_user_small"]];
NSString *nameStr = #"";
if ([GETVALUE(kUSERID) isEqualToString:[[modelData.commentArray objectAtIndex:0] valueForKey:#"cmt_userid"]]) {
nameStr = #"You";
}else {
nameStr = [[modelData.commentArray objectAtIndex:0] valueForKey:#"full_name"];
}
_lblUserName.text = nameStr;
_lblTime.text = [[modelData.commentArray objectAtIndex:0] valueForKey:#"cmt_post_time"];
}
NSString *OriginalFrontendText = [[modelData.commentArray objectAtIndex:0] valueForKey:#"cmt_text"];
UIFont *font = [UIFont fontWithName:#"Arial" size:13.0];
CGFloat descriptionHeight = [OriginalFrontendText boundingRectWithSize:CGSizeMake(180, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:#{NSFontAttributeName: font} context:nil].size.height;
[[self viewWithTag:tag]removeFromSuperview];
STTweetUserName *commentLbl;
if ([modelData.comments_count intValue] > 1) {
commentLbl = [[STTweetUserName alloc]initWithFrame:CGRectMake(0, 39, self.frame.size.width-10, descriptionHeight) withFont:9.0 attributeTextColor:[UIColor darkGrayColor] name:#"See More"];
commentLbl.text = [NSString stringWithFormat:#"%#See More",[[modelData.commentArray objectAtIndex:0] valueForKey:#"cmt_text"]];
}else
{
commentLbl = [[STTweetUserName alloc]initWithFrame:CGRectMake(0, 39, self.frame.size.width-10, descriptionHeight) withFont:9.0 attributeTextColor:[UIColor darkGrayColor] name:nil];
commentLbl.text = [[modelData.commentArray objectAtIndex:0] valueForKey:#"cmt_text"];
}
commentLbl.tag = tag;
if (commentLbl.tag == tag) {
[commentLbl removeFromSuperview];
}
[self addSubview:commentLbl];
commentLbl.detectionBlock = ^(STTweetHotUserName hotWord, NSString *string, NSString *protocol, NSRange range){
showAlert(string, nil, #"OK", nil);
//[self SeeMoreClicked];
};
self.frame = CGRectMake(self.contentView.frame.origin.x, self.contentView.frame.origin.y, self.contentView.frame.size.width, 150);
i am getting overlopping while scrolling
Use following code to make your footer view
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
UIView * v = [[UIView alloc] init];
v.frame = CGRectMake(0, 0, tableView.frame.size.width, 44);
UILabel * label = [[UILabel alloc] init];
label.frame = CGRectMake(20, 0, tableView.frame.size.width/2, 44);
label.text = #"Some text";
[v addSubview:label];
UIButton * btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.frame = CGRectMake(label.frame.size.width+label.frame.origin.x, 0, tableView.frame.size.width/2, 44);
[btn addTarget:self action:#selector(seeMore) forControlEvents:UIControlEventTouchUpInside];
btn.titleLabel.text = #"See more";
[v addSubview:btn];
return v;
}
Customise the above code however you want. This won't let your footer view overlap with text.
Get width of NSString text using
- (CGSize)getHeightForText:(NSString *)text havingWidth:(CGFloat)widthValue andFont:(UIFont *)font {
CGSize size = CGSizeZero;
if (text) {
CGRect frame = [text boundingRectWithSize:CGSizeMake(widthValue, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:#{ NSFontAttributeName:font } context:nil];
size = CGSizeMake(frame.size.width, frame.size.height+20.0f);
}
return size;
}

How to do pagination in uitableview without using Api?

I am working on one project where i want to use pagination in uitableview without using api. I am having a nsdictionary and i kept that dictionary in an nsarray ,now i want that in a list view type there are 10,20,30 numbers and which number i select that amount of rows will display in UI.
I have done this in uitableview
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *string1 = #"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:string1];
if(!cell)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:string1];
UILabel *label1 = (UILabel*)[cell.contentView viewWithTag:401];
CGFloat widthLabelHeader = CGRectGetWidth(orderTable.frame)/7;
if(!label1)
{
label1 = [[UILabel alloc]init];
label1.frame = CGRectMake(0, 0, widthLabelHeader, 45);
label1.layer.borderWidth = 0.5;
label1.font = [UIFont fontWithName:#"ChalkboardSE-Bold" size:14];
[cell.contentView addSubview:label1];
}
label1.textAlignment = NSTextAlignmentCenter;
UILabel *label2 = (UILabel*)[cell.contentView viewWithTag:402];
if(!label2)
{
label2 = [[UILabel alloc]init];
label2.frame = CGRectMake(CGRectGetMaxX(label1.frame), 0, widthLabelHeader, 45);
label2.layer.borderWidth = 0.5;
label2.font = [UIFont fontWithName:#"ChalkboardSE-Bold" size:14];
[cell.contentView addSubview:label2];
}
label2.textAlignment = NSTextAlignmentCenter;
UILabel *label3 = (UILabel*)[cell.contentView viewWithTag:403];
if(!label3)
{
label3 = [[UILabel alloc]init];
label3.frame = CGRectMake(CGRectGetMaxX(label2.frame), 0, widthLabelHeader, 45);
label3.layer.borderWidth = 0.5;
label3.font = [UIFont fontWithName:#"ChalkboardSE-Bold" size:14];
[cell.contentView addSubview:label3];
}
label3.textAlignment = NSTextAlignmentCenter;
UILabel *label4 = (UILabel*)[cell.contentView viewWithTag:404];
if(!label4)
{
label4 = [[UILabel alloc]init];
label4.frame = CGRectMake(CGRectGetMaxX(label3.frame), 0, widthLabelHeader, 45);
label4.layer.borderWidth = 0.5;
label4.font = [UIFont fontWithName:#"ChalkboardSE-Bold" size:14];
[cell.contentView addSubview:label4];
}
label4.textAlignment = NSTextAlignmentCenter;
UILabel *label5 = (UILabel*)[cell.contentView viewWithTag:405];
if(!label5)
{
label5 = [[UILabel alloc]init];
label5.frame = CGRectMake(CGRectGetMaxX(label4.frame), 0, widthLabelHeader, 45);
label5.layer.borderWidth = 0.5;
label5.font = [UIFont fontWithName:#"ChalkboardSE-Bold" size:14];
[cell.contentView addSubview:label5];
}
label5.textAlignment = NSTextAlignmentCenter;
UILabel *label6 = (UILabel*)[cell.contentView viewWithTag:406];
if(!label6)
{
label6 = [[UILabel alloc]init];
label6.frame = CGRectMake(CGRectGetMaxX(label5.frame), 0, widthLabelHeader, 45);
label6.layer.borderWidth = 0.5;
label6.font = [UIFont fontWithName:#"ChalkboardSE-Bold" size:14];
[cell.contentView addSubview:label6];
}
label6.textAlignment = NSTextAlignmentCenter;
UILabel *label7 = (UILabel*)[cell.contentView viewWithTag:407];
if(!label7)
{
label7 = [[UILabel alloc]init];
label7.frame = CGRectMake(CGRectGetMaxX(label6.frame), 0, widthLabelHeader, 45);
label7.layer.borderWidth = 0.5;
label7.font = [UIFont fontWithName:#"ChalkboardSE-Bold" size:14];
[cell.contentView addSubview:label7];
}
label7.textAlignment = NSTextAlignmentCenter;
dict1 = [array1 objectAtIndex:indexPath.row];
if( dict1)
{
label1.text = [dict1 objectForKey:#"key1" ];
label1.backgroundColor = [UIColor lightGrayColor];
label2.text = [dict1 objectForKey:#"key2" ];
label2.backgroundColor = [UIColor lightGrayColor];
label3.text = [dict1 objectForKey:#"key3" ];
label3.backgroundColor = [UIColor lightGrayColor];
label4.text = [dict1 objectForKey:#"key4" ];
label4.backgroundColor = [UIColor lightGrayColor];
label5.text = [dict1 objectForKey:#"key5" ];
label5.backgroundColor = [UIColor lightGrayColor];
label6.text = [dict1 objectForKey:#"key6" ];
label6.backgroundColor = [UIColor lightGrayColor];
label7.text = [dict1 objectForKey:#"key7" ];
label7.backgroundColor = [UIColor lightGrayColor];
}}
return cell;
}
Please Help me how to do this?
use this method is method and call Api and append in same array which used in table datasource
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
BOOL endOfTable = (scrollView.contentOffset.y >= ((showListingArray.count * 60) - scrollView.frame.size.height)); // Here 40 is row height
nextPage ++;
NSString *nextPageStr = [NSString stringWithFormat:#"%d", nextPage];
int totalpages = [[PaginnationDic objectForKey:#"totalPages"]intValue];
if ( endOfTable && !scrollView.dragging && !scrollView.decelerating)
{
if (nextPage >= totalpages) {
// NSLog(#"No More Page to load");
return;
}
objPCDetailTableView.tableFooterView = footerView;
NSDictionary *parametrs = #{#"movieid":_movieID, #"page":nextPageStr, #"cityId":[Utility getCityID]};
[self getMoviesDetailFromApi:parametrs];
[(UIActivityIndicatorView *)[footerView viewWithTag:10] startAnimating];
}
}
You should set this deleget method
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
with number you entered in text field and make this call [tableView reloadData]
or use this delegate methods
- (void)insertRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;
to insert just new rows into you tableView.

cellForRowAtIndexPath and sizeToFit reduces label width when scrolling

I've a custom cell with labels init in a UITableViewCell.
In my cellForRowAtIndexPath method after setting label content i call sizeToFit on the label to get the correct width and height, but when i scroll in my TableView, the label width reduce on each cells, every time i scroll.
Anyone for help ?
Thanks
My custom UITableViewCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
CGRect viewBounds = self.contentView.bounds;
// marge
CGFloat margin = 20;
self.excuse_date = [[UILabel alloc] initWithFrame:CGRectMake(5, 10, 300, 30)];
self.excuse_date.textColor = [UIColor blackColor];
self.excuse_date.font = [UIFont fontWithName:#"Arial" size:12.0f];
[self addSubview:self.excuse_date];
static CGFloat dateWidth = 130;
self.excuse_date.frame = CGRectMake(viewBounds.size.width-dateWidth-35, margin, dateWidth, 20);
CGRect dateFrame = self.excuse_date.frame;
self.excuse_date.textAlignment = NSTextAlignmentRight;
// setup excuse_auteur
self.excuse_auteur = [[UILabel alloc] init];
self.excuse_auteur.font = [UIFont fontWithName:#"Helvetica" size:13];
self.excuse_auteur.textColor = [UIColor darkGrayColor];
self.excuse_auteur.textAlignment = NSTextAlignmentLeft;
self.excuse_auteur.frame = CGRectMake(margin, margin, viewBounds.size.width-dateWidth-(margin*2), 20);
[self addSubview:self.excuse_auteur];
// setup excuse_texte
self.excuse_texte = [[UILabel alloc] initWithFrame:CGRectMake(20, CGRectGetMaxY(dateFrame)+margin/2, viewBounds.size.width - (margin*3), 200)];
self.excuse_texte.lineBreakMode = NSLineBreakByWordWrapping;
self.excuse_texte.numberOfLines = 0;
self.excuse_texte.font = [UIFont fontWithName:#"Helvetica" size:17];
self.excuse_texte.autoresizingMask = UIViewAutoresizingNone;
[self addSubview:self.excuse_texte];
CGRect textFrame = self.excuse_texte.frame;
// setup up image
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"up-small"]];
self.img = imageView;
[self addSubview:self.img];
imageView.frame = CGRectMake(20, CGRectGetMaxY(textFrame)+margin/2, 20, 20);
// setup up
self.up = [[UILabel alloc] initWithFrame:CGRectMake(45, CGRectGetMaxY(textFrame)+margin/2+2, viewBounds.size.width - margin*2, 20)];
self.up.font = [UIFont fontWithName:#"Helvetica" size:11];
self.up.textColor = [UIColor darkGrayColor];
self.up.textAlignment = NSTextAlignmentLeft;
[self addSubview:self.up];
}
return self;
}
My cellForRowAtIndexPath method
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
BBExcuse *excuse = [self.list objectAtIndex:indexPath.row];
static NSString *cellIdentifier = #"Cell";
// Similar to UITableViewCell, but
BBTableViewCell *cell = (BBTableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[BBTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
cell.excuse_texte.text = excuse.excuse_texte;
// #TODO problem here ?
[cell.excuse_texte sizeToFit];
cell.excuse_auteur.text = excuse.excuse_auteur;
cell.excuse_date.text = excuse.excuse_date;
cell.up.text = [NSString stringWithFormat:#"%#", excuse.up];
cell.img.frame = CGRectMake(20, CGRectGetMaxY(cell.excuse_texte.frame)+20/2, 20, 20);
cell.up.frame = CGRectMake(45, CGRectGetMaxY(cell.excuse_texte.frame)+20/2+2, 20, 20);
// setup up
return cell;
}
Ok solved by removing sizeToFit and specify height and width in cellForRowAtIndexPath
cell.excuse_texte.text = excuse.excuse_texte;
NSString *str = excuse.excuse_texte;
UILabel *gettingSizeLabel = [[UILabel alloc] init];
gettingSizeLabel.font = [UIFont systemFontOfSize:17];
gettingSizeLabel.text = str;
gettingSizeLabel.numberOfLines = 0;
gettingSizeLabel.lineBreakMode = NSLineBreakByWordWrapping;
CGSize maximumLabelSize = CGSizeMake(260.0f, 9999.0f);
CGSize theSize = [gettingSizeLabel sizeThatFits:maximumLabelSize];
// on resize sans sizetofit
cell.excuse_texte.frame = CGRectMake(cell.excuse_texte.frame.origin.x, cell.excuse_texte.frame.origin.y, cell.excuse_texte.frame.size.width, theSize.height);

Setting stretched UIImage as background for UILabel using resizableImageWithCapInsets

I have a chat application and I want to implement the chat bubbles as the background for the UILabel. This is what I'm trying to implement:
I tried using :
CGFloat scale = [[UIScreen mainScreen]scale];
//UIGraphicsBeginImageContext(newSize);
UIGraphicsBeginImageContextWithOptions(newSize, NO, scale);
[img drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
which results in the image being stretched equally like so:
So I tried using the resizableImageWithCapInsets and setting the image using colorWithPatternImage.
UIImage *newImage = [img resizableImageWithCapInsets:UIEdgeInsetsMake(0, 16, 0, 16)];
cell.answer.backgroundColor = [UIColor newImage];
But all it does is repeat the images as the background like so:
How do I stretch only the middle part of the image?
Or is it not possible using a UILabel?
For chating using the custom classes of PTSMessagingCell Here you can customize your images and other controls.
Catch the sample code PTSMessagingCell-master
try this.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UIImageView *balloonView;
UILabel *label;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
balloonView = [[UIImageView alloc] initWithFrame:CGRectZero];
balloonView.tag = 1;
label = [[UILabel alloc] initWithFrame:CGRectZero];
label.backgroundColor = [UIColor clearColor];
label.tag = 2;
label.numberOfLines = 0;
label.lineBreakMode = UILineBreakModeWordWrap;
label.font = [UIFont systemFontOfSize:14.0];
UIView *message = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, cell.frame.size.width, cell.frame.size.height)];
message.tag = 0;
[message addSubview:balloonView];
[message addSubview:label];
[cell.contentView addSubview:message];
[balloonView release];
[label release];
[message release];
}
else
{
balloonView = (UIImageView *)[[cell.contentView viewWithTag:0] viewWithTag:1];
label = (UILabel *)[[cell.contentView viewWithTag:0] viewWithTag:2];
}
NSString *text = [messages objectAtIndex:indexPath.row];
CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:14.0] constrainedToSize:CGSizeMake(240.0f, 480.0f) lineBreakMode:UILineBreakModeWordWrap];
UIImage *balloon;
if(indexPath.row % 2 == 0)
{
balloonView.frame = CGRectMake(320.0f - (size.width + 28.0f), 2.0f, size.width + 28.0f, size.height + 15.0f);
balloon = [[UIImage imageNamed:#"green.png"] stretchableImageWithLeftCapWidth:24 topCapHeight:15];
label.frame = CGRectMake(307.0f - (size.width + 5.0f), 8.0f, size.width + 5.0f, size.height);
}
else
{
balloonView.frame = CGRectMake(0.0, 2.0, size.width + 28, size.height + 15);
balloon = [[UIImage imageNamed:#"grey.png"] stretchableImageWithLeftCapWidth:24 topCapHeight:15];
label.frame = CGRectMake(16, 8, size.width + 5, size.height);
}
balloonView.image = balloon;
label.text = text;
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *body = [messages objectAtIndex:indexPath.row];
CGSize size = [body sizeWithFont:[UIFont systemFontOfSize:14.0] constrainedToSize:CGSizeMake(240.0, 480.0) lineBreakMode:UILineBreakModeWordWrap];
return size.height + 15;
}
i hope this code is useful for you.
variable newSize must be equal to size of label.
and replace this
cell.answer.backgroundColor = [UIColor newImage];
with
cell.answer.backgroundColor = [UIColor colorWithPatternImage:newImage];
Let me know if it works :)
Reference Link:

UItableviewcell glitch

So sometimes upon returning to my main menu for my game I am greeted by something quite extraordinary. As you can see from the picture I have replicated cells outside the UIView Table. Now at first I thought it was a graphics corruption that was based on memory issues, Then I discovered you could interact with them, they are valid cells...not ghost images and they respond to code, So I then did a little search and though that my table was stuck in editing mode or something so I call setediting:NO everywhere I could. And it haunts me still.
Does anyone even have the first idea what could be causing this? It does not happen all the time but it only ever seems to happen...IF it does when I am popping back to this screen from another view on top of it. I also can't replicate it consistently so it's hard to fix and know what is causing it.
Please keep in mind I might be doing something or not doing something I have not mentioned so don't forget to ask everything you may think relevant and I will be happy to inform you.
EDIT:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger) tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section
{
return [[[CurrentGamesInfo sharedCurrentGamesInfo] _currentGames] count];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
_indexPath = indexPath;
NSLog(#"%i",_indexPath.row);
[_indexPath retain];
[[CurrentGamesInfo sharedCurrentGamesInfo] SetCurrentGameWithIndex:[_indexPath row]];
UIView *tempView = [[[tableView cellForRowAtIndexPath:indexPath] contentView] viewWithTag:200];
if([[[(UIButton*)[tempView viewWithTag:CELL_BUTTONTEXT_ID] titleLabel] text] isEqualToString:#"Waiting"])
{
return;
}
if( ![[CurrentGamesInfo sharedCurrentGamesInfo] _selectedGame].isGameReady )
{
[_PopUp OptionsMessage:#"Game Not Ready" withTitle:#"Hold Your Horsies" hideBackButton:YES];
return;
}
NSString *gameID = [[[CurrentGamesInfo sharedCurrentGamesInfo] _selectedGame] GetGameID];
NSLog(#"%i",[[[CurrentGamesInfo sharedCurrentGamesInfo] _selectedGame] GetTurnNumber].intValue);
NSData *pngData = [NSData dataWithContentsOfFile:[AppDelegate applicationDocumentDirectory:gameID]];
UIImage *image = [UIImage imageWithData:pngData];
PhotoImage *photoImg = [[PhotoImage alloc]init];
[photoImg set_imageToSend:image];
[[[CurrentGamesInfo sharedCurrentGamesInfo] _selectedGame] SetImageToSend:photoImg];
[photoImg release];
UIImageView * imgView = (UIImageView*)[[[[tableView cellForRowAtIndexPath:indexPath] contentView]viewWithTag:300] viewWithTag:301];
[[[CurrentGamesInfo sharedCurrentGamesInfo]_selectedGame]setOpponentProfilePic:imgView.image];
[self TempCurrentGameFunction];
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewCellEditingStyleDelete;
}
WARNING: HEFTY FUNCTION INCOMING
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell;
GameInfo *gameThisRow = [[[CurrentGamesInfo sharedCurrentGamesInfo]_currentGames] objectAtIndex:indexPath.row];
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"MyIdentifier"] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleBlue;
NSLog(#"row : %i",indexPath.row);
NSLog(#"current game count : %i",[[[CurrentGamesInfo sharedCurrentGamesInfo] _currentGames]count]);
NSString *gameType = #"";
UIButton *gameStatusButton = [[UIButton alloc]initWithFrame:CGRectMake(100, -5, 90, 70)];
Boolean isYourTurn = [[gameThisRow GetPlayerRole] intValue] ? YES : NO;
NSString *gameStateString = #"Your Move";
[cell setUserInteractionEnabled:YES];
[cell setTag:ACTIVE_GAME_CELL];
if(!isYourTurn)
{
//_activeGameCount--;
gameStateString = #"Waiting";
[cell setUserInteractionEnabled:NO];
[cell setTag:INACTIVE_GAME_CELL];
}
[gameStatusButton setTitle:gameStateString forState:UIControlStateNormal];
[[gameStatusButton titleLabel] setFont:[UIFont fontWithName:#"Fredoka One" size:10]];
[gameStatusButton setTag:CELL_BUTTONTEXT_ID];
if( indexPath.row < [[[CurrentGamesInfo sharedCurrentGamesInfo] _currentGames]count])
{
switch ([gameThisRow gameType])
{
case 0:
gameType = #"Open Game";
[gameStatusButton setBackgroundImage:[UIImage imageNamed:#"buttonB_blue.png"] forState:UIControlStateNormal];
break;
case 1:
{
gameType = #"Challenge Game";
[gameStatusButton setBackgroundImage:[UIImage imageNamed:#"buttonB_orange.png"] forState:UIControlStateNormal];
}
break;
case 2:
{
gameType = #"Battle Game";
[gameStatusButton setBackgroundImage:[UIImage imageNamed:#"buttonB_pink.png"] forState:UIControlStateNormal];
}
break;
default:
break;
}
}
NSLog(#"%#",[[gameThisRow GetFaceBookData]objectForKey:#"name"]);
NSString *name = [[gameThisRow GetFaceBookData]objectForKey:#"name"];
UIView *labelView = [[UIView alloc] initWithFrame:CGRectMake(80, 10, 100, 50)];
[labelView setTag:200];
[labelView addSubview:gameStatusButton];
[gameStatusButton release];
[labelView setBackgroundColor:[UIColor clearColor]];
UILabel *labelName = [[UILabel alloc] initWithFrame:CGRectMake(0, 5, 100, 20)];
NSString *text = name;
NSArray *nameArray = [text componentsSeparatedByString:#" "];
NSString *nameWithInitials;
nameWithInitials = [NSString stringWithFormat:#"%#",[nameArray objectAtIndex:0]];
for( int i = 1; i < nameArray.count; ++i )
{
NSString *temp = [nameArray objectAtIndex:i];
nameWithInitials = [nameWithInitials stringByAppendingFormat:#" %C.",[temp characterAtIndex:0]];
}
text = nameWithInitials;
int maxSize = 20;
int minSize = 8;
UIFont *font = [UIFont fontWithName:#"Fredoka One"size:maxSize];
/* Time to calculate the needed font size.
This for loop starts at the largest font size, and decreases by two point sizes (i=i-2)
Until it either hits a size that will fit or hits the minimum size we want to allow (i > 10) */
for(int i = maxSize; i > minSize; i=i-2)
{
// Set the new font size.
font = [font fontWithSize:i];
// You can log the size you're trying: NSLog(#"Trying size: %u", i);
/* This step is important: We make a constraint box
using only the fixed WIDTH of the UILabel. The height will
be checked later. */
CGSize constraintSize = CGSizeMake([labelName frame].size.width, MAXFLOAT);
// This step checks how tall the label would be with the desired font.
CGSize labelSize = [text sizeWithFont:font constrainedToSize:constraintSize lineBreakMode:UILineBreakModeWordWrap];
/* Here is where you use the height requirement!
Set the value in the if statement to the height of your UILabel
If the label fits into your required height, it will break the loop
and use that font size. */
if(labelSize.height <= [labelName bounds].size.height)
break;
}
// You can see what size the function is using by outputting: NSLog(#"Best size is: %u", i);
// Set the UILabel's font to the newly adjusted font.
[labelName setFont:font];
// Put the text into the UILabel outlet variable.
[labelName setText:text];
[labelName setTextColor:[UIColor grayColor]];
[labelName setBackgroundColor:[UIColor clearColor]];
[labelName setTextAlignment:UITextAlignmentCenter];
[labelView addSubview:labelName];
[labelName release];
UILabel *labelSubtitle = [[UILabel alloc] initWithFrame:CGRectMake(0, 20, 100, 50)];
[labelSubtitle setText:gameType];
[labelSubtitle setFont:[UIFont fontWithName:#"Fredoka One" size:10]];
[labelSubtitle setTextColor:[UIColor grayColor]];
[labelSubtitle setBackgroundColor:[UIColor clearColor]];
[labelSubtitle setTextAlignment:UITextAlignmentCenter];
[labelView addSubview:labelSubtitle];
[labelSubtitle release];
[[cell contentView] addSubview:labelView];
NSString *path = [NSString stringWithFormat:#"http://graph.facebook.com/%#/picture?width=200&height=200",[[gameThisRow GetFaceBookData]objectForKey:#"id"] ];
UIImageView *pictureImage = [[UIImageView alloc] init];
[pictureImage setImageWithURL:[NSURL URLWithString:path] placeholderImage:[UIImage imageNamed:#"Icon-Small.png"]success:^(UIImage *image)
{
pictureImage.image = [image imageScaledToSize:CGSizeMake(100, 100)];
} failure:^(NSError *error)
{
[pictureImage setImage:[[UIImage imageNamed:#"Icon-Small.png" ]imageScaledToSize:CGSizeMake(50, 50)]];
NSLog(#"%#",[error localizedDescription]);
}];
NSLog(#"%#",[pictureImage image]);
pictureImage.layer.masksToBounds = YES;
[pictureImage setFrame:CGRectMake(pictureImage.frame.origin.x+20, 37 - 25, 50, 50)];
UIImageView *pictureFrameView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"profile_frame.png"]];
CGRect temp = pictureImage.frame;
//hand & hard coded, i feel so ashamed and sullied
temp.origin.x -= 12;
temp.origin.y -= 9;
temp.size.width = 70;
temp.size.height = 73;
[pictureFrameView setFrame:temp];
UIView *pictureView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 80, 80)];
[pictureView addSubview:pictureFrameView];
[pictureView addSubview:pictureImage];
[pictureImage setTag:301];
[pictureFrameView release];
[pictureImage release];
[[cell contentView] addSubview:pictureView];
[pictureView setTag:300];
[pictureView release];
//custom stuff start
UIImage *rowBackground;
//UIImage *selectionBackground;
NSInteger sectionRows = [tableView numberOfRowsInSection:[indexPath section]];
NSInteger row = [indexPath row];
if (row == 0 && row == sectionRows - 1)
{
rowBackground = [UIImage imageNamed:#"table_bottom.png"];
//selectionBackground = [UIImage imageNamed:#"topAndBottomRowSelected.png"];
}
else if (row == 0)
{
rowBackground = [UIImage imageNamed:#"table_top.png"];
//selectionBackground = [UIImage imageNamed:#"topRowSelected.png"];
}
else if (row == sectionRows - 1)
{
rowBackground = [UIImage imageNamed:#"table_bottom.png"];
//selectionBackground = [UIImage imageNamed:#"bottomRowSelected.png"];
}
else
{
rowBackground = [UIImage imageNamed:#"table_mid.png"];
//selectionBackground = [UIImage imageNamed:#"middleRowSelected.png"];
}
UIImageView *imageView = [[UIImageView alloc] initWithImage:rowBackground];
[cell setBackgroundView:imageView];
[imageView release];
//((UIImageView *)cell.selectedBackgroundView).image = selectionBackground;
//custom stuff end
__block CGRect newPos = inviteFriendsParentView.frame;
CGRect tempCurrentGameSubMenuFrame = currentGameSubMenu.frame;
tempCurrentGameSubMenuFrame.size.height = [friendsTable rowHeight] * [friendsTable numberOfRowsInSection:0] + 10;
currentGameSubMenu.frame = tempCurrentGameSubMenuFrame;
float bottomofFrameYPos = currentGameSubMenu.frame.size.height;
newPos.origin.y += bottomofFrameYPos;
return cell;
}

Resources