Center Align text in UITableViewCell problem - objective-c

I'm kinda new to Objective-C and iPhone development and I've come across a problem when trying to center the text in a table cell. I've searched google but the solutions are for an old SDK bug that has been fixed and these don't work for me.
Some code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
cell.textLabel.text = #"Please center me";
cell.textLabel.textAlignment = UITextAlignmentCenter;
return cell;
}
The above doesn't center the text.
I have also tried the willDisplayCell method:
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
cell.textLabel.textAlignment = UITextAlignmentCenter;
}
and I've tried some of the old posted solutions:
UILabel* label = [[[cell contentView] subviews] objectAtIndex:0];
label.textAlignment = UITextAlignmentCenter;
return cell;
None of these have any effect on the text alignment. I have run out of idea's any help would be most appreciated.
Cheers in advance.

Don't know if it helps your specific problem, however UITextAlignmentCenter does work if you use initWithStyle:UITableViewCellStyleDefault

It doesn't work because the textLabel is only as wide as it needs to be for any given text. (UITableViewCell moves the labels around as it sees fit when set to the UITableViewCellStyleSubtitle style)
You can override layoutSubviews to make sure the labels always fill the cell's entire width.
- (void) layoutSubviews
{
[super layoutSubviews];
self.textLabel.frame = CGRectMake(0, self.textLabel.frame.origin.y, self.frame.size.width, self.textLabel.frame.size.height);
self.detailTextLabel.frame = CGRectMake(0, self.detailTextLabel.frame.origin.y, self.frame.size.width, self.detailTextLabel.frame.size.height);
}
Be sure to keep the height/y-position the same, because as long as the detailTextLabel's text is empty textLabel will be vertically centered.

Use this code:
cell.textLabel.textAlignment = NSTextAlignmentCenter;
Above code will work.
Dont use UITextAlignmentCenter, it is deprecated.

This hack will center the text when using UITableViewCellStyleSubtitle.
Load both text labels with your strings, then do this before returning the cell. It might be simpler to just add your own UILabels to each cell, but I was determined to find another way...
// UITableViewCellStyleSubtitle measured font sizes: 18 bold, 14 normal
UIFont *font = [UIFont boldSystemFontOfSize:18]; // measured after the cell is rendered
CGSize size = [cell.textLabel.text sizeWithFont:font];
CGSize spaceSize = [#" " sizeWithFont:font];
float excess_width = ( cell.frame.size.width - 16 ) - size.width;
if ( cell.textLabel.text && spaceSize.width > 0 && excess_width > 0 ) { // sanity
int spaces_needed = (excess_width/2.0)/spaceSize.width;
NSString *pad = [#"" stringByPaddingToLength:spaces_needed withString:#" " startingAtIndex:0];
cell.textLabel.text = [pad stringByAppendingString:cell.textLabel.text]; // center the text
}
font = [UIFont systemFontOfSize:14]; // detail, measured
size = [cell.detailTextLabel.text sizeWithFont:font];
spaceSize = [#" " sizeWithFont:font];
excess_width = ( cell.frame.size.width - 16 ) - size.width;
if ( cell.detailTextLabel.text && spaceSize.width > 0 && excess_width > 0 ) { // sanity
int spaces_needed = (excess_width/2.0)/spaceSize.width;
NSString *pad = [#"" stringByPaddingToLength:spaces_needed withString:#" " startingAtIndex:0];
cell.detailTextLabel.text = [pad stringByAppendingString:cell.detailTextLabel.text]; // center the text
}

In CustomTableViewCell.m:
- (void)layoutSubviews {
[super layoutSubviews];
self.textLabel.frame = CGRectMake(0, self.textLabel.frame.origin.y, self.contentView.frame.size.width, self.textLabel.frame.size.height);
}
In the method table:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
CustomTableViewCell *cell = (CustomTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[CustomTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
cell.textLabel.text = #"Title";
cell.textLabel.textAlignment = UITextAlignmentCenter;
return cell;
}
If needed, the same thing can be repeated for self.detailTextLabel

In same situation I created custom UITableViewCell with a custom label:
MCCenterTextCell.h file:
#import <UIKit/UIKit.h>
#interface MCCenterTextCell : UITableViewCell
#property (nonatomic, strong) UILabel *mainLabel;
#end
MCCenterTextCell.m file:
#import "MCCenterTextCell.h"
#interface MCCenterTextCell()
#end
#implementation MCCenterTextCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
self.accessoryType = UITableViewCellAccessoryNone;
self.selectionStyle = UITableViewCellSelectionStyleGray;
_mainLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 5, 320, 30)];
_mainLabel.font = BOLD_FONT(13);
_mainLabel.textAlignment = NSTextAlignmentCenter;
[self.contentView addSubview:_mainLabel];
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
#end

You could use code to center text
cell.indentationLevel = 1;
cell.indentationWidth = [UIScreen mainScreen].bounds.size.width/2-10;

In case one wish to align the text to the right, I've had success adapting the solution described here.
cell.transform = CGAffineTransformMakeScale(-1.0, 1.0);
cell.textLabel.transform = CGAffineTransformMakeScale(-1.0, 1.0);
cell.detailTextLabel.transform = CGAffineTransformMakeScale(-1.0, 1.0);

Here is what works for me...
NSString *text = #"some text";
CGSize size = [text sizeWithAttributes:#{NSFontAttributeName:SOME_UIFONT}];
[cell setIndentationLevel:1];
[cell setIndentationWidth:(tableView.frame.size.width - size.width)/2.0f];
cell.textLabel.font = SOME_UIFONT;
[cell.textLabel setText:text];

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.

UITableView willDisplayCell Acting Weird, Cells borders adjusted only after reuse

I am trying to have 10 pixels gap between cells and the edge of the screen. I implemented willDisplayCell:forRowAtIndexPath and also the heightForCell since am using two different prototype cells in my table view.
The problem am having is really weird. The cells are only adjusted when i pull the list up, am guessing only when they are reused! check the images please.![enter image description here][1]
This is the initial screen:
https://www.dropbox.com/s/epl2n8a5zohhdmz/Edited.screenShot.01.png?dl=0
This is the screen after the table view is scrolled:
https://www.dropbox.com/s/c81dx9wmaq0mgr5/Edited.screenShot.02.png?dl=0
Here is my code:
- (void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
cell.layer.borderWidth = 5.0f;
cell.layer.borderColor = [UIColor grayColor].CGColor;
cell.layer.cornerRadius = 7.0;
cell.layer.bounds = CGRectMake(0, 0, 260, cell.bounds.size.height - 10);
cell.backgroundColor = [UIColor colorWithRed:207/255.0 green:207/255.0 blue:207/255.0 alpha:1.0];
CGRect cellFrame = CGRectMake(20, cell.frame.origin.y, 280, cell.frame.size.height);
cell.frame = cellFrame;
cell.contentView.frame = cellFrame;
[cell.contentView alignmentRectForFrame:cellFrame];
[cell setNeedsLayout];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([[self.namesList[indexPath.row] objectForKey:#"Relation"] length] == 0) {
return 69.0;
} else {
return 89.0;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSMutableString *details = [[NSMutableString alloc] init];
UITableViewCell *cell = [[UITableViewCell alloc] init];
UILabel *nameLabel;
UILabel *relationLabel;
UILabel *ageLabel;
UILabel *dayLabel;
UILabel *dateLabel;
Helper *dateConvert = [[Helper alloc] init];
if ([[self.namesList[indexPath.row] objectForKey:#"Relation"] length] == 0) {
cell = [tableView dequeueReusableCellWithIdentifier:#"Cell2" forIndexPath:indexPath];
} else {
cell = [tableView dequeueReusableCellWithIdentifier:#"Cell3" forIndexPath:indexPath];
relationLabel = (UILabel *) [cell viewWithTag:2];
relationLabel.text = [self.namesList[indexPath.row] objectForKey:#"Relation"];
}
nameLabel = (UILabel *) [cell viewWithTag:1];
ageLabel = (UILabel *) [cell viewWithTag:3];
dayLabel = (UILabel *) [cell viewWithTag:4];
dateLabel = (UILabel *) [cell viewWithTag:5];
[details appendString:[self.namesList[indexPath.row] objectForKey:#"Age"]];
[details appendString:#")"];
ageLabel.text = details;
dayLabel.text = [dateConvert getWeekDay:[self.namesList[indexPath.row] objectForKey:#"Date"]];
dateLabel.text = [self.namesList[indexPath.row] objectForKey:#"Date"];
return cell;
}
I have spent days trying to find the problem :( every help is greatly appreciated :)
Why not make your life easier and design the cell in Interface Builder to have the 10 px space already. You can add a UIView, make that 10 px from top, left, right and bottom, then put you UI elements inside of that. I would suggest subclassing your UITableViewCells and have code in those to display your data and set the borders.

Resizing UITextView and UITableViewCell

I have new to objective C programming and i am currently trying to develop an iOS app. I am loading comment from the server onto the UITextView in the UITableViewCell.
This is the code that is used to load data into the UITextview.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// set the location to read the sample data
static NSString *CellIdentifier = #"CommentCell";
CommentCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[CommentCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
PostModel *posts;
CommentModel *comments;
if (contentTitle == nil) {
posts = _feed.posts[articleIndexPath.section];
comments = posts.comments[indexPath.section];
}
else {
posts = _feed.posts[searchResult];
comments = posts.comments[indexPath.section];
}
NSString *content = comments.content;
content = [content stringByReplacingOccurrencesOfString:#"<p>" withString:#""];
content = [content stringByReplacingOccurrencesOfString:#"</p>" withString:#""];
cell.usernameLabel.text = comments.name;
[cell.commentTextView setScrollEnabled:YES];
cell.commentTextView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
cell.commentTextView.text = content;
[cell.commentTextView sizeToFit];
[cell.commentTextView setScrollEnabled:NO];
[cell.commentTextView setTextColor:[UIColor whiteColor]];
[cell.usernameLabel setTextColor:[UIColor whiteColor]];
// make the borders of the cell round
[cell.layer setCornerRadius:7.0f];
[cell.layer setMasksToBounds:YES];
cell.contentView.layer.borderColor = [[UIColor colorWithRed:51/255 green:56/255 blue:67/255 alpha:1] CGColor];
//make the borders of the image round
[cell.userImage.layer setMasksToBounds:YES];
[cell.userImage.layer setCornerRadius:7.0f];
return cell;
}
This is the code that i used to resize the UITableViewCell and UITextView
- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"CommentCell";
CommentCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
PostModel *posts;
CommentModel *comments;
if (contentTitle == nil) {
posts = _feed.posts[articleIndexPath.section];
comments = posts.comments[indexPath.section];
}
else {
posts = _feed.posts[searchResult];
comments = posts.comments[indexPath.section];
};
if (cell.commentTextView.textContainer.size.height >= 40) {
float height = [self heightForTextView:cell.commentTextView containingString:comments.content];
return height;
}
else {
return 79;
}
}
This is the method that i used to detect the height of the text
- (CGFloat)heightForTextView:(UITextView *)textView containingString:(NSString *)string {
float horizontalPadding = 8;
float verticalPadding = 16;
float widthOfTextView = textView.textContainer.size.width - horizontalPadding;
float height = [string sizeWithFont:textView.font constrainedToSize:CGSizeMake(widthOfTextView, 999999.0f) lineBreakMode:NSLineBreakByWordWrapping].height + verticalPadding;
return height;
}
- (CGSize)text: (NSString *)text sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size {
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"7")) {
NSDictionary *attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:font, NSFontAttributeName, nil];
CGRect frame = [text boundingRectWithSize:size options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading) attributes:attributesDictionary context:nil];
return frame.size;
}
else {
return [text sizeWithFont:font constrainedToSize:size];
}
}
It load fine when i run it initially but when i scroll down and back up, the UITextView became a vertical single line column.
Any help would be greatly appreciated!
I think the this might be the cause:
- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
You are using a dequeued cell's text view to determine the height of the cell. However the dequeued cell may not having any text data (or different text) in it, plus the commentView is UIViewAutoresizingFlexibleWidth, the width calculated by
float widthOfTextView = textView.textContainer.size.width - horizontalPadding;
may be very small under the scenario of scroll down and backup.

Changing height dynamic for Table Rows , CustomCell and Layout

There is a custom cell. In it there is two labels. One of them called nameLabel's height has to change dynamically. It can be 1,2 or 3 lines sometimes. But the rows are on eachother, they cross their own row lines. How can I solve this problem?
The labels and Custom Cell object's Use Autolayout option is disabled.
The label height has to change dynamic, And then the CustomCell's. And then tableRow. My head is confused. And why can't I see CustomCell's background color is changing?
Thanks
Here is my code for :
- (CGFloat)tableView:(UITableView *)tableView
heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
UILabel *label = [[UILabel alloc] init];
label.numberOfLines = 0; // allows label to have as many lines as needed
label.text = [[self.dataList objectAtIndex:indexPath.row] objectForKey:#"NAME"];
CGSize labelSize = [label.text sizeWithFont:label.font constrainedToSize:CGSizeMake(320, 63) lineBreakMode:NSLineBreakByWordWrapping];
CGFloat h = labelSize.height;
NSInteger x=0.0;
if (h==63.0) x=30;
if (h==42.0) x=20;
if (h==21.0) x=10;
return h+30;
}
- (UITableViewCell*)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellID = #"cellid";
CustomCell *cell = (CustomCell*)[tableView dequeueReusableCellWithIdentifier:cellID];
if (cell == nil)
{
cell = (CustomCell*)[[[NSBundle mainBundle]
loadNibNamed:#"CustomCell" owner:nil options:nil]
lastObject];
}
// customization
NSDictionary *d = [self.dataList objectAtIndex:indexPath.row];
cell.nameLabel.text = [d objectForKey:#"NAME"];
cell.cityLabel.text = [d objectForKey:#"CODE"];
cell.indexPath = indexPath;
return cell;
}
At this link there is picture of simulator and xib of the Custom Cell to understand easy the problem:
http://compfreek.wordpress.com/2013/08/14/custom-cell-for-table-row-height-changes-dynamic/
Hear is another way try this change according to ur code it may different, but it may solve your problem.I am putting all views through code only, because it is easy for me check this out.
//in your subclassed class
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
//may be u did same i am adding the label to cell
UILabel *nameLabel = [[UILabel alloc]initWithFrame:CGRectZero];
nameLabel.numberOfLines = 5; //set number of lines
nameLabel.tag = 100;
[self addSubview:nameLabel];
UILabel *otherLabel = [[UILabel alloc] initWithFrame:CGRectZero];
otherLabel.tag = 200;
[self addSubview:otherLabel];
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
//do your customisation when cell is selected
}
-(void)layoutSubviews
{
//in this method i am setting the frames for label
[super layoutSubviews];
UILabel *nameLabel = (UILabel *) [self viewWithTag:100];
nameLabel.text = self.nameString;
CGSize maxSize = CGSizeMake(self.bounds.size.width / 2, MAXFLOAT);//set max height
CGSize nameSize = [self.nameString sizeWithFont:[UIFont systemFontOfSize:17]
constrainedToSize:maxSize
lineBreakMode:NSLineBreakByWordWrapping];
nameLabel.frame = CGRectMake(self.bounds.origin.x +2,self.bounds.origin.y+3, nameSize.width, nameSize.height);
UILabel *otherLabel = (UILabel *) [self viewWithTag:200];
otherLabel.frame = CGRectMake(nameLabel.frame.size.width+15,self.bounds.origin.y+3, 100, 40);
otherLabel.text = self.otherString;
}
//in your main class
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:#"CustomCell"];
if(cell == nil)
{
cell = [[[CustomCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"CustomCell"]autorelease];
}
//change it for ur need
NSString *name = #"hear is your long length name uzamaki naruto from uzamaki clan";
NSString *other = #"other name";
cell.nameString = name;
cell.otherString = other;
return cell;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *name = #"hear is your long length name uzamaki naruto from uzamaki clan";
//replace it your height logic
float cellWidth = 350; // ur cell width
CGSize maxSize = CGSizeMake( cellWidth / 2, MAXFLOAT);//set max height
CGSize nameSize = [name sizeWithFont:[UIFont systemFontOfSize:17]
constrainedToSize:maxSize
lineBreakMode:NSLineBreakByWordWrapping];
return nameSize.height + 10;// for ur 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.