Anyone have a walk around on animating the process when switching tabs?
I am currently doing this with 2 issues.
1: It messes up my UIControl colors.
2: It switches the tab first, thereafter perform the animation.
I want to implement something like the effect when pushing a view to navigation stack.
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1.0];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:bookingVC.view cache:YES];
[UIView commitAnimations];
[self.tabBarController setSelectedIndex:0];
Right now I am doing this, which doesn't have any animation effect.
NSArray *tabBarVC = [self.tabBarController viewControllers];
UINavigationController *firstTabNC = [tabBarVC objectAtIndex:0];
BookingViewController *bookingVC = (BookingViewController *)[[firstTabNC viewControllers] objectAtIndex:0];
[bookingVC setNSStringProperty:newString]; //this string will be displayed on a UITextField whenever viewDidAppear;
// So, I need some animation here when I switch tabs to make it more obvious that the UITextField is updated.
[self.tabBarController setSelectedIndex:0];
I am totally clueless on creating my own animation, please do guide me along. I am opened to ideas to better the presentation.
Thanks.
Any reason you need to use the pre-iOS4 way of animating? Animation blocks simplify this:
[UIView animateWithDuration:1.0
delay:0
options:UIViewAnimationOptionTransitionCurlUp
animations:
^{
// show your desired view however you do it
}
completion:
^(BOOL finished) {
[self.tabBarController setSelectedIndex:0];
}];
EDIT: Sorry, I didn't pick up you were doing a view transition somehow.. silly. There's another block-based method for that case:
[UIView transitionWithView:bookingVC.view
duration:1.0
options:UIViewAnimationOptionsTransitionCurlUp
animations:
^{
// do view transitioning here
}
completion:
^(BOOL finished) {
[self.tabBarController setSelectedIndex:0];
}];
EDIT 2: Alright, so you seem to need some help with the context of all this. You should be animating changes to active tabs in the UITabBarControllerDelegate protocol (which your custom class would implement). In particular, the tabBarController:didSelectViewController: method.
I'd recommend you first override the tabBarController:shouldSelectViewController: method to make sure that you don't accidentally animate a transition from a tab to the same tab:
- (BOOL)tabBarController:(UITabBarController *)tabBarController
shouldSelectViewController:(UIViewController *)viewController
{
return viewController != [tabBarController selectedViewController];
}
In didSelectViewController:, do the animation. I'm also going to take this opportunity to rework your code, because if you're doing it within this method then the selectedIndex of the tab bar controller is handled automatically, and whatever you were doing with bookingVC.view can be replaced by a direct transition between the active tab controller and the new (selected) one:
- (void)tabBarController:(UITabBarController *)tabBarController
didSelectViewController:(UIViewController *)viewController
{
[UIView transitionFromView:[tabBarController selectedViewController].view
toView:viewController.view
duration:1.0
options:UIViewAnimationOptionsTransitionCurlUp |
UIViewAnimationOptionsShowHideTransitionViews
completion:nil];
}
Note here that I use UIViewAnimationOptionsShowHideTransitionViews as part of your animation options. I'm doing this because our animation is on top of the system already changing the active tab, so we don't want to muck it up by trying to remove the view from the view heirarchy at the same time as the system is.
Try placing your animation sequence in didSelectItem::
- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item;
Then set up a modalView controller and animate the page curl effect from there.
Related
I have a design where I need to swap in and out two tableviews using one viewcontroller (I need the same navigation title to appear for both). So I've created each tableview in its own subclassed tableviewcontroller class, then I've included a class variable for each in my viewcontroller. Each tableview has the viewcontroller as a parent and calls the viewcontrollers swap method when a swap needs to occur. This method and the viewDidLoad method is listed below:
- (void) viewDidLoad
{
[super viewDidLoad];
[[self navigationItem] setTitle: AddAPhotoViewControllerTitle];
SelectAnAlbumTableViewController *selectAnAlbumTableViewControllerTemp = [[SelectAnAlbumTableViewController alloc] initWithParent: self];
[self setSelectAnAlbumTableViewController: selectAnAlbumTableViewControllerTemp];
[selectAnAlbumTableViewControllerTemp release];
[[self view] insertSubview: [[self selectAnAlbumTableViewController] tableView] atIndex: 0];
}
- (void) switchTableViews
{
if ([[[self selectAnAlbumTableViewController] tableView] superview] == nil)
{
[[self view] insertSubview: [[self selectAnAlbumTableViewController] tableView] atIndex: 0];
[[[self selectAPhotoTableViewController] tableView] removeFromSuperview];
[selectAPhotoTableViewController release];
selectAPhotoTableViewController = nil;
}
else
{
SelectAPhotoTableViewController *selectAPhotoTableViewControllerTemp = [[SelectAPhotoTableViewController alloc] initWithAssetGroup: [[self selectAnAlbumTableViewController] assetGroup] parent: self];
[self setSelectAPhotoTableViewController: selectAPhotoTableViewControllerTemp];
[selectAPhotoTableViewControllerTemp release];
[[self view] insertSubview: [[self selectAPhotoTableViewController] tableView] atIndex: 0];
[[[self selectAnAlbumTableViewController] tableView] removeFromSuperview];
}
I have 2 questions:
1) When I'm doing the swap, I'm inserting the new tableview, animating the transition (I didn't include the animation code to keep it concise), then removing the old tableview from the superview. Is this the correct order / correct way to do this? It works fine, but I'm wondering if there isn't some code smell here.
2) Using this design pattern, what would be the best way to go about putting in an activity indicator that can be displayed while each tableview is loading? I've tried implementing the indicator in the viewcontroller, and it seemed to work ok, but I wasn't sure how to set it's position? In terms of what? The center of? I guess this goes back to the first question I asked to, what is the superview and when, or if there is even a superview?
Just use two UITableViews.
Instantiate them and put them in instance variables. If you need to, save the state i.e. which table view is being displayed.
I see nothing wrong with it. I assume your reason is that each table controller has its own logic as to deserve a separate class. It is a bit unorthodox to embed controllers inside controllers, and you'll have to pass the view lifecycle calls.
Example:
-(void) switch
{
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.75];
[UIView setAnimationDelegate:self];
if ([self.visibleVC isKindOfClass:[OrangeVC class]])
{
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.view cache:YES];
[self.visibleVC viewWillDisappear:TRUE];
[self.visibleVC.view removeFromSuperview];
self.visibleVC = self.appleVC;
[self.view addSubview:self.visibleVC.view];
}
else if ([self.visibleVC isKindOfClass:[AppleVC class]])
{
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.view cache:YES];
[self.visibleVC viewWillDisappear:TRUE];
[self.visibleVC.view removeFromSuperview];
self.visibleVC = self.orangeVC;
[self.view addSubview:self.visibleVC.view];
}
[self.visibleVC viewWillAppear:TRUE];
[UIView commitAnimations];
}
Note the viewWillAppear calls, you need at least that to wake up the table. I'm not sure if you should call viewWillDisappear, but it doesn't hurt. If you don't, watch it in instruments in case the controller is not cleaning up properly.
You can add any activity hud in the self.view of the parent controller, use a hud widget, darken the view currently loading, ..., it's a design issue more than technical. Remember to disable the user interaction while you load (userInteractionEnabled=NO) on the parent view and the button that initiated the switch.
How can I modify the animation for dismiss?
for present, I've used :
SlideShow *slider = [[SlideShow alloc] initWithNibName:#"SlideShow" bundle:nil];
slider.view.alpha = 0.0;
[self presentModalViewController: slider animated: NO];
[UIView beginAnimations: nil context: nil];
[UIView setAnimationDuration:1.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
slider.view.alpha = 1.0;
[UIView commitAnimations];
and it works..
But how about a way to dismiss it using a custom animation (I was looking for a Fade-Out animation for dismiss)
Thanks.
You are fading view controllers the old school way, since iOS 3 the easiest and best way to fade a view controller is to set its property: (ex. in the init method)
self.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
Your view controller will then fade nicely in and out.
presentModalViewController is essentially a method that serves up a pre-baked animation for your viewController.view. If you want to make a custom animation for dismissing or presenting a modal view, you have to handle it all on your own.
using the transition, UIModalTransitionStyleFlipHorizontal seems to flip from right to left when initialized and left to right when returning.
Is there any way to make it flip the opposite way?
Try this... transition the views first and when it completes, then present the modal view controller (not animated)
ModalViewController *modalViewController = [ModalViewController alloc] initWithNibName:#"ModalViewController" bundle:nil];
[UIView transitionFromView:self.view toView:modalViewController.view duration:0.75 options:UIViewAnimationOptionTransitionFlipFromLeft completion:^(BOOL finished){
if (finished) {
[self presentViewController:modalViewController animated:NO completion:nil];
}
}];
Not if you're using the modalTransitionStyle property.
If you want to do it you'd probably have to animate it yourself.
These are all the possible transition styles that you can use.
I have a small problem with UINavigationController animation between two view.
My application build more than two view,
first view contains login information, second view contains root menu, last view contains sample data and so on..
My MainWindow.xib contains a UINavigationController component which is contains all navigation structure.
When my login view loaded, i use this lines of code
- (void)viewWillAppear:(BOOL)animated {
[self.navigationController setNavigationBarHidden:YES animated:NO];
}
for hide UINavugationConttoller (I don't need to show to user navigation bar during the login.)
After that when the user execute the login submit button on the login view
i use this code for push the RootmenuView to the UINavigationController's stack.
RootMenuController *rootMenuController = [[RootMenuController alloc] initWithNibName:#"RootMenuController" bundle:0];
[self.navigationController pushViewController:rootMenuController animated:NO];
[rootMenuController release];
It's working very well. And when the Rootmenuview loaded user have to show the navigation bar then i'm showing the UINavigation's tool bar with this code
- (void)viewDidAppear:(BOOL)animated {
[self.navigationController setNavigationBarHidden:NO animated:YES];
}
But i don't like the default animation transitions of UINavigationController then i changed above code with below
[UIView beginAnimations:#"View Flip" context:nil];
[UIView setAnimationDuration:0.50];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationTransition:
UIViewAnimationTransitionFlipFromRight
forView:self.navigationController.view cache:YES];
RootMenuController *rootMenuController = [[RootMenuController alloc] initWithNibName:#"RootMenuController" bundle:0];
[self.navigationController pushViewController:rootMenuController animated:NO];
[UIView commitAnimations];
[rootMenuController release];
It's working too but UINavigationController flickering during between two view naimation transition.
I didn't solve this problem.
Any suggestions ?
Thank you
Have you tried [setAnimationTransition:forView:cache:NO]? I got some odd behavior similar to yours when I used to mess around with UIView animations and used caching.
i have coded following in appDelegeate .m file .but i cant run presentModalViewController method.if i run [self.window addSubview:mview] ,it does not show the result..?any help
to go from one controller to another controller?here mtController is Navigationcontroller.
- (void)flip
{
MViewController *mview = [[MViewController alloc] init];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:2.0];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft
forView:window
cache:YES];
[mtController.view removeFromSuperview];
[self.window addSubview:mview];
// [self presentModalViewController:mailView animated:YES];
[UIView commitAnimations];
[mailView release]
}
If you want to add a NavigationController to a window you are supposed to call
[self.window addSubview:mview.view];
And if you want to go from one view in a NavigationController to another view, the correct thing to do would be to push the new ViewController.
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
In your code sample you create an object called mview, but then below in the presentModalViewController you reference mailView (and in the release). Is that a mistake?
After you add the mview.view to the window, is it the only view on the stack? If not, you might need to bring it to the front. Also, assuming the release statement at the bottom was meant to be [mview release] you're going to have another problem if you don't save/retain that view controller. I don't believe adding it to the window subviews retains it.