Reputation: 7068
Where do I use the height calculated in heightForRowAtIndexPath?
Sorry if the text is not too clear, this is Hebrew :) See, the second cell has 2 lines? So I wanted the cell to be higher. So, I've calculated the height of the cell acording to the text and then went to setup the cell. The background, for instance should have been as the size of the cell itself, and it all mixed up...
Here is the code:
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
AnswerObject* answer = self.question.answers[indexPath.row];
CGFloat height = [AnswerTableViewCell answerCellHeight:answer];
return height;
}
-(AnswerTableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
AnswerTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[AnswerTableViewCell alloc] init];
}
AnswerObject* answer = self.question.answers[indexPath.row];
[cell setupAnswerTableViewCell:self.question answer:answer row:indexPath.row];
return cell;
}
AnswerTableViewCell:
- (id)init
{
self = [super init];
if (self) {
// self.frame = CGRectMake(0, 0, 280, 77);
self.backgroundColor = [UIColor clearColor];
self.contentView.backgroundColor = [UIColor clearColor];
self.answerLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 10, self.frame.size.width-20, self.frame.size.height)];
self.answerLabel.numberOfLines = 20;
self.answerLabel.textColor = [UIColor whiteColor];
self.answerLabel.font = [UIFont fontWithName:@"HelveticaNeue-Light" size:16];
self.answerLabel.textAlignment = NSTextAlignmentRight;
self.answerLabel.lineBreakMode = NSLineBreakByWordWrapping;
self.answerToggle = [[UIButton alloc]initWithFrame:CGRectMake(self.frame.size.width-50, 23, 30, 30)];
self.backgroundImage = [[UIImageView alloc]init];
self.backgroundImage.frame = self.bounds;
[self addSubview:self.answerLabel];
[self addSubview:self.answerToggle];
[self addSubview:self.backgroundImage];
}
return self;
}
-(void)setupAnswerTableViewCell:(QuestionObject*)question
answer:(AnswerObject*)answer
row:(NSInteger)row{
self.question = question;
self.answer = answer;
self.row = row;
CGSize labelSize = [answer.answerText sizeWithFont:self.answerLabel.font constrainedToSize:CGSizeMake(self.answerLabel.frame.size.width, 100000) lineBreakMode:self.answerLabel.lineBreakMode];
// self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, labelSize.height + 20);
self.answerLabel.frame = CGRectMake(self.answerLabel.frame.origin.x, self.answerLabel.frame.origin.y, self.answerLabel.frame.size.width, labelSize.height);
self.answerLabel.text = answer.answerText;
[self.answerToggle addTarget:self
action:@selector(flip:)
forControlEvents:UIControlEventTouchDown];
self.answerToggle.tag = [answer.answerID intValue];
if (self.row == 0) {
self.backgroundImage.image = [UIImage imageNamed:@"List_Top_Item_Not_Selected_612x113px.png"];
}
else if (self.row == ([self.question.answers count] - 1)){
self.backgroundImage.image = [UIImage imageNamed:@"List_Bottom_Item_Not_Selected_612x113px.png"];
}
else{
self.backgroundImage.image = [UIImage imageNamed:@"List_Item_Not_Selected_612x113px.png"];
}
}
+(CGFloat)answerCellHeight:(AnswerObject*)answer{
CGSize labelSize = [answer.answerText sizeWithFont:[UIFont fontWithName:@"HelveticaNeue-Light" size:16] constrainedToSize:CGSizeMake(280, 100000) lineBreakMode:NSLineBreakByWordWrapping];
return labelSize.height + 20;
}
Upvotes: 0
Views: 120
Reputation: 21805
heightForRowAtIndexPath
the UITableView
ask the datasource for the height of the cell it should prepare before you can fill its contents.
The tableView then allocates that much size/space between two cells.
The cells that go though there are still needed to be given by the datasource and that is done in cellForRowIndexPath
method.
Edit
Your frames are overlapping as you are returning custom heights for the cell. but not using them in the cell and initializing subviews to other values.
You can use layoutSubviews
to get proper height and lay out your views properly.. or use a extra parameter height in the setupAnswerCell
method and pass in the custom height and layout your items there.
Upvotes: 1
Reputation: 119031
You don't use the height, you just provide it. The table view uses it to determine the overall height of the content and how to display the cell at that index path. The cell should expect to be laid out at the stated height / resize appropriately to that height.
When you're setting up your cell in code and not using auto-layout you should be setting the frame of the cell. It doesn't really matter what you set it to, but you should set it and then the frames of all subviews relative to it. You then need to add auto-resizing rules to all of the subviews. In your case, both subviews should specify flexible width and height rules.
Add these things to ensure your cell contents are laid out properly.
Upvotes: 0
Reputation: 535801
Here is example code:
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
int ix = indexPath.row;
if ([NSNull null] == self.heights[ix]) {
NSString* s = self.trivia[ix];
CGFloat h = [self cellHeightForLabelString:s];
self.heights[ix] = @(h);
}
return [self.heights[ix] floatValue];
}
I don't know when and how many times I will be asked for the height of any given row, and calculating the height takes a little bit of time, so I keep an array of all the heights, which starts out as an array of NSNull objects. If I have already calculated the height for the requested row, I return it. If I haven't, I calculate it, store it, and then I return it.
The runtime then makes each row the height that I requested.
Upvotes: 1
Reputation: 22936
The heightForRowAtIndexPath is a delegate method you implement, all you need to do is return the value for the height you want each cell to be and the TableView will 'use' the value and set the cell height itself.
cellForRowAtIndexPath is recursively called to layout the contents of each cell (set labels, imageViews for each cell etc) just before they're presented on screen.
Consider this simple heightForRowAtIndexPath:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 50;
}
If this was your implementation, each cell in your tableview would automatically have it's height set to 50 points.
You don't have to do anything more... Simply return the height value you want for each cell.
This is only a simple example, you could put some conditional logic in heightForRowAtIndexPath that makes every second cell (for example) a different height.
Upvotes: 1