I am writing an app that needs to display a series of approximately 10-20 'views'. I have 4 view controllers and nibs that I would like to use. Each view has a forward and back button on it and the views should slide in either from the right or the left depending on the button pushed. I want to be able to reuse the nibs and controllers to present the information. I was trying to use a uinavigation controller, but ran into the problem that you can't push a view onto the stack more than once. The overall structure is a uinavigationcontroller within a tabbarcontroller. Is there a way to do this with a uinavigation controller, or should I try a different approach.
I would suggest making a container view controller class. It would create and "own" the four different view controllers you want to use. Then use something like this to switch between them:
// get the view that's currently showing
UIView *currentView = self.view;
// get the the underlying UIWindow, or the view containing the current view view
UIView *theWindow = [currentView superview];
// remove the current view and replace with newView
[currentView removeFromSuperview];
[theWindow addSubview:newView];
// set up an animation for the transition between the views
CATransition *animation = [CATransition animation];
[animation setDuration:0.5];
[animation setType:kCATransitionPush];
[animation setSubtype:kCATransitionFromLeft];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[[theWindow layer] addAnimation:animation forKey:#"SwitchToView1"];
(stolen from here)
Related
I am using the following code to launch a view controller named secondViewController.
[self.navigationController pushViewController:secondViewController animated:YES];
The code successfully causes the secondVC to slide in from the right to left
After the user is done I would like the user to be able to go back to the first View Controller. For this purpose I have wired a back button to a method that uses similar code, however in this case I would like it to slide from left to right, i.e. the opposite direction. However, not surprisingly the return VC also goes from right to left.
[self.navigationController pushViewController:returnViewController animated:YES];
Is there a way to reverse the direction so that in the second case, it slides from left to right?
EDIT:
Using the code from the answer suggested by Brendan, I have added the following method to override the pushViewController. I am calling it the same way but have had to comment the swapButtonsForViewController as the selector SwapButtons is not recognized. Not sure what it really does.
In addition, if you call it as super, I get an error: no visible#interface in the super VC for this VC. Not sure how to fix that. If I change super to self, error disappears but it still goes right to left.
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated{
UIView *theWindow = self.view ;
if( animated ) {
CATransition *animation = [CATransition animation];
[animation setDuration:0.45f];
[animation setType:kCATransitionPush];
[animation setSubtype:kCATransitionFromLeft];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]];
[[theWindow layer] addAnimation:animation forKey:#""];
}
//make sure we pass the super "animated:NO" or we will get both our
//animation and the super's animation
[super pushViewController:viewController animated:NO];
// [self swapButtonsForViewController:viewController];
}
Oops, a few things in addition to my comment:
Did you inherit from UINavigationController? That will help, if you didn't do that already.
Also, the link I shared with you will replace the direction for both cases, unfortunately. I should have read the question more carefully, apologies.
Good news though! Try both of these:
https://stackoverflow.com/a/16535931/5806860
https://stackoverflow.com/a/16384808/5806860
Those are similar solutions, but have minor changes that could potentially solve your problem.
I'm trying to add a sub view with Core-Animation using the attached code.
First time it happens as expected, but after that there's a flash of white in the place of the sub-view before it's fully pushed.
// Add the picker
viewToPush.frame = CGRectMake(0,185,320, 258);
CATransition *animation = [CATransition animation];
[animation setType:kCATransitionMoveIn];
[animation setSubtype:kCATransitionFromTop];
[self.view addSubview:viewToPush];
[viewToPush.layer addAnimation:animation forKey:nil];
btw, in order to remove the subView I just use
[viewToRemove removeFromSuperview];
10x
Why do you add the animation to the viewToPush's layer, not the super view's? I suspect the layer of viewToPush is not stable as you remove the view from the super view. Do you have many views that can act as viewToPush or viewToRemove so they have to be dynamically allocated? Otherwise I would just change their hidden properties to implement such animations.
I am using the following code to popping to a parent view controller (not always the direct parent in the stack), but for some reason I get the current view controller slide in over itself before the parent I am popping to.
CATransition* transition = [CATransition animation];
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromLeft;
[self.navigationController.view.layer addAnimation:transition forKey:kCATransition];
[self.navigationController popToViewController:vc animated:YES];
hasPopped = YES;
This appears to be down to the animation code Im using. The only reason I am setting this is because when the app is rotated to landscape the views come in from the bottom on the side. As raised in this question: https://stackoverflow.com/questions/4102345/why-do-views-slide-out-at-the-bottom-when-landscape
I solved this by turning the animated:off during the pop as the assigned animation was providing it
Hai all,
in my iphone application, when i click a UIButton it will show a UIDatePicker (using setVisible:YES) ,is there any way to animate the DatePicker appearance,(now when the user taps it will suddenly appear in the UI)
thanks in advance
Yes , it is possible to have an animation when you call your picker to set visible.
Initially your picker is hidden. When UIButton is pressed You just call below method (animatePicker).
In below method there is just hidden set to false for pickerview but with CAanimation.
-(void)animatePicker
{
CATransition *animation = [CATransition animation];
[animation setDelegate:self];
// Set the type and if appropriate direction of the transition,
[animation setType:kCATransitionMoveIn];
[animation setSubtype:kCATransitionFromTop];
// Set the duration and timing function of the transtion -- duration is passed in as a parameter, use ease in/ease out as the timing function
[animation setDuration:0.4];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]];
[[PickerView layer] addAnimation:animation forKey:#"transitionViewAnimation"];
PickerView.hidden = FALSE;
[[PickerView layer] removeAnimationForKey:#"transitionViewAnimation"];
animation = nil;
}
Note: Please include Quartz framework(QuartzCore.framework) and import its header file( QuartzCore/QuartzCore.h) to your controller.
A good idea is to bring it up like any other keyboard. Start it offscreen. Start an animation, set it to a position onscreen, then commit the animation. Otherwise you can do any other crazy view animation you want to do. Fade in, other slide animations, expand into view perhaps?
I am facing problems in flipping views in iPhone.
I have two views in appDelegate. I want to flip them once user clicks on a button.
I have the following code:
CATransition *transition = [CATransition animation];
transition.duration = 0.75;
[transition #"twist"];
[transition setSubtype:#"fromRight"];
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[transition setFillMode:#"extended"];
[[window layer] addAnimation:transition forKey:nil];
[window addSubview:self.s.view];
[CATransaction commit];
But this is not working. Do anybody knows a better way to flip the views on window side.
What I am doing is calling the method from appDelegate in the respective viewControllers to flip the views.
If you're using the 3.0 SDK and all you want is a simple flip transition (ala the Weather app) then you don't need to go down to CATransition. The higher-level UIView animation transitions will do what you want but with 3.0 there is an even easier way: simply present your new view as a modal view controller and set the modal transition style to flip. From within the first controller:
UIViewController *controllerForSecondView = ..;
controllerForSecondView.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:controllerForSecondView animated:YES];
Flip back again by using dismissModalViewController.
Documentation Reference
#Luke - thanks, this sample helped me...1 correction though (based on UIViewController.h)
UIViewController *controllerForSecondView = ..;
controllerForSecondView.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:controllerForSecondView animated:YES];
From the header file comments:
// Defines the transition style that will be used for this view controller when it is presented modally. Set this property on the view controller to be presented, not the presenter.
// Defaults to UIModalTransitionStyleSlideVertical.
#property(nonatomic,assign) UIModalTransitionStyle modalTransitionStyle
See The Elements sample code. Particularly AtomicElementViewController -flipCurrentView.