13

I am working on one iPhone application in which I implemented one animation UIViewAnimationTransitionFlipFromLeft. Here my application works fine in the Portrait mode. It is doing the same animation as specified means Flip from Left to Right.

But when I am doing this UIViewAnimationTransitionFlipFromLeft in landscape mode then it is not rotating from left to right. Instead of it is rotating from top to bottom. This is really critical issue. Can you help me out to solve this.

The code I am using for iPhone application to rotate the view is as follows:

   CGContextRef context = UIGraphicsGetCurrentContext();
    [UIView beginAnimations:nil context:context];
    [UIView setAnimationTransition: UIViewAnimationTransitionFlipFromLeft forView:self.view.window cache:NO];
    [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
    [UIView setAnimationDuration:1.0];
    [UIView commitAnimations];
    [self.navigationController pushViewController:objSecond animated:YES];

Thanks, Best Regards, Gurpritsingh Saini

AppAspect
  • 4,461
  • 2
  • 30
  • 46
  • Are you sure your application supports landscape orientation? From what you describe, it sounds like your app does a FlipFromLeft in portrait mode irrespective of how you hold the device (landscape or portrait) – Swapnil Luktuke Apr 18 '11 at 14:07
  • Hello, My application supports all the four orientations available in the iPhone. In portrait mode it is working fine fliping animation from left to right. But in ladscape mode instead of flipping left to right it flips from top to bottom. Can you help me to solve the issue. – AppAspect Apr 18 '11 at 16:47
  • can you reformat your code properly? Why are you doing...self.view.window.transform = CGAffineTransformMakeRotation(M_PI * 0.50) – ax123man Apr 18 '11 at 17:32
  • Oh Sorry, That was by mistake. I was just testing with this but not worked. Can you please help me. I need it desperately. – AppAspect Apr 19 '11 at 12:13
  • One point: In your code above, you're using the older UIView method beginAnimations:context:. The context parameter is not a CGContextRef. It's a key that you use to keep track of which animation is which. It's supposed to be an NSString. I would expect passing in a CGContextRef would cause a compiler warning, and it might cause memory management problems, because a CGContextRef is a Core Foundation object, not an NSObject. – Duncan C May 21 '12 at 18:40

5 Answers5

15

If you are using iOS 4.0 or later, the following will do exactly what you want (I just tested it out to make sure)

NewView *myNewView = [[NewView alloc] initWith.....];
[UIView transitionFromView:self.view toView:myNewView.view duration:1 options:UIViewAnimationOptionTransitionFlipFromLeft completion:nil];
//[self.navigationController pushViewController:myNewView animated:NO];
[myNewView release];

EDIT: I'm changing the above code a bit (nothing new, just commenting out the navigation controller because it's not necessary for this).

So there are several ways to go about this (as far as keeping track of the next view), but this is the easiest I can think of. You can already switch from view 1 to 2, so I'm going to explain how to get from 2 to 10 (or however many you need).

Basically, the view transition lasts too long for viewDidLoad to catch a call to go to the next view. So what we need to do is set up a timer that waits and sends a method to switch at a later time. So this is the code you would see in view 2 (and 3 and 4, etc.).

- (void)viewDidLoad {
    // this gets called before animation finishes, so wait;
    self.navigationController.delegate = self;
    // you will need to set the delegate so it can take control of the views to swap them;
    [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(switchView) userInfo:nil repeats:NO];
}

I only wait 1 second until I call the switch method, but if you are loading a lot into your views, you may want to wait a bit longer. 1.5 seconds should be more than enough, but you can play around with that to see where it works and doesn't work.

Next, you have to call the next view in the switchView method.

- (void)switchView {
    NextView *myNextView = [[NextView alloc] initWith ... ];
    [UIView transitionFromView:self.view toView:nextView.view duration:1 options:UIViewAnimationOptionTransitionFlipFromLeft completion:nil];
    [nextView release];
}

This worked perfectly for me. Just to make sure I was getting new views, I assigned tags to each view and added UILabels as subviews in each view's viewDidLoad method and each showed the number of its view. So hopefully this is what you needed. I'm sure you have more complex things you will need to do, but this will give you the animation and logic you need to get the look you want. (on a side note, viewDidAppear doesn't seem to get called when doing this, so it might be necessary to call it manually from viewDidLoad if you really need to use it, but otherwise it works fine)

justin
  • 5,811
  • 3
  • 29
  • 32
  • Hello Slev, Thanks for posting this answer here. It is really helpful. But along the "pushViewController", I also need to do "Popviewcontroller" from the next controller and I tried there but now working. And here It is only working when I push one view to another. But in my application I am having hirarchy of two controllers upto level n. So, It is not possible using this to go after the 2nd view controller. – AppAspect May 22 '11 at 06:22
  • FirstView: (Button Next -Clicked) [UIView beginAnimations:nil context:NULL]; [UIView setAnimationTransition: UIViewAnimationTransitionFlipFromRight forView:self.view.window cache:NO]; [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; [UIView setAnimationDuration:1.0]; [UIView commitAnimations]; [self.navigationController pushViewController:objCategory animated:YES]; SecondView: (ViewWillAppear) [self.navigationController pushViewController:objCategory2View animated:YES]; Please help me to solve this issue now. – AppAspect May 22 '11 at 06:26
  • I think I might have a possible solution for this, though I'm going to edit my original answer and add on just so it's easier to read (as well as type) – justin May 22 '11 at 18:49
  • Hello Slev, I checked this code but not working at my side. Can you give me some working reference for the same. – AppAspect May 24 '11 at 04:52
  • Which part of it isn't working for you? That way I can try to supply you code to better fit your need. I only say this because the code I have above works for me (both to go to and from views), so if you can let me know what part isn't working (or what you need to do with it), I will be glad to help – justin May 24 '11 at 05:32
  • Hello Slev, After seeing your continuous effort I have provided bounty to you and you are very near to our solution so far. I am able to do the flip to right or left in landscape view so far. But I have to manage the hierarchy in which I can do animation for one view to other by using this code. But from second view to upto n-1 th viewcontroller I just pushviewcontroller in viewWillAppear method. So, Please help me for that situation. If I do animation for only 2 view controller, this is the best solution so far. Please help me with some working model or some references. – AppAspect May 24 '11 at 16:27
  • For a better idea of what to help provide you, what exactly do you want the views to do? I ask because we might be able to get rid of the navigation controller if you don't need it for any other reason that to push/pop views. The code above would let you do that animation on its own and the navigation controller would only complicate it (by adding extra references). Also, how would you like to switch views? Let's say you have 10 views. Do you want to go from 1 to 10, showing each view as you go? If I can find out more detailed what you are looking to do, I can provide a basic code for it – justin May 24 '11 at 18:18
  • Hello Slev, OK. Suppose I need to go from view 1 to 10 in hierarchy order. So, I can push from 1 to 2 - 2 to 3 and so on upto 10 continuous just by clicking one button on view 1 - stated "Go to view 10" and then I push using your code specified above. But what to do when we push from 2 to 3 , 3to 4 and so on in the view will appear method of respective controllers. That is the simple question I think. If you need more then I can tell u that also. – AppAspect May 25 '11 at 04:05
  • That is all I need to know. I have a practice app already set up to work with, so I will get back to you when I find something. Hopefully it won't take too long because I have a couple ideas in mind – justin May 25 '11 at 04:54
  • Alright, I have a working code that switched 10 consecutive views upon pressing a button. I'm going to edit my answer to tell you how I went about it – justin May 25 '11 at 05:38
  • Slev, I have the same problem - this code works fine in portrait mode, but switching to landscape make it fail. Can you give any additional hints? – Valerii Hiora Jul 15 '11 at 19:50
  • The only thing I can really hint at is checking your view controllers as they are created. I was able to get this method working in landscape just fine, but noticed that `viewDidLoad` was called for each, but not `viewDidAppear:`, which was very confusing. So if you are having troubles with the methods, I would suggest to log your `viewDidLoad` to ensure the views are created, then try to make sure no vital code is in `viewDidAppear:` since it doesn't seem to get called (I truly wish I knew why this happens) – justin Jul 15 '11 at 21:12
  • Thanks for hints, unfortunately didn't help, but I've got it to work using transitionWithView: and providing additional container view. – Valerii Hiora Jul 16 '11 at 19:17
  • I'm sorry it didn't help you out. It seems my code only works for certain situations, and since I don't use it for any of my own applications, I haven't spent the time to remove the artifacts from it yet. I'm very glad to hear you got a version working, though – justin Jul 16 '11 at 19:48
2

You will have to manually add a transformation to your view; the flip transformation always operates as if the view controller were in portrait orientation.

Note that the context argument to +beginAnimations:context: is not meant to be a CGContextRef per se. You probably don't want to pass the current graphics context there. Pass NULL instead.

Jonathan Grynspan
  • 43,286
  • 8
  • 74
  • 104
  • Hello, I removed the current graphics context and put NULL but the same thing as before. It is working like in Portrait mode. Not working in landscape as per requirement that is left to right. Can you please help me here. – AppAspect Apr 19 '11 at 13:04
  • Do you have any transformation reference you are talking about? – AppAspect Apr 19 '11 at 13:05
1
CGContextRef context = UIGraphicsGetCurrentContext();

[UIView beginAnimations:nil context:context];

[UIView setAnimationTransition: UIViewAnimationTransitionFlipFromLeft forView:self.view cache:NO];

[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];

[UIView setAnimationDuration:1.0];

[UIView commitAnimations];

I think this will work out.

visakh7
  • 26,380
  • 8
  • 55
  • 69
Rams
  • 1,721
  • 12
  • 22
  • FYI - indent 4 spaces (or use the `{}` button) to format code - more help [here](http://stackoverflow.com/editing-help) – McDowell May 19 '11 at 09:27
  • Hello, It is not working and by the way this is the same code I posted here. Can you please provide perfect solution you have. Thanks in advacne. – AppAspect May 19 '11 at 18:14
1

Try with this :

CABasicAnimation *rotateAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.y"];
    CGFloat startValue = 0.0;
    CGFloat endValue = M_PI;
    rotateAnimation.fromValue = [NSNumber numberWithDouble:startValue];
    rotateAnimation.toValue = [NSNumber numberWithDouble:endValue];
    rotateAnimation.duration = 1.5;
    [self.view.layer addAnimation:rotateAnimation forKey:@"rotate"];
visakh7
  • 26,380
  • 8
  • 55
  • 69
Priyanka
  • 152
  • 6
0

The Accepted answer by slev did not work for me, I got all sorts of errors after trying the code in my custom Segue. I found a method that not only works but is more precise as it doesn't require the use of a Timer. Here is MySegue.m:

@implementation FlipRightSegue

- (id)initWithIdentifier:(NSString *)iden source:(UIViewController *)sour destination:(UIViewController *)dest
{
    self = [super initWithIdentifier:iden source:sour destination:dest];

    return self;
}

- (void)perform
{

    UIViewController *src = [self sourceViewController];
    UIViewController *dst = [self destinationViewController];

    //[UIView transitionFromView:src.view toView:dst.view duration:1 options:UIViewAnimationOptionTransitionFlipFromRight completion:nil];
    //[UIView commitAnimations];

    [UIView transitionWithView:src.navigationController.view duration:0.8 options:UIViewAnimationOptionTransitionFlipFromLeft
                   animations:^{
                       [src.navigationController pushViewController:dst animated:NO];
                   }
                   completion:NULL];
}

@end

I also have a second class for flips to the right. Code was taken from this website: http://www.dailycode.info/Blog/post/2012/11/29/iOS-Custom-Flip-Segue-(portrait-and-landscape-layout)-xcode-4.aspx

firescar96
  • 419
  • 3
  • 8