I need to switch views by swiping with a curl animation for transition.
I tried PageControl (and other approaches -.-), but it's not what I need for several reasons, so I'll go for the GestureRecogntion, but I stuck.
My problem by now is the architecture. There is the firstVC, calling the SecondVC, onto which I add the subviews (of a third VC) to, which should be swipeable. I don't know if it's possible at all to swipe through subviews from another VC or if it's the code or the IB setup that won't do the job (It's my first time with gesture recogntion)
So by now I just loaded 4 dummy subviews when the secondVC loads. My GR-Code (just for the leftswipe, but rightswipe is more or less the same..)
- (void)handleSwipeFrom:(UISwipeGestureRecognizer *)recognizer {
NSInteger viewToBeShown = 0;
NSString *nextSubviewStr = [NSString stringWithFormat: #"view%d", (viewToBeShown)];
if (recognizer.direction == UISwipeGestureRecognizerDirectionLeft){
if (currentSubview >0) {
viewToBeShown = currentSubview-1;
nextSubviewStr = [NSString stringWithFormat: #"view%d", (viewToBeShown)];
Ubg *nextSubview = [[Ubg alloc] initWithNibName:nextSubviewStr bundle:nil];
[self.view removeFromSuperview];
[self.view addSubview:nextSubview.view];
Could you tell me if that could should basically work (and it's just my IB setup that's not correct)? This is driving me nuts! If you need any other information, just let me know.
Thank you for your time and patience!
This is the code used for curl animation
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration: 1];
//setting animation for the current view
[UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:self.navigationController.view cache:YES];
//Next ViewController to push
nextPage *detailViewController = [[nextPage alloc] initWithNibName:#"nextPage" bundle:nil];
//Push the next viewcontroller to NavigationController
[self.navigationController pushViewController:detailViewController animated:NO];
[detailViewController release];
//Start the Animation
[UIView commitAnimations];
Related
I have a button that, when pressed, presents a view controller to the user. I currently do this using a method like this:
ProjectViewController *myProj = [[ProjectViewController alloc] init];
myProj.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
myProj.modalPresentationStyle = UIModalPresentationFullScreen;
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:myProj];
[self presentModalViewController:navController animated:YES];
[myProj release];
[navController release];
I would like to present this new view to the user as a growing rectangle from the middle of the screen. What is the best way of doing this?
Cheers
Try the undocumented transition style zoomyIn/zoomyOut
If those are not the ones you are looking for, set the frame of the view to the center of the view with 0 width/height and transform it to it's final size and position. Untested sample code:
[UIView beginAnimations:nil context:nil];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:0.7];
yourview.frame = finalFrame;
[UIView commitAnimations];
I want to fade the whole screen (including navigation bar) to black when a user presses a button on a uinavigationcontroler, before showing a new view. (i don't want to push this new view, for various reasons).
How would I achieve this?
EDIT
Thanks to Mac and Eiko, I have figured it out. Here's the code I used. Not sure if it is optimal, but it does the trick.
// this is called from a programmatically constructed button.
// change (void) to (IBAction) if linking from IB.
- (void)fadeAndShow:(id)sender
{
// blackView is a #property which has been #synthesize-d
// do I really need to alloc and init this?
blackView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
blackView.alpha = 0.0;
[blackView setBackgroundColor:[UIColor blackColor]];
[self.navigationController.navigationBar.superview addSubview:blackView];
[UIView beginAnimations:#"fadeAway" context:NULL];
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:0.75];
[UIView setAnimationDidStopSelector:#selector(showNewScreen:finished:context:)];
blackView.alpha = 1.0;
[UIView commitAnimations];
}
-(void)showNewScreen:(NSString *)animationID finished:(BOOL)finished context:(void *)context
{
// I guess you could fade in somewhere in the new view controller.
// don't know how to fade back in this view tho... viewDidAppear?
NewViewController *controller = [[NewViewController alloc] initWithNibName:#"NewView" bundle:nil];
[self.navigationController setNavigationBarHidden:YES];
controller.hidesBottomBarWhenPushed = YES;
[[self navigationController] pushViewController:controller animated:NO];
[blackView removeFromSuperview];
[controller release];
}
Off the top of my head (I haven't actually tested the following at all):
-(IBAction) buttonClicked:(id) sender
{
[UIView beginAnimations:#"myAnimation" context:nil];
[UIView setAnimationDuration:ANIMATION_DURATION];
blackView.alpha = 1.0;
[UIView commitAnimations];
}
Create a UIView in the navigationbar's superview (which I'm assuming is window-sized) that is the same size as the window.
Set that view's backgroundColor to [UIColor blackColor], and its alpha to 0.0.
In your button handler do something like the above (assuming your new UIView is blackView and ANIMATION_DURATION is your desired animation time in seconds).
Then, add your new view on top.
EDIT: too quick for me Eiko! Also, code at the top since the ordered list seems to screw around with the code formatting - sorry the answer reads a little odd.
You can add a black coloured UIView in screen size on top of your current view, and animate its alpha from 0 to 1. When the animation is done, add your new view. You can remove the black one then. Animate from 1 to 0 for the opposite effect - going from black to the content).
I have a seachButton in the navigation bar which upon hitting calls following method:
- (IBAction)search:(id)sender
{
if (nil == searchViewController)
searchViewController = [[SearchViewController alloc] initWithNibName:#"SearchViewController" bundle:nil];
searchViewController.view.backgroundColor = [UIColor clearColor];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlDown
forView:searchViewController.view
cache:NO];
[self.view addSubview:searchViewController.view];
[UIView commitAnimations];
}
It should load SearchViewController.xib which contains a view with UISearchBar and two buttons. When I call the search method for the first time, the view appears very quickly with some weird animation, when I call it again, the animation is alright. Does anyone have a clue what could be wrong?
Add both views to window in appdelegate, I had the same problem you had and this worked. Strange because later on I remove them from the superview but it is still working.
A UIViewController does not load its view until the view method is called. I guess the problem is the view is not loaded when you call the animation first time. You can try to modify you code like this:
if (nil == searchViewController) {
searchViewController = [[SearchViewController alloc] initWithNibName:#"SearchViewController" bundle:nil];
searchViewController.view;
}
Try putting the animation code in the viewDidLoad function. This ensures all assets and views from the nib file have been loaded and are able to be used by your app.
- (IBAction)search:(id)sender
{
if (nil == searchViewController)
searchViewController = [[SearchViewController alloc] initWithNibName:#"SearchViewController" bundle:nil];
[self.view addSubview:searchViewController.view];
}
-(void)viewDidLoad
{
self.view.backgroundColor = [UIColor clearColor];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlDown
forView:self.view
cache:NO];
[UIView commitAnimations];
}
Try putting the code for animations and view loading in the viewDidAppear: method instead of viewDidLoad: (which Chris suggested above).
In general, I have had problems doing view related things in viewDidLoad:. But doing those in viewDidAppear: has always helped (I might be missing some subtlety that causes this behavior).
I have set up a multiview application with two views. The views can be switched using a button in each view (there are two separate actions). I am using the animation UIViewAnimationTransitionFlipFromRight, and when I go from the first to the second view, the view I am going to appears behind the flipping animation. I would like it just to be white. Any help is appreciated.
alt text http://img35.imageshack.us/img35/9982/picture11wu.png
This is the action switching the views:
- (IBAction)switchViewsOne:(id)sender
{
if (self.uLViewController == nil)
{
ULViewController *uLController =
[[ULViewController alloc]
initWithNibName:#"ULView"
bundle:nil];
self.uLViewController = uLController;
[uLController release];
}
[UIView beginAnimations:#"View Flip" context:nil];
[UIView setAnimationDuration:1.25];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
UIViewController *comming = nil;
UIViewController *going = nil;
UIViewAnimationTransition transition;
if (uLViewController.view.superview == nil)
{
comming = uLViewController;
going = mainViewController;
transition = UIViewAnimationTransitionFlipFromLeft;
}
[UIView setAnimationTransition: transition forView:self.view
cache:YES];
[comming viewWillAppear:YES];
[going viewWillDisappear:YES];
[going.view removeFromSuperview];
[self.view insertSubview: comming.view atIndex:10];
[going viewDidDisappear:YES];
[comming viewDidAppear:YES];
[UIView commitAnimations];
}
You could try using addSubView which just adds it to the top of the stack.
This kind of bug can be if comming.view is nil
[self.view insertSubview: comming.view atIndex:10];
Check, maybe your nib isn't loaded properly
ULViewController *uLController = [[ULViewController alloc] initWithNibName:#"ULView" bundle:nil];
NSLog(#"Loaded controller %#:", uLController);
I'm using the PageControl project, which is on Apple's dev site. I've added a flip view to the project and an info icon to the top right of each view/page. For some reason, only the first page is able to animate the flipping. Page 2 on still shows the flipped page but does not animate. To make sure it isn't anything special about page 1, I switch page 1 and 2 and that worked fine. Page 2 in position 1 animated while Page 1 in position 2 did not. Any ideas why this would happen or how I can trouble shoot it?
I did take a look at this thread, which seems to be the same issue: Flip View Iphone. However, My flipview is a UIViewController and so is the class with the info icon on it. In the other thread, they are using UIViews.
I did implement the showInfo code from the above thread. When on Page 2, I see no flip. Then I scroll over to Page 1 and see it has flipped. Not sure why it isn't staying with Page 2. When on Page 1, it doesn't animate the flip. The flipview just suddenly appears.
Do you have a containerView? Something that can be there so you can add and remove subviews from it? Animation can break if you have two viewControllers, one coming and one going, without a containerView. I use a rootViewController and animate all my pages to and from each other with the rootViewcontroller in the back. Here is my code for flipping, you'll probably have to do a little editing to make it work for you:
(keep in mind that self is the rootViewcontroller, a viewcontroller with a blank view (color it so it matches your views))
- (void)switchTwoViews:(UIViewController *)view1 otherView:(UIViewController *)view2
{
/*
This method is called to switch views.
It flips the displayed view from the main view to the flipside view and vice-versa.
*/
UIViewController *coming = nil;
UIViewController *going = nil;
UIViewAnimationTransition transition;
[view1.view setUserInteractionEnabled: NO];
[view2.view setUserInteractionEnabled: NO];
if (view1.view.superview == nil) {
coming = view1;
going = view2;
transition = UIViewAnimationTransitionFlipFromLeft;
}
else {
coming = view2;
going = view1;
transition = UIViewAnimationTransitionFlipFromRight;
}
// in some cases the following is needed to size the view
// coming.view.frame = [UIScreen mainScreen].applicationFrame;
// going.view.alpha = 1.0; //uncomment these lines if we want fading of views
// coming.view.alpha = 0.0;
NSArray *viewArray = [[NSArray alloc] initWithObjects:coming, going, nil];
[coming viewWillAppear:YES];
[going viewWillDisappear:YES];
[UIView beginAnimations:#"View Flip" context:viewArray]; {
[UIView setAnimationDuration:1.0];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(animationDidEnd:finished:context:)];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
// coming.view.alpha = 1.0; //uncomment these lines if we want fading of views
// going.view.alpha = 0.0;
[UIView setAnimationTransition:transition forView:self.view cache:YES];
[self.view addSubview: coming.view];
}
[UIView commitAnimations];
}
- (void) animationDidEnd:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context
{
NSArray *viewArray = context;
[((UIViewController *)[viewArray objectAtIndex:1]).view removeFromSuperview];
[[viewArray objectAtIndex:1] viewDidDisappear:YES];
[[viewArray objectAtIndex:0] viewDidAppear:YES];
[[[viewArray objectAtIndex:0] view] setUserInteractionEnabled: YES];
[viewArray release];
}