Switching views with Transition effect - xcode

I'm trying to add an effect to a switch between 2 views. The switch happen just rotating the device. So far I'm able to apply the effect when from portrait go to landscape, but not viceversa.
Here's my code:
-(void)orientationChanged:(NSNotification *)object{
UIDeviceOrientation deviceOrientation = [[object object] orientation];
if (deviceOrientation == UIInterfaceOrientationPortrait)
{
/* If I run with this block, I have a Exc Bad Access Error and can't run, so I put it
under comment
[UIView transitionWithView:self.view duration:1.0
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
[self.view addSubview:self.portraitView];
} completion:NULL];
*/
self.view = self.portraitView;
//[self dismissModalViewControllerAnimated:YES];
}
else if (deviceOrientation == UIInterfaceOrientationLandscapeLeft || deviceOrientation ==
UIInterfaceOrientationLandscapeRight)
{
[UIView transitionWithView:self.view duration:1
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
[self.view addSubview:self.landscapeView];
} completion:NULL];
[self dismissModalViewControllerAnimated:NO];
}
}
In this way I have the desired effect when passing from Portrait to Landscape, but when I put the device back to Portrait it doesn't load the portraitView, the landscapeView remains on.
Hope somebody can help me.
EDIT:
I just edited my above code in this way:
-(void)orientationChanged:(NSNotification *)object{
UIDeviceOrientation deviceOrientation = [[object object] orientation];
if (deviceOrientation == UIDeviceOrientationPortrait)
{
if (self.isViewLoaded && self.view.window)
{
NSLog(#"Portrait1");
[UIView transitionWithView:self.view duration:1
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
NSLog(#"Portrait2");
[self.view.window addSubview:self.portraitView];
} completion:NULL];
[self dismissModalViewControllerAnimated:YES];
}
}
else if (deviceOrientation == UIDeviceOrientationLandscapeLeft || deviceOrientation ==
UIDeviceOrientationLandscapeRight)
{
[UIView transitionWithView:self.view duration:1
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
[self.view addSubview:self.landscapeView];
} completion:NULL];
[self dismissModalViewControllerAnimated:NO];
NSLog(#"Landscape");
}
}
And the effect works fine. But I have the big issue that when I switch back from Landscape to Portrait the landscapeView remains ON the portraitView. How could I dismiss it?

Referring to your updated code, when your device orientation becomes UIDeviceOrientationPortrait, you are making the mistake of adding portraitView as a subview to self.view.window instead of self.view.
Also, what is the purpose behind [self dismissModalViewControllerAnimated:NO]? You haven't actually presented a modal view controller anywhere, so it doesn't serve any purpose.

Related

dismissViewControllerAnimated differs in ios8 and ios7

I have a launchViewController A and two other view controllers B and C. In the app, present sequence is A->B->C. I also have a need to dismiss C and directly back to A.
The problem is:
In iOS7, I call [self dismissViewControllerAnimated:false completion:^{}] in A. the functions viewWillAppear and viewDidAppear in B view controller will not be called.
But in iOS8, things are different. viewWillAppear and viewDidAppear will be called in B view controller. This results in a flashes of B's contents when dismiss.
Can anyone help me to find a way to fix this.
if you want to dismiss current ViewController in Which you are you should use
[self.presentingViewController dismissViewControllerAnimated:false completion:^{}]
instead of [self dismissViewControllerAnimated:false completion:^{}]
I fixed the issue by using this:
- (void)dismissDeepViewControllerAnimated: (BOOL)flag completion: (void (^)(void))completion {
if([UIDevice currentDevice].systemVersion.floatValue >= IOSCapVersion){
UIView *window = ((AppDelegate *)[UIApplication sharedApplication].delegate).window;
UIView *view = [window snapshotViewAfterScreenUpdates:false];
[((AppDelegate *)[UIApplication sharedApplication].delegate).window addSubview:view];
[self dismissViewControllerAnimated:false completion:^{
[UIView animateWithDuration:AnimationDurationDismissViewController animations:^{
view.alpha = 0;
}completion:^(BOOL finished) {
if (finished) {
[view removeFromSuperview];
}
}];
completion();
}];
}
else{
[self dismissViewControllerAnimated:flag completion:^{
completion();
}];
}
}

Transition segue like facebook open image to fullscreen xcode

Can anyone say how to implement transition segue like in facebook app when i open image to fullscreen?
I fount this example http://joris.kluivers.nl/blog/2013/01/15/custom-view-controller-transitions-using-uistoryboardsegues/
but it blinking during the transition on ios7 and i don't understand how to fix it( Have anyone any ideas?
The blinking is being caused by the temporary image that is created to simulate the transition being removed before the image is unhidden in the new view. I changed the completion block to delay by .25 seconds to allow for the image to be unhidden.
[UIView animateWithDuration:0.4f delay:.0f options:UIViewAnimationOptionCurveEaseInOut animations:^{
imageView.frame = dest;
if (self.unwinding) {
[self.destinationViewController dismissViewControllerAnimated:YES completion:nil];
} else {
((UIViewController *)self.destinationViewController).modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self.sourceViewController presentViewController:self.destinationViewController animated:YES completion:nil];
}
} completion:^(BOOL completed) {
int64_t delayInSeconds = 1;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC/4);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
imageView.hidden = YES;
[imageView removeFromSuperview];
});
}];

Xcode custom segue - Opposite of Cover Vertical (top to bottom) - COMPLETE NEWBIE

I have been trying for some time to create a custom segue that does the opposite of the cover vertical (to create a from top to bottom effect animation).I had looked through other questions, google and youtube but cannot get it working.I am completely new to the classes etc. so any help in a step by step guide or video would be so good. I believe that this URL is trying to do something similar to what I want:
http://jrwren.wrenfam.com/blog/2012/02/01/storyboard-custom-segue-for-custom-pushviewcontroller-animation/ , I just cannot get it working.
If any of you know a way to create a segue that is a top to bottom version of the cover vertical segue could you please help me out?
Well, you would want to create a subclass of UIStoryBoardSegue, like the walkthrough shows you, however under the Storyboard class' .m file(implementation) you would want the following code as your -(void)perform: method -
-(void)perform{
UIViewController *sourceViewController = (UIViewController *) self.sourceViewController;
UIViewController *destinationViewController = (UIViewController *) self.destinationViewController;
[sourceViewController.view addSubview:destinationViewController.view];
[destinationViewController.view setFrame:sourceViewController.view.window.frame];
[destinationViewController.view setTransform:CGAffineTransformMakeTranslation(0, -sourceViewController.view.frame.size.height)];
[destinationViewController.view setAlpha:1.0];
[UIView animateWithDuration:0.75
delay:0.0
options:UIViewAnimationOptionTransitionFlipFromTop
animations:^{
[destinationViewController.view setTransform:CGAffineTransformMakeTranslation(0, 0)];
[destinationViewController.view setAlpha:1.0];
}
completion:^(BOOL finished){
[destinationViewController.view removeFromSuperview];
[sourceViewController presentViewController:destinationViewController animated:NO completion:nil];
}];}
Hopefully this is helpful.
Building on #dmason82's answer, translating to Swift, and simplifying a little, this works for me:
class UIStoryboardSegueFromTop: UIStoryboardSegue {
override func perform() {
let src = self.sourceViewController as UIViewController
let dst = self.destinationViewController as UIViewController
src.view.superview?.insertSubview(dst.view, aboveSubview: src.view)
dst.view.transform = CGAffineTransformMakeTranslation(0, -src.view.frame.size.height)
UIView.animateWithDuration(1.0, animations: {
dst.view.transform = CGAffineTransformMakeTranslation(0, 0)
}) { (Finished) in
src.presentViewController(dst, animated: false, completion: nil)
}
}
}
Here is my implementation of an Opposite Cover Vertical Segue using Storyboards
https://github.com/viccarre/OppositeCoverVerticalSegue
Hi I just tried the two other answer but it doesn't work as you ask.
In order to create a custom segue looking the exact reverse of cover vertical (modal segue default) I created this code :
- (void)perform
{
UIViewController *sourceViewController = self.sourceViewController;
UIViewController *destinationViewController = self.destinationViewController;
[sourceViewController presentViewController:destinationViewController animated:NO completion:nil];
[destinationViewController.view addSubview:sourceViewController.view];
[sourceViewController.view setTransform:CGAffineTransformMakeTranslation(0, 0)];
[sourceViewController.view setAlpha:1.0];
[UIView animateWithDuration:0.75
delay:0.0
options:UIViewAnimationOptionTransitionFlipFromBottom
animations:^{
[sourceViewController.view setTransform:CGAffineTransformMakeTranslation(0,destinationViewController.view.frame.size.height)];
[sourceViewController.view setAlpha:1.0];
}
completion:^(BOOL finished){
[sourceViewController.view removeFromSuperview];
}];
}
#end
To complete dmason's answer and have your controller unwind in the opposite direction - going back up from where it came, do this in the presented view controller:
[UIView animateWithDuration:0.75
delay:0.0
options:UIViewAnimationOptionTransitionFlipFromBottom
animations:^{
[self.view setTransform:CGAffineTransformMakeTranslation(0, -self.view.frame.size.height)];
}
completion:^(BOOL finished){
[self dismissViewControllerAnimated:NO completion:nil];
}
];
Bergy's answer didn't work for me.
dmason's answer is great, and if you want to add an unwind segue so your modal animates properly when it's closed, your perform action could look like this (in a new custom segue class)
- (void)perform
{
UIViewController *sourceViewController = self.sourceViewController;
UIViewController *destinationViewController = self.destinationViewController;
[sourceViewController dismissViewControllerAnimated:NO completion:nil];
[destinationViewController.view addSubview:sourceViewController.view];
[UIView animateWithDuration:0.75
animations:^{
sourceViewController.view.center = CGPointMake(sourceViewController.view.center.x, sourceViewController.view.center.y-600);
}
completion:^(BOOL finished){
[sourceViewController.view removeFromSuperview];
}
];
}
I advise you to use the Hero library to achieve this. It adds a lot of animations and transitions, notably between view controllers : https://github.com/lkzhao/Hero/blob/master/README.md
There is an transition called "Cover", and you can choose the direction (left, top, right, bottom)

Xcode: Why does my flip animation flip twice?

I'm having a little problem. I have an UILabel which have an UILongPressGestureRecognicer. When the UILongPressGestureRecognizer is called my app is supposed to switch to a new view using a flip animation.
This is the code I have used for the GestureRecognizer:
UILongPressGestureRecognizer *labelLongPressRecognizer;
labelLongPressRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(LoadLabelSettings:)];
labelLongPressRecognizer.numberOfTouchesRequired = 1;
labelLongPressRecognizer.minimumPressDuration = 2.0;
[NewLabel addGestureRecognizer:labelLongPressRecognizer];
and this is the code for the view switching animation:
CGContextRef context = UIGraphicsGetCurrentContext();
[UIView beginAnimations:nil context:context];
[UIView setAnimationTransition: UIViewAnimationTransitionFlipFromRight forView:self.view cache:NO];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:1.0];
[self.view addSubview:LabelSettingsViewController.view];
[UIView commitAnimations];
if (self.interfaceOrientation == UIInterfaceOrientationLandscapeRight || self.interfaceOrientation == UIInterfaceOrientationLandscapeLeft) {
LabelSettingsViewController.view.frame = CGRectMake(0, 0, 480, 300);
}
My problem is that when I hold down on my UILabel the switch animation begins, but when I release it repeats the animation again. So basically the animation occur twice and I only want it to take place once.
Any ideas?
Thanks in advance :)
Are you checking the sender state, e.g.,
- (void)LoadLabelSettings:(UILongPressGestureRecognizer *)sender
{
if (sender.state == UIGestureRecognizerStateEnded) // or whatever
// then do the flipping stuff
}
Check out the "Overview" of the "UILongPressGestureRecognizer Class Reference", which talks about the long press being continuous and I presume numerous events could be triggered:
http://developer.apple.com/library/ios/#DOCUMENTATION/UIKit/Reference/UILongPressGestureRecognizer_Class/Reference/Reference.html

Page curl up - for landscape left and landscape right

I am trying to create a page turn application in xcode. The page turn works fine for landscape right but for landscape left, the page curl happens from the left. I added a container view and then the page curl on landscape left started happening from the bottom but not from right.
I found some suggestions here (http://stackoverflow.com/questions/4780488/i-want-to-use-animation-to-imageview-using-uianimationtransitioncurl-right-or-lef) and here (http://stackoverflow.com/questions/4780488/i-want-to-use-animation-to-imageview-using-uianimationtransitioncurl-right-or-lef)
but these both suggestions were with old style of page transition code and not with the block code. I tried to modify these with new block style code but it is not working for me.
I am attaching my code here:
- (void)viewDidLoad
{
UIImage *img = [UIImage imageNamed:#"s1p1.png"];
currentView.image = img;
img = [UIImage imageNamed:#"s1p2.png"];
swapView.image = img;
UISwipeGestureRecognizer *nextPage;
nextPage = [[[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(turnPage)] autorelease];
if ([[UIDevice currentDevice] orientation] == UIInterfaceOrientationLandscapeLeft) {
[nextPage setDirection:UISwipeGestureRecognizerDirectionRight];
}
else {
[nextPage setDirection:UISwipeGestureRecognizerDirectionLeft];
}
[self.view addGestureRecognizer:nextPage];
[super viewDidLoad];
}
-(void) turnPage
{
if ([[UIDevice currentDevice] orientation] == UIInterfaceOrientationLandscapeLeft)
{
NSLog(#"landscapeleft");
mainView.transform = CGAffineTransformMakeRotation(M_PI);
currentView.transform = CGAffineTransformMakeRotation(-M_PI);
swapView.transform = CGAffineTransformMakeRotation(-M_PI);
[UIView transitionWithView:mainView
duration:1
options:UIViewAnimationOptionTransitionCurlUp
animations:^{
currentView.hidden = YES;
swapView.hidden = NO;
}
completion:^(BOOL finished){
UIImage *temp = [currentView.image retain];
currentView.image = swapView.image;
swapView.image = temp;
[temp release];
currentView.hidden = NO;
swapView.hidden = YES;
}];
}
else
{
NSLog(#"landscaperight");
[UIView transitionWithView:self.view
duration:1
options:UIViewAnimationOptionTransitionCurlUp
animations:^{
currentView.hidden = YES;
swapView.hidden = NO;
}
completion:^(BOOL finished){
UIImage *temp = [currentView.image retain];
currentView.image = swapView.image;
swapView.image = temp;
[temp release];
currentView.hidden = NO;
swapView.hidden = YES;
}];
}
}
where I have two views: the self.view is the primary view from the window and then the mainView is my container view. currentView and SwapView are imageviews.
Any thoughts on this? Many thanks for reviewing this.

Resources