Can't change UITableViewCell contentView height - ios

I have a custom uitableviewcell.
i want to change its height based on some if condition.
How can i be able to do this ?
I tried doing this in cellForRowAtIndexPath -
if (cell.newsFeedImage.image == NULL)
{
NSLog(#"NULL");
cell.uDisplayImage.frame = CGRectMake(20, 20, 20, 20);
}
The log message appears, but the frame never changes.
Please help.

try to do this in heightForRowAtIndexPath
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
if (cell.newsFeedImage.image == nil) {
cell.uDisplayImage.frame = CGRectMake(20, 20, 20, 20);
}
else return 40;
}

The height of the cell is set in the tableView datasource method
heightForRowAtIndexPath

It's a little more complicated than that.
This questions has been answered at great length here: Using Auto Layout in UITableView for dynamic cell layouts & variable row heights

Related

UITableView second prototype cell does not appear to be respecting custom height?

I am dequeuing the second prototype cell but the height of the cell appears to not be respected.
Can anyone lead me in the right direction ? I have tried searching google with no avail.
The problem has been solved,my solution is implementing in code:
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
CGFloat height;
if ([indexPath row] == 0) {
height = 170.0f;
}
else {
height = 72.0f;
}
return height;
}
you need to implemented the table view delegate method heightForRowAtIndexPath: in order to change a cell's height. you can't do this purely in storyboards.
Remember
storyboards or xib can not dequeue cell without code,so you have to setDelegate and write in code tableView:heightForRowAtIndexPath ,
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
CGFloat height;
if ([indexPath row] == 0) {
height = 100.f;
}
else {
height = 50.f;
}
return height;
}

UIImageView auto resize inside a custom UITableViewCell with varying height

I have set up a custom cell prototype inside storyboard not using autolayout and i have run into a rather vexing problem where a UIImageView i have inside the cell seems to obey constraints all of it's own when i want it to reflect the size of the cell with a bit of padding.
Here is the setup in storyboard interface builder and view mode is set to "scale to fill"
And here is what i get back, with no editing of the placement or scaling of the image, it seems very much like it's using aspect fill.
I have tried various options and none seem to work for me so far, The only other way i can think is turn of auto resizing and set the rect myself manually when the cell is created any ideas?
and my code for setting the cell
- (void)setCell:(NSDictionary*)messageData
{
[_nameLabel setText:messageData[#"name"]];
[_messageLabel setText:messageData[#"message"]];
[_nameLabel sizeToFit];
[_messageLabel sizeToFit];
UIImage *image;
if([messageData[#"direction"] boolValue])
{
image= [[UIImage imageNamed:#"bubble_left"]resizableImageWithCapInsets:UIEdgeInsetsMake(18, 6, 6, 10) resizingMode:UIImageResizingModeStretch];
}
else
{
image= [[UIImage imageNamed:#"bubble_right"]resizableImageWithCapInsets:UIEdgeInsetsMake(18, 10, 6, 6) resizingMode:UIImageResizingModeStretch];
}
[_bubbleImage setImage:image];
}
and the protocol methods
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CUIChatCellTableViewCell *cell = [_chatTableView dequeueReusableCellWithIdentifier:#"CustomCell" forIndexPath:indexPath];
NSDictionary *messageData = _testDataArray[indexPath.row];
[cell setCell:messageData];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
_customCell = [_chatTableView dequeueReusableCellWithIdentifier:#"CustomCell"];
//configure cell
NSDictionary *messageData = _testDataArray[indexPath.row];
[_customCell setCell:messageData];
//Get height of the cell
CGFloat height = [_customCell.messageLabel frame].size.height+[_customCell.nameLabel frame].size.height+20;
return height;
}
Set autoresizing properties like this, may you get help from this.
I could not get AutoResizing to work and i tried another test project from scratch and it seemed to work, so it must have been certain settings, either way i ended up having to set the height manually for each cell based on it's content anyway here is the code to do so
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
_customCell = [tableView dequeueReusableCellWithIdentifier:#"CustomCell"];
//configure cell
CMessageInfo *messageData = _testDataArray[indexPath.row];
[_customCell setCell:messageData];
//Get height of the cell
CGFloat height = [_customCell.messageLabel frame].size.height+[_customCell.nameLabel frame].size.height+20;
return height;
}

Table Cell expansion laggy

I have a custom table view & cell where a cell is expanded when selected. It is now functioning properly and accordingly. However, When I select cells to expand them, it takes about half a second to respond. The code below is located in the didSelectRowAtIndexPath. My hypothesis is that between beginUpdates and endUpdates, there are too many things going on to increase the height of the original cell and then updating the whole table view. Is there another way I can better implement this?
**[_tableView beginUpdates];**
ReviewTestTableCell *reviewCell1 = (ReviewTestTableCell *)[tableView cellForRowAtIndexPath:indexPath];
CGRect rect = CGRectMake(reviewCell1.review.width, 900, reviewCell1.review.width, 900);
CGRect textRectb = [reviewCell1.review textRectForBounds:rect limitedToNumberOfLines:1000];
float labelHeight = textRectb.size.height;
reviewCell1.review.height = labelHeight;
expandHeight = labelHeight + 75 ;
if ([[userdefaults objectForKey:#"merchantType"] isEqual:#"T"])
{reviewCell1.height = labelHeight + 50;
reviewCell1.bottomRatingView.height = reviewCell1.bottomRatingView.height - 20;
}
else
{
reviewCell1.height = labelHeight + 75;}
reviewCell1.bottomRatingView.hidden = NO;
reviewCell1.bottomRatingView.top = reviewCell1.review.bottom;
**[_tableView endUpdates];**
[_isExpandList replaceObjectAtIndex:indexPath.row withObject:#1];
}
EDIT/ADD:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell3 = [self tableView:tableView cellForRowAtIndexPath:indexPath];
if ([_isExpandList[indexPath.row] isEqual: #1] && [[_dataList objectAtIndex:indexPath.row] valueForKey:#"Item1Score"] != nil) {
return cell3.height + 3 + 65;
}
else if ([_isExpandList[indexPath.row] isEqual: #0])
{
return cell3.height +5;
}
else return cell3.height +3;
}
You should not go through that elaborate dance of trying to manually expand the cell. You should certainly not manually call willDisplayCell.
Using the method described in the answer to this question, you should have a property or something to keep track of which cell was selected and make your heightForRowAtIndexPath: method adjust for that particular indexPath, then just call
[tableView beginUpdates];
[tableView endUpdates];
Which will call heightForRowAtIndexPath for every cell, which your method will give a larger height for when it matches the selected row. The tableView will smoothly adjust the height of your cell.
Something similar to:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([self.selectedIndexPath isEqual:indexPath]) {
return 80.0f;
}
return tableView.rowHeight;
}

The created cell is wider then it should be.

I am creating a cell:
-(AnswerTableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
AnswerTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[AnswerTableViewCell alloc] initWithFrame:CGRectMake(0, 0, self.answersTable.frame.size.width, [self tableView:nil heightForRowAtIndexPath:indexPath])];
}
NSLog(#"cell.frame - %#", NSStringFromCGRect(cell.frame));
NSLog(#"self.answersTable.frame - %#", NSStringFromCGRect(self.answersTable.frame));
AnswerObject* answer = self.question.answers[indexPath.row];
CGFloat height = [self tableView:nil heightForRowAtIndexPath:indexPath];
[cell setupAnswerTableViewCell:self.question answer:answer row:indexPath.row height:height];
return cell;
}
I see only a half of it.
When I print the cell and the table frames, I can see that the table is thiner then the cell. How did it happened?
2014-03-20 21:36:22.478 Theory[43601:60b] cell.frame - {{0, 0}, {320, 44}}
2014-03-20 21:36:22.479 Theory[43601:60b] self.answersTable.frame - {{20, 38.880001068115234}, {280, 500}}
You should create your cell using this initializer
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
This is the usual init in cells, so you do not need frame.
// You need to get the cell height from the answer text and return it in this method as CGFloat (Something like this example)
-(CGFloat)getAnswerHeightForCell:(Aswer *)answer {
NSString *text = answer.text;
CGSize textSize = [text sizeWithFont:[UIFont systemFontOfSize:14.0f] constrainedToSize:CGSizeMake(self.tableView.frame.size.width - PADDING * 3, 1000.0f)];
return textSize.height ;
}
In your dataSource and delegate methods of the tableView you need to add the height of the cell and create the cell.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
Answerobject * answer = [self.question.answers[indexPath.row];
CGFloat answeSize = [self getAnswerHeightForCell:answer ];
return textSize.height + SOME_EXTRA_HEIGHT_FOR_PADDING;
}
-(AnswerTableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
AnswerTableViewCell *cell =( AnswerTableViewCell*) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[LZCommentCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] ;
}
AnswerObject* answer = self.question.answers[indexPath.row];
[cell setupAnswerTableViewCell:self.question answer:answer row:indexPath.row];
return cell;
}
It's probably not the tableViewCell that has the wrong frame, but the tableview. In case of UITableView, its rows will always have the same width as the tableView itlself.
BTW you really should not use initWithFrame:reuseIdentifier: since it's deprecated. (And especially not nitWithFrame: method, how will your cell know about its reuseIdentifer?) You should use initWithStyle:reuseIdentifier: instead if you are creating your cells programmatically.
Also calling
[self tableView:nil heightForRowAtIndexPath:indexPath]
in tableView:cellForRowAtIndexPath is very wrong. If you pass tableView in the parameter it will cause an infinite loop, that's probably the reason why you are passing nil. You can extract the code in your tableView:heightForRowAtIndexPath into a separate method and call in both cases. But you really should trust your cell to adjust the layout of its content based on its height, so you really should not deal with cell frame in tableView:cellForRowAtIndexPath method.

cellForRowAtIndexPath sees cell as different height when its loaded, then reloaded?

Preface: this is quite an abstract question.
I've got some cells in a UITableView that use a different image depending on the height of the cell (in 50px increments, from 50px up to 1000px high). I'm hitting a weird issue where when the app first loads, cellForRowAtIndexPath reports that the first three cells (regardless of whether or not all three are onscree) have a height of 100px, then when I scroll down and back up again, their height reverts to the correct value. There's no onscreen change of height, only the image used changes, and the value of cell.frame.size.height in my NSLog statements.
I've been logging in heightForRowAtIndexPath and cellForRowAtIndexPath, and I can verify that the heights are correct when they leave heightForRowAtIndexPath. But, when entering cellForRowAtIndexPath, those first three heights are all set uniformly to 100. I then scroll down until those three cells are off-screen, then scroll back up, and the .height value has changed to the correct value.
To summarise, my questions are:
Is there any code called between the very end of heightForRowAtIndexPath and the very beginning of cellForRowAtIndexPath that could be changing the cell.frame.size.height value of these first few cells?
Why would this issue only be occurring on the first THREE cells? And, why would they revert when reloaded a moment later? I thought the reuse identifier could be the cause, but they're still assigned that identifier when first loaded, so that shouldn't matter, should it?
EDIT: I think the 100px height is coming from the row height of the prototype cell in my storyboard, as if I change that to 101px, those first three cells are then initially at 101px.
EDIT: Here's the code I'm using to set the image, though this part is working, it's just got the wrong value to work with:
UIImage *cappedBG;
float cellHeight = cell.contentView.frame.size.height;
if (cellHeight <= 51) {
cappedBG = [[UIImage imageNamed: #"bg50.png"] resizableImageWithCapInsets: UIEdgeInsetsMake(25, 25, 25, 25) resizingMode: UIImageResizingModeStretch];
} else if (cellHeight <= 101) {
cappedBG = [[UIImage imageNamed: #"bg100.png"] resizableImageWithCapInsets: UIEdgeInsetsMake(25, 25, 25, 25) resizingMode: UIImageResizingModeStretch];
} else if (cellHeight <= 151) {
cappedBG = [[UIImage imageNamed: #"bg150.png"] resizableImageWithCapInsets: UIEdgeInsetsMake(25, 25, 25, 25) resizingMode: UIImageResizingModeStretch];
} else if (cellHeight <= 201) {
cappedBG = [[UIImage imageNamed: #"bg200.png"] resizableImageWithCapInsets: UIEdgeInsetsMake(25, 25, 25, 25) resizingMode: UIImageResizingModeStretch];
} else {
cappedBG = [[UIImage imageNamed: #"bg250.png"] resizableImageWithCapInsets: UIEdgeInsetsMake(25, 25, 25, 25) resizingMode: UIImageResizingModeStretch];
}
You just can't rely on the frame of the cell in tableView:cellForRowAtIndexPath:. The frame of the cell you configure in that method will be set after the code has returned from this method.
The values you get are not the actual heights of that particular row. You get the height from the cell that has just been dequeued. If there is no cell to dequeue the height from the cell that was just created is used. And 100 is probably the height of the cell in your storyboard/nib.
This height has nothing to do with the height of the cell that will be displayed.
Since you calculate the row height in tableView:heightForRowAtIndexPath: already, use this value.
float cellHeight = [self tableView:tableView heightForRowAtIndexPath:indexPath];
if (cellHeight <= 51) {
cappedBG = [[UIImage imageNamed: #"bg50.png"] resizableImageWithCapInsets: UIEdgeInsetsMake(25, 25, 25, 25) resizingMode: UIImageResizingModeStretch];
...
You shouldn't really be doing layout of a cell in cellForRowAtIndexPath.
The best way to do this is to create a UITableViewCell subclass with all the UI elements you need.
Then in the subclass you can override - (void)layoutSubviews.
This way you keep everything separate rather than putting EVERYTHING in the view controller.
Currently, after looking at your question, I think you are having trouble with different cell heights (when scrolled). I believe you have not given correct values in heightForRowAtIndexPath.
Following is the simple code that I have written. This code has displays 20 rows in the table and alternate row has different size.(I have used different colours to distinguish)
#pragma mark - TableView DataSource Methods
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexPath.row %2 == 0) return 50;
else return 100;
}
// Customize the number of sections in the table view.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 20;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *stringCellIdentifier = #"BookOutVehicleCell";
UITableViewCell *tableViewCell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:stringCellIdentifier];
if (tableViewCell == nil)
tableViewCell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:stringCellIdentifier] autorelease];
if(indexPath.row %2 == 0) tableViewCell.contentView.backgroundColor = [UIColor redColor];
else tableViewCell.contentView.backgroundColor = [UIColor greenColor];
return tableViewCell;
}
#pragma mark - TableView Delegate Methods
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
This is the output.
In this case, even if we scroll the tableview up and down, rows height does not change.
Hope this helps. And sorry If I have misunderstood your question. It would be nice if you provide a code snippet. It will give us better idea about the issue.
EDIT:
As per my understanding of the issue you are getting correct heights for each row/cell, however you have used an imageview in cell which will display different images as per the height of the cell. Check if following works for you:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *stringCellIdentifier = #"BookOutVehicleCell";
UITableViewCell *tableViewCell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:stringCellIdentifier];
if (tableViewCell == nil)
tableViewCell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:stringCellIdentifier] autorelease];
//Check your height here and use appropriate image
if(cell.contentView.frame.size.height <100)
{
image = "xxx.png";
}
else
if(cell.contentView.frame.size.height >=100 && cell.contentView.frame.size.height <200)
{
image = "yyy.png";
}
}
Thanks.

Resources