How to switch off -reloadData's cell height animation - ios

I have a UITableView, its cells' height can be either 68pt or 78pt. For example there are two 68pt height cells and one 78pt. I add new object to the datasourse and then call -reloadData to refresh the UITableView. But when this method fires - appears animation of one cell height change and I'd like to switch it off.
Due to some limitations I can't use [tableView beginUpdates] and [tableView endUpdates].

Try:
[UIVIew setAnimationsEnabled:NO];
[tableView reloadData];
[UIView setAnimationsEnabled:YES];
to see if this is what you want. (animations in UIView are enabled by default)

Related

Asynchronous image download inside a cell without knowing the height

I'm facing this problem and I've been trying to figure out how to fix it but without success.
I have a table view with cells that contain an image which I still don't know which height is going to be. I created an outlet to the height constraint of the imageView and I'm downloading the image asynchronous with PinRemoteImage (I can use SDWebImage too but I think it's buggy in iOS 9). Inside the blocks is where I assign the new constant for the height constraint and then I do a layout update.
The cell never updates, the only way I can see the image correctly is scrolling down and then up (when the tableview repaints the cell)
__weak typeof(UITableView*) weakTable = tableView;
__weak typeof(NSIndexPath*) index = indexPath;
[cell.commentImageView pin_setImageFromURL:[[CTImageHelper sharedInstance] resizedImageURLConverterFromStringWithPrefix:comment.image.completePath andOptions:optionsString] completion:^(PINRemoteImageManagerResult *result) {
CommentTableViewCell *cellToUpdate = [weakTable cellForRowAtIndexPath:index];
cellToUpdate.heightSize = [NSNumber numberWithFloat:result.image.size.height/2];
cellToUpdate.commentImageViewHeightConstraint.constant = result.image.size.height/2;
[cellToUpdate setNeedsLayout];
}];
This is the code for setting the table view row height automatically
self.postTableView.estimatedRowHeight = 244.0;
self.postTableView.rowHeight = UITableViewAutomaticDimension;
And an image about the cell constraints:
Any ideas about what am I doing wrong? Thanks!
Put layoutIfNeeded just after setNeedsLayout
[cellToUpdate setNeedsLayout];
[cellToUpdate layoutIfNeeded];
// and then tell the tableView to update.
[weakTable beginUpdates];
[weakTable endUpdates];
// then scroll to the current indexPath
[weakTable scrollToRowAtIndexPath:indexPath
atScrollPosition:UITableViewScrollPositionNone
animated:NO];
Update [weakTable beginUpdates];[weakTable endUpdates]; might crash if call it more than once at a time. you need to make sure there is no colision between them.
You may also try just reloading the cell itself.
[cellToUpdate setNeedsLayout];
[cellToUpdate layoutIfNeeded];
[weakTable reloadRowsAtIndexPaths:[indexPath] withRowAnimation:UITableViewRowAnimationNone];
You should call layoutIfNeeded after calling setNeedsLayout to actually trigger the layout.
You need to tell the tableview that the height has changed on it's cells by triggering an empty update, apart from the setNeedsLayout and layoutIfNeeded:
[tableView beginUpdates];
[tableView endUpdates];

UITableViewCell - Update tableview layout

I have a tableviewcell, that on tap, grows in size, height wise, by updating the frame.
The problem is, the cells below don't adjust, move down to make it visible underneath, and the select row events are still based on the old sizes, before tap. I am using Facebook POP - which is handling animation, so tableview.beginUpdates() is out of the question, maybe?
You cannot manually update the frame of a UITableViewCell by changing its frame or bounds. Instead, you need to change the value returned by -tableView:heightForRowAtIndexPath: for that indexPath and then perform:
[self.tableView beginUpdates];
[self.tableView endUpdates];
This will cause the tableView to recalculate the heights of all the rows.
First, you need to make sure that you return the new height in heightForRowAtIndexPath, then you need to make the tableview update the cell. If you don't care about animation just call [tableview reloadData]. If you want animation you need to call [tableview reloadRowAtIndexPath: indexpath_of_your_cell]

Visible UITableViewCells not resizing on rotate

I have a UITableView with custom cells. When I rotate the device, the visible cells do not resize. Scrolling to new cells works fine and when I scroll back, all is well, but is there a way to get the initial, visible cells to smoothly resize on rotate?
[self.tableview reloadData] from the UITableViewController; works, but I don't think that is the optimal solution, as it requires a network call for data retrieval.
I am already calling the following code from the UITableViewController in order to layout some gradient layers I use, but this does nothing to resize the ImageView.
-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
for (ProjectCell *cell in [[self.tableView.subviews firstObject] subviews]) {
cell.laidOut = NO;
[cell layoutSubviews];
}
}
Thanks
I believe this will do what you want:
[self.tableView beginUpdates];
[self.tableView reloadRowsAtIndexPaths:[self.tableView indexPathsForVisibleRows] withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView endUpdates];
As long as the cells you want to reload are the visible cells.

UITableView animation glitch when deleting and inserting cells with varying heights

I am having a problem with the animation that UITableView provides when deleting and inserting a cell at the same time.
I have a list of cells lets call them questions. When one question is tapped it should add a cell beneath itself to display the answer to that question. If another answer is already being displayed that answer should be removed from the table.
The issue arises when the cell being inserted is very tall. If it is so tall that it's eventual bounds encroach into the space that the cell to be deleted takes up then during the animation we see the through the answer cell that we are deleting to see the cell that is being added
(see link to video of problem)
the is what my code looks like to move around the cells in the table view
[tableView beginUpdates];
if (deleteIndex) {
[tableView deleteRowsAtIndexPaths:#[deleteIndex] withRowAnimation:UITableViewRowAnimationTop];
}
if (addIndex) {
[tableView insertRowsAtIndexPaths:#[addIndex] withRowAnimation:UITableViewRowAnimationTop];
}
[tableView endUpdates];
I have tried
[tableView beginUpdates];
if (deleteIndex) {
[tableView deleteRowsAtIndexPaths:#[deleteIndex] withRowAnimation:UITableViewRowAnimationTop];
}
[tableView endUpdates];
//do stuff to update data source
[tableView beginUpdates];
if (addIndex) {
[tableView insertRowsAtIndexPaths:#[addIndex] withRowAnimation:UITableViewRowAnimationTop];
}
[tableView endUpdates];
But because there's no callback confirming that the table view did complete the first set update before starting the second block pretty much the same problem occurs. I know I could use perform selector with delay, but this seems like a bandaid.
Second I tried to encompass the animation in a block like this
[UIView animateWithDuration:0.0 animations:^{
[tableView beginUpdates];
if (deleteIndex) {
[tableView deleteRowsAtIndexPaths:#[deleteIndex] withRowAnimation:UITableViewRowAnimationTop];
}
[tableView endUpdates];
//do stuff to update data source
} completion:^(BOOL finished) {
[tableView beginUpdates];
if (addIndex) {
[tableView insertRowsAtIndexPaths:#[addIndex] withRowAnimation:UITableViewRowAnimationTop];
}
[tableView endUpdates];
}];
Again, because the completion block is fired after we call endUpdates not after the updates actually complete this does not resolve the use.
I also went into storyboard to be sure that clip subviews to bounds is selected for the cells. Again, this does not resolve the issue because we are not seeing a subview of the cell expand beyond it's expected height.
Looking closer at the animation by slowing it down it looks like apple inserts the cell to be added under the cells that won't be changed in the table and then moves the cells that will remain into their new positions. As a result the cell that was deleted becomes a transparent window where we see what they are actually doing under the hood.
The right approach would be to first remove the old answer and then after the animation is over add the new answer. There is a UITableViewDelegate method that is triggered after the cell animation is complete.
tableView:didEndDisplayingCell:forRowAtIndexPath:
Inserting the new answer row within this delegate method will result in the correct animation.
There are a few details to keep in mind- You'll need some logic to ensure that the correct cell height is returned and that the correct number of expected rows in the section is returned. Those data source methods are called after we remove our old answer in and again when we add the new one when we call
endUpdates
on the table view
Using anything other than UITableViewRowAnimationTop results in some strange animation behavior. This is because the content view of the cell is not what is being animated.
i solve same problem in my project by hide control like:
in ~cell.m have
(void)setSelected:(BOOL)selected animated:(BOOL)animated;
{
if(selected == NO)
{
self.selectedView.hidden = YES;
self.descriptionLabel.hidden = YES;
}
else
{
self.selectedView.hidden = NO;
self.descriptionLabel.hidden = NO;
}
}
may it still helpful

Objective-c how to increase/decrease height of UITableViewCell on click of provided button on Celll

I have UItable view cell on which there is a button.when I click on the that button particular
cell should increase and display its 8 labels and when i click again on button it should get its original shape.initially i want to display only two labels.
can anyOne help me how should I proceed.
and I have tried like I created customized cell with 8 labels and one button.
I am trying to display cell with 8 labels when button is click otherwise with two.which is not happening.
Thanks
If you want to reload a cell in your UITableView, use the following code:
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationNone];
This will cause both your tableView:heightForRowAtIndexPath: and tableView:cellForRowAtIndexPath: methods to be called with the appropriate indexPath before the corresponding cell redraws. Make sure you keep track of whether the cell at that index path should be expanded or contracted (don't store that information in the cell itself, since you'll be creating a new cell), and respond accordingly.
The method linked to the button on cell should be like this :
- (IBAction)myMethod:(id)sender;
In its implementation you could try this :
UIButton *button=sender;
UITableViewCell *cell=[button superview]; //this should get you the contentView OR the UITableViewCell
//now you can increase cell to display all its content
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
[cell setFrame:yourFrame];
[UIView commitAnimations];
I'm not sure that [button superview] get the table cell or the property contentView of the cell because now i cannot try this code.

Resources