How to simultaneously animate a cell and table change in iOS? - ios

I am trying to simultaneously animate a custom UITableViewCell and the UITableView that contains it.
When clicked, the subviews of the UITableViewCell slightly re-arrange such that the height of the cell increases. I want the re-arrangement within the cell to happen concurrently with the resizing of the UITableView's slot for that cell, so that it doesn't overlap with the cell below it.
When clicked again, the reverse is to happen.
This is what I've tried so far.
The UITableView
When the UITableView is clicked, I use didSelectRowAtIndexPath to update a selectedPath property:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (self.selectedPath && indexPath.row == self.selectedPath.row) {
self.selectedPath = nil;
} else {
self.selectedPath = indexPath;
}
[tableView reloadData];
}
Note, it calls reloadData, which triggers each visible cell to re-fetch the prototype and configure it based on whether it is selected or not:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
QueueItemTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"QueueCell" forIndexPath:indexPath];
[cell setImage:[UIImage imageNamed:[self.imageList objectAtIndex:indexPath.row]]];
if (self.selectedPath && indexPath.row == self.selectedPath.row) {
[cell makeSelected:YES];
} else {
[cell makeSelected:NO];
}
return cell;
}
- (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*) indexPath {
CGFloat height = 210;
if (indexPath.row == [self.imageList count] - 1) {
height += 10;
}
if (self.selectedPath && indexPath.row == self.selectedPath.row) {
height += 35;
}
return height;
}
The UITableViewCell subclass
In the custom cell class, its animation happens when it is made selected or not selected:
- (void)makeSelected:(BOOL)selected {
if (selected) {
[UIView animateWithDuration:0.5 animations:^{
self.customImage.frame = CGRectMake(5, 5, 310, 210);
}];
} else {
[UIView animateWithDuration:0.5 animations:^{
self.customImage.frame = CGRectMake(10, 10, 300, 200);
}];
}
}
What is happening
The table view immediately snaps to the new the allotted height for the cell, and then the cell's contents slowly animate to the new state. I want the two things to happen concurrently, and smoothly.

You might want to call
[UIView animateWithDuration:0.5 animations:^{
[self.tableView reloadData];
}];
and re-write the custom cell as following:
- (void)makeSelected:(BOOL)selected {
if (selected) {
self.customImage.frame = CGRectMake(5, 5, 310, 210);
} else {
self.customImage.frame = CGRectMake(10, 10, 300, 200);
}
}
I hope it helps.

try this... reload particular cell insteade
NSIndexPath* indexPath1 = [NSIndexPath indexPathForRow:selectedRowIndexPath inSection:section];
// Add them in an index path array
NSArray* indexArray = [NSArray arrayWithObjects:indexPath1, nil];
// Launch reload for the two index path
[self.tableView reloadRowsAtIndexPaths:indexArray withRowAnimation:UITableViewRowAnimationFade];

[self.tableView beginUpdates];
[self.tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates];
You need to reload particular cell while tap use like this..
- (void)makeSelected:(BOOL)selected {
if (selected) {
self.customImage.frame = CGRectMake(5, 5, 310, 210);
} else {
self.customImage.frame = CGRectMake(10, 10, 300, 200);
}
}
Declare BOOl isSelect; as Global
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (self.selectedPath && indexPath.row == self.selectedPath.row) {
isSelect = NO;
} else {
self.selectedPath = indexPath;
isSelect = YES;
}
[self.tableView beginUpdates];
[self.tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
QueueItemTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"QueueCell" forIndexPath:indexPath];
[cell setImage:[UIImage imageNamed:[self.imageList objectAtIndex:indexPath.row]]];
if (self.selectedPath && indexPath.row == self.selectedPath.row && isSelect) {
[cell makeSelected:YES];
} else {
[cell makeSelected:NO];
}
return cell;
}
- (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*) indexPath {
CGFloat height = 210;
if (indexPath.row == [self.imageList count] - 1) {
height += 10;
}
if (self.selectedPath && indexPath.row == self.selectedPath.row && isSelect) {
height += 35;
}
return height;
}
It reload the cell with animation.. I hope it will help you.. Now you check it will work as you want...

Related

Insert UITableViewCell With Animation and Scroll to it

My requirement is simple , i just need to add a TableCell with rightRowAnimation and scroll to it. It happens as long as i am with within tableView height , as i cross the height of tableView to add cell further , it adds cell but displays no animation when scrolling to it.
Attached is a simple project with a UITableView for reference , Appreciate your help !!
Sample Project with a simple UItableView and Add Button
Code
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return self.dataArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MyCell1"];
BOOL myBool = indexPath.row%2 == 0;
if(myBool){
cell.backgroundColor = [UIColor redColor];
}else{
cell.backgroundColor = [UIColor whiteColor];
}
cell.textLabel.text = [self.dataArray objectAtIndex:indexPath.row];
return cell;
}
-(IBAction)addTapped:(id)sender {
[self.dataArray addObject:#"New Object"];
// [_tableView beginUpdates];
[_tableView insertRowsAtIndexPaths:#[[NSIndexPath indexPathForRow:self.dataArray.count-1 inSection:0]] withRowAnimation:UITableViewRowAnimationRight];
// [_tableView endUpdates];
[_tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:self.dataArray.count-1 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}
Use bellow method for the animation.
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
cell.alpha = 0;
cell.layer.transform = CATransform3DMakeScale(0.5, 0.5, 0.5);
[UIView animateWithDuration:0.7 animations:^{
cell.alpha = 1;
cell.layer.transform = CATransform3DScale(CATransform3DIdentity, 1, 1, 1);
}];
}
change what ever your requirements
you can try this to animate row put in table.
-(void)viewWillAppear:(BOOL)animated
{
dispatch_async(dispatch_get_main_queue(), ^{
[UIView transitionWithView:yourtablename
duration:5.1f
options:UIViewAnimationOptionTransitionFlipFromTop
animations:^(void) {
[yourtablename reloadData];
} completion:NULL];
});
}
also you can change animation style.

How top expand collapse custom cell tableview and expanding the cell must be dynamic height in iOS objective c

How top expand collapse custom cell tableview and expanding the cell must be dynamic height in iOS objective c?
viewcontroller having custom tableview cells when click on the cell,cell must be expand/collapse having one view and display data in that view and height must be dynamic
You'll have to maintain a state (expanded/not expanded) for the custom table view cell. Every time it's tapped you make the necessary changes in the UI and toggle the state. You can then call
reloadData()
or
-(void)reloadRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths
withRowAnimation:(UITableViewRowAnimation)animation;
You can also calculate and set the new height of the cell and the reload function will take care of the animation.
You used tableview then easy manage expand and collapse custom cell tableview and expanding with animation.
Follow code for expand and collapse.
.h File
BOOL currentlyExpanded;
NSMutableIndexSet *expandedSections;
.m File
- (void)viewDidLoad
{
if (!expandedSections)
{
expandedSections = [[NSMutableIndexSet alloc] init];
}
}
Use Tableview Delegate and Datasource method..
#pragma mark - Tableview Delegate -
- (BOOL)tableView:(UITableView *)tableView canCollapseSection:(NSInteger)section
{
return YES;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if ([self tableView:tableView canCollapseSection:section])
{
if ([expandedSections containsIndex:section])
return 6; //return your array count..
else
return 1;
}
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *MyIdentifier = #"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier]
;
}
if ([self tableView:tableView canCollapseSection:indexPath.section])
{
//Display your dynamic cell contain..
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([self tableView:tableView canCollapseSection:indexPath.section])
{
NSInteger section = indexPath.section;
currentlyExpanded = [expandedSections containsIndex:section];
NSInteger rows;
if (currentlyExpanded)
{
rows = [self tableView:tableView numberOfRowsInSection:section];
[expandedSections removeIndex:section];
}
else
{
[expandedSections addIndex:section];
rows = [self tableView:tableView numberOfRowsInSection:section];
}
// Animation when cell expand and collapse
if(currentlyExpanded)
{
[tableView deleteRowsAtIndexPaths:tmpArray
withRowAnimation:UITableViewRowAnimationTop];
CGFloat startRadians, endRadians;
startRadians = M_PI/2;
endRadians = 0.0f;
btnArrow.layer.affineTransform = CGAffineTransformMakeRotation(startRadians);
[UIView animateWithDuration:0.3f animations:^{
btnArrow.layer.affineTransform = CGAffineTransformMakeRotation(endRadians);
}completion:^(BOOL finished){
}];
}
else
{
[tableView insertRowsAtIndexPaths:tmpArray
withRowAnimation:UITableViewRowAnimationTop];
[UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
[btnArrow setTransform:CGAffineTransformRotate(btnArrow.transform, M_PI/2 )];
}completion:^(BOOL finished){
}];
}
}
}

expanded UITableviewCell height not manageable

I am using this in my app and i am create two identifiers for UITableview one is "normal cell" and another one is "expended cell" which will show when someone tap on a "normal cell". my problem is this that I can not manage heights of both cells separately for example I want normal cell height to be 120 and extended cell is to be 60. But if I change height in heightForRowAtIndexPath then both cells showing same height. here is my code.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
FSParallaxTableViewCell *cell = nil;
static NSString *cellIdentifier = nil;
if ([indexPath isEqual:self.expandedIndexPath]) {
cellIdentifier = #"ExpandedCell";
}
else {
cellIdentifier = #"NormalCell";
}
cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
if (cell == nil) {
cell = [[FSParallaxTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
if ([[cell reuseIdentifier] isEqualToString:#"ExpandedCell"]) {
cell.contentView.backgroundColor = [UIColor grayColor];
}
if ([[cell reuseIdentifier] isEqualToString:#"NormalCell"]) {
[cell.cellImageView sd_setImageWithURL:[NSURL URLWithString:[[rssOutputData objectAtIndex:indexPath.row]xmllink]]
placeholderImage:[UIImage imageNamed:#"placeholder"] options:indexPath.row == 0 ? SDWebImageRefreshCached : 0];
cell.clipsToBounds = YES;
}
return cell;
}
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// disable touch on expanded cell
UITableViewCell *cell = [self.theTableView cellForRowAtIndexPath:indexPath];
if ([[cell reuseIdentifier] isEqualToString:#"ExpandedCell"]) {
return;
}
// deselect row
[tableView deselectRowAtIndexPath:indexPath
animated:NO];
// get the actual index path
indexPath = [self actualIndexPathForTappedIndexPath:indexPath];
// save the expanded cell to delete it later
NSIndexPath *theExpandedIndexPath = self.expandedIndexPath;
// same row tapped twice - get rid of the expanded cell
if ([indexPath isEqual:self.expandingIndexPath]) {
self.expandingIndexPath = nil;
self.expandedIndexPath = nil;
}
// add the expanded cell
else {
self.expandingIndexPath = indexPath;
self.expandedIndexPath = [NSIndexPath indexPathForRow:[indexPath row] + 1
inSection:[indexPath section]];
}
[tableView beginUpdates];
if (theExpandedIndexPath) {
[theTableView deleteRowsAtIndexPaths:#[theExpandedIndexPath]
withRowAnimation:UITableViewRowAnimationNone];
}
if (self.expandedIndexPath) {
[theTableView insertRowsAtIndexPaths:#[self.expandedIndexPath]
withRowAnimation:UITableViewRowAnimationNone];
}
[tableView endUpdates];
// scroll to the expanded cell
[self.theTableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle
animated:YES];
}
can anyone please help me resolving this issue I want to set height for both cells separately.
add below code in heightForAtIndexpath method
if ([indexPath isEqual:self.expandedIndexPath]) {
return 60.0;
}
else
return 120.0f;
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
}
if ([[cell reuseIdentifier] isEqualToString:#"ExpandedCell"]) {
return 60;
}
if ([[cell reuseIdentifier] isEqualToString:#"NormalCell"]) {
return 120;
}
}
You have to set the height of table view cell separately. you can set the height separately according as the row.In following code i have set the 1st row height 35, 2nd row height 70 and rest of the row will have height 65.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
switch (indexPath.row)
{
case 0:
return 35;
break;
case 1:
return 70;
break;
default:
return 65;
break;
}
}

Show/Hide custom class elements when uitableviewcell is selcted

I am new to iOS development. I have doubt related to UITableViewCell height.
I am using one tableview, I have taken prototype cell in storyboard. The cell height I have given is 75. But what I need is when I select cell height will be increase and show 1 button (which is in black color in the image). The button is declared in UITableViewCell's custom class. Below of that image I have one label. If button is showing I need to place the label at the bottom of button or else in the place of button I need to show that label.
Thanks in advance.......
You can use [tableView beginUpdates] and [tableView endUpdates];
for Ex:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self hideControlMethodsTable];//Declare method to hide when button tableview loads initially
[tableList beginUpdates];
[tableList deselectRowAtIndexPath:indexPath animated:YES];
CellRes = (ReservationTableViewCell*)
[tableList cellForRowAtIndexPath:indexPath];
if (cellSelectedFirstTime == true) {
self.selectedRow = indexPath.row;
[self showControlsMethodsTable];
cellSelectedFirstTime = false;
}
else{
if(self.selectedRow == indexPath.row){
self.selectedRow = -1;
[self hideControlMethodsTable];
}
else{
self.selectedRow = indexPath.row;
[self showControlsMethodsTable];
}
}
[tableList endUpdates];
}
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if(openForFirstCell == true){
if (cellSelectedFirstTime==true) {
CellRes = [UIColor lightGrayColor];
return 180.;
}
return 60;
}
}
Hope this helps you.

Animating UITableView update, succeeded but needs more detail

I want to show animation when add cells to UITableView.
Here's is what I implemented (pseudo code)
[self.tableView beginUpdates];
// remove row exists
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:(rows exists) withRowAnimation:UITableViewRowAnimationFade];
(chang data source here, for me, it's NSFetchedResultsController)
// insert new rows
[self.tableView insertRowsAtIndexPaths:(new rows) withRowAnimation:UITableViewRowAnimationFade];
[self.tableView endUpdates];
This code shows animation well, but it has a small problem.
The cells are shows moving animation from frame rect (0, 0, 0, 0) to it's actual position, not only fading animation.
I think problem is that initial frame of cells are (0, 0, 0, 0), so I set up initial frame property of cell in cellForRowAtIndexPath, but it does not work.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
....
cell.frame = CGRectMake(0, indexPath.row * 64, 320, 64);
NSLog(#"set frame");
....
}
How can I show shade anmation only, with no cell moving animation?
The code is untested, but the idea should work:
BOOL animateRowsAlpha = NO;
- (void)reloadData {
[UIView animateWithDuration:0.2
animations:^{
for (UITableViewCell *cell in self.tableView.visibleCells) {
cell.alpha = 0.0f;
}
} completion:^(BOOL finished) {
animateRowsAlpha = YES;
[self.tableView reloadData];
}
];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"Cell";
UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell)
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
if(animateRowsAlpha)
cell.alpha = 0.0;
return cell;
}
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
if (!animateRowsAlpha) {
return;
}
[UIView animateWithDuration:0.2
animations:^{
cell.alpha = 1.0f;
}];
NSArray *indexPaths = [tableView indexPathsForVisibleRows];
NSIndexPath *lastIndexPath = [indexPaths lastObject];
if(!lastIndexPath || [lastIndexPath compare:indexPath] == NSOrderedSame) {
animateRowsAlpha = NO;
}
}

Resources