Reusing UITableViewCell moves subview frame - ios

I'm subclassing UITableViewCell. In the xib for my custom cell, I have an UIImageView that has a frame of (0, 0, 57, 57). It has autolayout constraints set to top, left, width, and height.
When the table view is first rendered, all the cells look fine. But when I scroll around, (and thus reusing the celles) the frame for the UIImageView shifts to (15, 0, 57, 57). None of the other subviews seem to be affected.
The UITableViewDataSource:
- (UITableViewCell*) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
Content* content = [[[ContentManager sharedContentManager] allContent] objectAtIndex:indexPath.row];
ContnetCell* cell = [tableView dequeueReusableCellWithIdentifier:kCellReuseIdentifier forIndexPath:indexPath];
[cell loadWithContent:content];
return cell;
}
The Cell:
{
[super prepareForReuse];
self.imageView.image = nil;
}
-(void)loadWithContent:(Content*)content
{
self.imageView.image = content.contentImage;
}

It's a custom cell right? If you use the same property names for your custom images or labels as those found in a default cell (i.e, imageView, textLabel or detailTextLabel), strange things can happen. Try renaming imageView to something else and see if that fixes it.

Related

Autolayout is breaking when UITableViewCell is scrolled especially for UIImageView

I need UITableViewCell in a dynamic height depends on the content length.
This is a prototype cell
And the content shows fine when first loaded like this
But when I scroll the UITableView, the cell's content breaks like this, especially for UIImageView.
In the implementation of the cell, I only used setImage and setText method.
What seems the problem? Or, is there another way to set each cell's height differently after viewDidLoad?
** Edit: this is my implementation of cellForRowAtIndexPath
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NotificationCell *cell = [tableView dequeueReusableCellWithIdentifier:#"notification"];
if(!cell) {
[tableView registerNib:[UINib nibWithNibName:#"NotificationCell" bundle:nil] forCellReuseIdentifier:#"notification"];
cell = [tableView dequeueReusableCellWithIdentifier:#"notification"];
}
[cell setContent:[notifications objectAtIndex:indexPath.row]];
[cell layoutIfNeeded];
return cell;
}
And setContent in NotificationCell.m has only setText and setImage
Because the tableView already has an imageView property and it is on the left side of the cell, you set the image to that imageView. You should rename the outlet of your custom imageView. So, it should be not called imageView, give the other name for it.

Can I set my autolayout constraints so that an imageview is set to the height of the image

I am building out a dynamic tableview cell. The height is dynamic based on the content that is loaded. I'm running into a hangup with height of the imageview. The images currently load aspect fill in an imageview that is 100% of the width. Is it possible to set an autolayout constraint on my imageview so that the imageview is hidden (has a height of 0) if there is no image for a tableview cell?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
TableViewTileCell *cell = [tableView dequeueReusableCellWithIdentifier:#"tileCell"];
if (!cell)
{
[tableView registerNib:[UINib nibWithNibName:#"TableViewTileCell" bundle:nil] forCellReuseIdentifier:#"tileCell"];
cell = [tableView dequeueReusableCellWithIdentifier:#"tileCell"];
}
cell.tileView.layer.borderColor = [UIColor blackColor].CGColor;
cell.tileView.layer.borderWidth = 1.0f;
[cell.contentView setBackgroundColor:[UIColor colorWithRed:0.96 green:0.96 blue:0.96 alpha:1.0]];
NSString *url=[self.resultsArray[indexPath.row] valueForKey:#"imageURL"];
cell.tileTitle.text = [self.resultsArray[indexPath.row] valueForKey:#"title"];
cell.tileDate.text = [self.resultsArray[indexPath.row] valueForKey:#"date"];
cell.tileContent.text = [self.resultsArray[indexPath.row] valueForKey:#"summary"];
if(![url isEqualToString:#""]){ //If we got a url value back load the image
[cell.tileImageview setImageWithURL:[NSURL URLWithString:url] placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
}
return cell;
}
Is it possible to set an autolayout constraint on my imageview so that the imageview is hidden (has a height of 0) if there is no image for a tableview cell?
Make the whole cell content a vertical UIStackView. In cellForRow, make the image view hidden. The stack view has the wonderful ability to change the constraints in exactly the way you describe: when the image view is hidden, the constraints will change and the image view will occupy zero space, with the other views occupying the whole space.
The alternative is not terrible: you simply have to do, yourself, what the UIStackView would do — remove the empty image view in code and adjust the constraints, in cellForRow. Swapping constraints and views together into and out of the interface is standard practice, and is easy to do.

I'm having trouble resizing a table view cell

I am trying to create a sample app to resize a cell. The cell is staying at the default height of 44px. I am unable to make this change through the storyboard because I have a view with varying height inside the cell. Can this be done with only 1 cell? I have an outlet from the table cell to the variable called cell. My code in the .m file is as follows. Also, all the cells are already static.
self.whereCell.frame = CGRectMake(0, 191, 320, 78);
Have you tried the tableView:heightForRowAtIndexPath: method?
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == 0) {
return 191;
}
return 44;
}
This shouldn't been needed if the cell is static though; you should be able to set the height of the cell in Interface Builder.

UITableview cell subview larger height then cell

#All Hello
Its quite interesting problem i have.
Actually i have subviews which can be larger in height then cell height itself (Its required for my design). For example cell "A" height is 40 while subview height= 70.
I can show larger subview but when the cell A goes off the screen (i scroll to top) then its subview also disappear (Obvious) result. But that gives undesired effect as larger subview which before extends to cell say "B" beneath container cell suddenly disappear.
I have tried to set cell background as transparent in willDisplayCell delegate method but no luck.
Below is my related method if anyone wants to see
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *MyIdentifier = #"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:nil];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:MyIdentifier] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
NSArray *newArray = [[dataDictionary allKeys] sortedArrayUsingSelector: #selector(compare:)];
[cell.contentView addSubview: [[[dataDictionary objectForKey:[newArray objectAtIndex:indexPath.section]] objectForKey:#"DayView"] objectAtIndex:indexPath.row]];
return cell;
}
Pardon me if i am not very much clear but this is best i can explain my situation.
I want to show views like http://postimg.org/image/e5ok5hybl/ image.
If you must do this, you can use a simple trick:
Move the y-origin of the table to a negative value equal to the amount your view extends below the cell, e.g. origin -30px.
Make the table height taller by the same amount, i.e. make it 30px taller.
Increase the top content inset of the table by the same amount, i.e. increase by 30px.
What you've effectively done is extend the table view off-screen while maintaining the original position of the cells. Since the table view extends off-screen, the cell will not be dequeued until the part that extends below the cell has scrolled off screen.
Here is a sample project demonstrating the trick.

resizing a UITableViewCell frame issue

I am trying to resize my UITableViewCell's frame via:
[cell setFrame:CGRectMake(cell.frame.origin.x,
cell.frame.origin.y,
cell.frame.size.width,
cell.frame.size.height+25)];
however, it's not resizing after I do this... why is this?
This is weird as if I add a UIToolBar into the cell, it resizes but when I am adding a UIView, it doesn't:
[cell.contentView addSubview:sideSwipeView];
Here's the long and short of it:
Your cell width is determined by the width of the tableview it's in.
[EDIT: If it's a grouped table view, the cell is 20 - 60 pixels narrower than the tableview width, depending if you're using an iPhone, or an iPad.]
Your cell height is determined by the heightForRowAtIndexPath method.
If you're manually setting the cell's frame, it's going to be useless except when you're using a subclassed cell where you want to add subviews based on the cell's dimensions.
Even in this case, it's recommended to get the cell's frame from the tableview by using rectForRowAtIndexPath:(NSIndexPath*)indexPath method and then setting that frame as the cell's frame (after setting the frame's origin Y as 0).
I'm not quite sure about the UIToolBar, but your subview's frame won't change on changing the cell frame.
Maybe if you could tell us what you're trying to achieve, we can suggest a solution for you?
--------------------EDIT--------------------
So you need to dynamically add a subview to a cell on tapping it and resize it's height according to the new subview. This is gonna get hairy so here goes:
In your .h file declare:
BOOL subviewAdded;
In your .m file, in the init, do:
subviewAdded = NO;
Let's assume that you want the cell's height to be 50 without the subview and 100 with the subview. Accordingly, your heightForRow method should be:
- (CGFloat)tableView:(UITableView *)tableView
heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return (subviewAdded?100.0f:50.0f);
}
This means that initially since subviewAdded is NO, all your cells will have the smaller height.
Now, to add a subview to a cell on tapping it, and to change it's height dynamically, do this in your didSelectRow method:
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
//Get the cell at this indexPath
UITableViewCell *thisCell = [tableView cellForRowAtIndexPath:indexPath];
if(subviewAdded)
{
subviewAdded = NO;
for(int i = 0; i < [thisCell.contentView.subviews count]; i++)
{
UIView *thisSubview = [thisCell.contentView.subviews objectAtIndex:i];
[thisSubview removeFromSuperview];
}
}
else
{
UIView *someView = [[UIView alloc] initWithFrame:someFrame];
[thisCell.contentView addSubview:someView];
[someView release];
subviewAdded = YES;
}
NSMutableArray *array = [NSMutableArray array];
[array addObject:indexPath];
[tableView reloadRowsAtIndexPaths:array
withRowAnimation:UITableViewRowAnimationFade];
}
So what's going to happen here is you're adding a subview to this cell you've tapped. Reloading this cell will call heightForRowAtIndexPath and do a nice little fade animation and change your tableview heights.
IMPORTANT: Ideally, you should maintain an array of NSNumbers with boolean values. The array size should be the same size as the number of tableview cells you have.
In heightForRow, you would then check against this array instead of using a single boolean for the whole tableView. This would ensure that you could have different heights for different cells.
That would look something like:
- (CGFloat)tableView:(UITableView *)tableView
heightForRowAtIndexPath:(NSIndexPath *)indexPath {
BOOL thisBool = (BOOL)[[booleanArray objectAtIndex:indexPath.row] boolValue];
return (thisBool?100.0f:50.0f);
}
I didn't post all that code here since it's implied and what I've posted should put you well on your way to doing the boolean array thing.
Anyway, there you are. I just tested this code myself so it works :)
If you want to increase the height of your cell based on some parameter eg. text, image,
you must implement the heightForRowAtIndexPath method of UITableViewDelegate in your code.
- (CGFloat)tableView:(UITableView *)tableView
heightForRowAtIndexPath:(NSIndexPath *)indexPath

Resources