Reputation: 1993
I have an UITableView with sections in my iPhone application where it looks as something similar to viewing a contact details in standard contacts app. In one of the sections I have a UISegmentedControl set as a header of the section and the items in that section depend on what segment is selected in the segmented control. What I wanted to do is to have animations shifting the rows of one tab out of the view to one side and shifting the rows of another tab in from the other side. I have managed to achieve this by inserting/deleting the respective rows with default UITableView's animations for that but it looks a bit weird when the number of rows in one tab is different from the other one. Also the code for that is quite nasty.
Here's the code I have (simplified a bit):
[self.tableView beginUpdates];
UITableViewRowAnimation delAnim = UITableViewRowAnimationRight;
UITableViewRowAnimation insAnim = UITableViewRowAnimationLeft;
NSUInteger numdel = [self.list count];
NSUInteger numins = [newlist count];
NSMutableArray* indices = [NSMutableArray arrayWithCapacity: numdel];
for (NSUInteger i = 0; i < numins; i++)
{
[indices addObject: [NSIndexPath indexPathForRow: i inSection: SECT]];
}
[self.tableView insertRowsAtIndexPaths: indices withRowAnimation: insAnim];
[indices removeAllObjects];
for (NSUInteger i = 0; i < numdel; i++)
{
[indices addObject: [NSIndexPath indexPathForRow: i inSection: SECT]];
}
[self.tableView deleteRowsAtIndexPaths: indices withRowAnimation: delAnim];
self.list = newlist;
[self.tableView endUpdates];
I'm fairly new to Objective C and Cocoa, so any advices are very welcome.
Upvotes: 1
Views: 919
Reputation: 11156
You could try using a separate table view which you animate in directly. The snippet here is just typed off-the-cuff, so might need some work, but it should give you some pointers at least:
- (void) switchToNewTableFromRight
{
UITableView * newTableView = [[UITableView alloc] initWithFrame: self.tableView.frame style: self.tableView.style];
// put it off to the right of the existing table
CGRect frame = newTableView.frame;
frame.origin.x += frame.size.width;
newTableView.frame = frame;
// set data for new table
// you should ensure you're setup to supply data for the new table here, btw
newTableView.delegate = self;
newTableView.dataSource = self;
[newTableView reloadData];
// add to parent of current table view at this (offscreen) location
[self.tableView.superview addSubview: newTableView];
// now we animate
[UIView beginAnimations: @"TableFromRight" context: newTableView];
// set the function it should call when the animation completes
[UIView setAnimationDelegate: self];
[UIView setAnimationDidStopSelector: @selector(animation:finished:context:)];
// set new table's frame to current table's frame
newTableView.frame = self.tableView.frame;
// set current table's frame to be offscreen to the left
frame = self.tableView.frame;
frame.origin.x -= frame.size.width;
self.tableView.frame = frame;
// commit the animations to start them going
[UIView commitAnimations];
}
- (void) animation: (NSString *) animationID finished: (BOOL) finished context: (void *) context
{
// could be a good idea to check that finished == YES here
UITableView * newTableView = (UITableView *) context;
self.tableView = newTableView;
// newTableView has been inited but not autoreleased, etc.
// now the controller (self) owns it, so release that first reference
[newTableView release];
}
The idea here is that you setup the new table (making it the same size as the existing one), place it offscreen to the right of the existing table, and then animate the movement of both tables left by their width. This way the existing table will shift offscreen while the new one will shift onscreen. When the animation completes it will call the supplied method, giving you the opportunity to make the new table view the official table view.
Another option would be to use a flip transition, which might go something like this:
// setup new table
UITableView * newTableView = [[UITableView alloc] initWithFrame: self.tableView.frame style: self.tableView.style];
newTableView.delegate = self;
newTableView.dataSource = self;
[newTableView reloadData];
[UIView beginAnimations: nil context: NULL];
[UIView setAnimationDuration: 1.0];
[UIView setAnimationTransition: UIViewAnimationTransitionFlipFromRight forView: self.tableView.superview cache: YES];
// generally here you'd remove the old view and add the new view
// I'm *assuming* that UITableViewController's -setTableView: will do the same thing
self.tableView = newTableView;
[UIView commitAnimations];
Hopefully one of those will have the desired effect.
Upvotes: 3