2013-06-29 44 views
2

我想在使用自定義的segue的UIViewControllers之間添加一個簡單的推動畫。沒有UINavigationController的Push Segue動畫

(無需轉換我的控制器使用一個UINavigationController)不使用導航控制器時

迄今爲止發現的正常工作與導航控制器的答案,但失敗。 (我還在讀書,並試圖其他答案我在這裏看到的堆棧溢出)

我定製SEGUE .M感謝(ZHCustomSegue.m)扎基爾在12年7月5日

#import "SFCustomSegue.h" 
#import "QuartzCore/QuartzCore.h" 

@implementation SFCustomSegue 


-(void)perform { 

UIViewController *sourceViewController = (UIViewController*)[self sourceViewController]; 
UIViewController *destinationController = (UIViewController*)[self destinationViewController]; 

CATransition* transition = [CATransition animation]; 
transition.duration = 4.0; 
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 
transition.type = kCATransitionPush; 
transition.subtype = kCATransitionFromRight; 

[sourceViewController.view.layer addAnimation:transition forKey:kCATransition]; 

[sourceViewController presentViewController:[self destinationViewController] animated:NO completion:nil]; 

} 

如果我使用的是導航控制器按扎基爾原來的例子,取而代之的最後兩行:

[sourceViewController.navigationController.view.layer addAnimation:transition 
                  forKey:kCATransition]; 

[sourceViewController.navigationController pushViewController:destinationController animated:NO];  

工程....

蘋果的醫生說(通知不是導航控制器,並採用AM odal segue):

- (void)perform 
{ 
// Add your own animation code here. 

[[self sourceViewController] presentModalViewController:[self destinationViewController] animated:NO]; 
} 

通過不工作,我沒有得到動畫。在Zakir的代碼中,使用4.0秒需要4.0秒,並且獲得我想要的動畫。當然,如果我使用導航控制器,推送轉換是默認的。在這段代碼中,我沒有獲得動畫,它需要0秒。

有沒有人得到自定義segue動畫來使用UIViewControllers?

回答

0

看來,我的上面的代碼,「幾乎」工作,但不完全。 目前的主要問題很可能是最後一步被調用。

我的工作的代碼看起來是這樣的:

#import "SFCustomSegue.h" 
#import "QuartzCore/QuartzCore.h" 

@implementation SFCustomSegue 

static const float delay = 0.5f; 

-(void)perform { 

    UIViewController *sourceViewController = (UIViewController*)[self sourceViewController]; 
    UIViewController *destinationController = (UIViewController*)[self destinationViewController]; 

    [sourceViewController.view addSubview:destinationController.view]; 

    CATransition* transition = [CATransition animation]; 
    transition.duration = delay; 
    transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 
    transition.type = kCATransitionPush; 
    transition.subtype = kCATransitionFromRight; 

    [sourceViewController.view.layer addAnimation:transition forKey:kCATransition]; 

    [self performSelector:@selector(performDone:) withObject:destinationController afterDelay:delay]; 
} 

- (void)performDone:(id)viewController{ 
    UIViewController *destination = (UIViewController*)viewController; 
    [destination.view removeFromSuperview]; 
    [[self sourceViewController] presentViewController:destination animated:NO completion:nil]; 

} 

@end 

的關鍵在於解決這個被添加視圖過渡(13號線),然後除去它(線28)和把它加回到(29行)使用presentViewController:animated:completion:

我仍然「卡住」只使用常規的CATransition轉換類型,但這對我來說已經夠用了,因爲我想使用kCATransitionPush

+0

如果有人可以重寫這個來使用完成塊,我希望更好,但這是有效的。 –

2

由於您致電presentViewController,源視圖控制器正在不停地移動。如果你真的想取代與目標視圖控制器源視圖控制器,使源被dealloced,你可以這樣做:

static UIImageView *screenShotOfView(UIView *view) 
{ 
    // Create a snapshot for animation 
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, 0.0); 
    CGContextRef context = UIGraphicsGetCurrentContext(); 
    [view.layer renderInContext:context]; 
    UIImageView *screenShot = [[UIImageView alloc] initWithImage:UIGraphicsGetImageFromCurrentImageContext()]; 
    UIGraphicsEndImageContext(); 
    return screenShot; 
} 

- (void)perform 
{ 
    UIViewController *source = (UIViewController *) self.sourceViewController; 
    UIViewController *destination = (UIViewController *) self.destinationViewController; 

    // Swap the snapshot out for the source view controller 
    UIWindow *window = source.view.window; 
    UIImageView *screenShot = screenShotOfView(source.view); 
    CGRect originalFrame = destination.view.frame; 

    BOOL animsEnabled = [UIView areAnimationsEnabled]; 
    [UIView setAnimationsEnabled:NO]; 
    { 
     window.rootViewController = destination; 
     [window addSubview:screenShot]; 
     [source.view removeFromSuperview]; 
     CGRect frame = destination.view.frame; 
     frame.origin.x += source.view.bounds.size.width; 
     destination.view.frame = frame; 
    } 
    [UIView setAnimationsEnabled:animsEnabled]; 

    [UIView animateWithDuration:kAnimationDuration 
        animations:^{ 
         destination.view.frame = originalFrame; 
         CGRect frame = screenShot.frame; 
         frame.origin.x -= screenShot.bounds.size.width; 
         screenShot.frame = frame; 

        } 
        completion:^(BOOL finished) { 
         [screenShot removeFromSuperview]; 
        }]; 
} 
0

我從兩個答案合併的想法,讓這個代碼(工作好): (從上面的答案不包括在設備的方向,例如,它們將不能在橫向工作)

(CATransitions的變體是不合適的,因爲兩個視圖之間有差距而一個推另一個)

#import "PushSegue.h" 

/* 
@interface TransitionDelegate : NSObject 
- (id) initWithScreenshot: (UIView*) screenshot; 
@end 
*/ 

@implementation PushSegue 
- (void) perform 
{ 
    UIViewController* source = (UIViewController*) self.sourceViewController; 
    UIViewController* destination = (UIViewController*) self.destinationViewController; 

    const BOOL iPad = [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad; 
    float animationDuration = iPad ? 0.5 : 0.3; 

    // Swap the snapshot out for the source view controller 
    UIWindow* window = source.view.window; 
    UIImageView* screenShot = screenShotOfView(source.view); 

    // accord to device orientation 

    float rotation; 
    //NSString* transitionType; 

    CGRect originalFrame = destination.view.frame; 
    CGRect destinationFrame = destination.view.frame; 

    switch ([UIApplication sharedApplication].statusBarOrientation) 
    { 
     case UIInterfaceOrientationPortraitUpsideDown: 
      rotation = M_PI; 
      destinationFrame.origin.x -= source.view.bounds.size.width; 
      //transitionType = kCATransitionFromLeft; 
      break; 

     case UIInterfaceOrientationLandscapeLeft: 
      rotation = M_PI + M_PI_2; 
      destinationFrame.origin.y -= source.view.bounds.size.width; 
      //transitionType = kCATransitionFromBottom; 
      break; 

     case UIInterfaceOrientationLandscapeRight: 
      rotation = M_PI_2; 
      destinationFrame.origin.y += source.view.bounds.size.width; 
      //transitionType = kCATransitionFromTop; 
      break; 

     default: 
      rotation = 0; 
      destinationFrame.origin.x += source.view.bounds.size.width; 
      //transitionType = kCATransitionFromRight; 
      break; 
    } 

    screenShot.transform = CGAffineTransformMakeRotation(rotation); 

    // reposition after rotation 
    CGRect screenshotFrame = screenShot.frame; 
    screenshotFrame.origin.x = 0; 
    screenshotFrame.origin.y = 0; 
    screenShot.frame = screenshotFrame; 

    switch ([UIApplication sharedApplication].statusBarOrientation) 
    { 
     case UIInterfaceOrientationPortraitUpsideDown: 
      screenshotFrame.origin.x += screenShot.bounds.size.width; 
      break; 

     case UIInterfaceOrientationLandscapeLeft: 
      screenshotFrame.origin.y += screenShot.bounds.size.width; 
      break; 

     case UIInterfaceOrientationLandscapeRight: 
      screenshotFrame.origin.y -= screenShot.bounds.size.width; 
      break; 

     default: 
      screenshotFrame.origin.x -= screenShot.bounds.size.width; 
      break; 
    } 

    // swap the view with its screenshot 
    window.rootViewController = destination; 
    [window addSubview:screenShot]; 
    [source.view removeFromSuperview]; 

    /* 
    CATransition* transition = [CATransition animation]; 

    transition.duration = animationDuration; 
    transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 
    transition.type = kCATransitionPush; 
    transition.subtype = transitionType; 
    transition.delegate = [[TransitionDelegate alloc] initWithScreenshot:screenShot]; 

    [window addSubview:destination.view]; 

    [screenShot.window.layer addAnimation:transition forKey:nil]; 
    */ 

    const BOOL animationsEnabled = [UIView areAnimationsEnabled]; 
    [UIView setAnimationsEnabled:NO]; 
    { 
     destination.view.frame = destinationFrame; 
    } 
    [UIView setAnimationsEnabled:animationsEnabled]; 

    [UIView animateWithDuration:animationDuration 
        animations:^ 
    { 
     destination.view.frame = originalFrame; 
     screenShot.frame = screenshotFrame; 
    } 
        completion:^(BOOL finished) 
    { 
     [screenShot removeFromSuperview]; 
    }]; 

    /* 
    const BOOL animationsEnabled = [UIView areAnimationsEnabled]; 
    [UIView setAnimationsEnabled:NO]; 
    { 
     CGRect frame = destination.view.frame; 
     frame.origin.x += source.view.bounds.size.width; 
     destination.view.frame = frame; 
    } 
    [UIView setAnimationsEnabled:animationsEnabled]; 

    [UIView animateWithDuration:animationDuration 
        animations:^ 
    { 
     destination.view.frame = originalFrame; 
     CGRect frame = screenShot.frame; 
     frame.origin.x -= screenShot.bounds.size.width; 
     screenShot.frame = frame; 
    } 
    completion:^(BOOL finished) 
    { 
     [screenShot removeFromSuperview]; 
    }]; 
    */ 

    /* 
    CATransition* transition = [CATransition animation]; 

    transition.duration = animationDuration; 
    transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 
    transition.type = kCATransitionPush; 

    switch ([UIApplication sharedApplication].statusBarOrientation) 
    { 
     case UIInterfaceOrientationPortraitUpsideDown: 
      transition.subtype = kCATransitionFromLeft; 
      break; 

     case UIInterfaceOrientationLandscapeLeft: 
      transition.subtype = kCATransitionFromBottom; 
      break; 

     case UIInterfaceOrientationLandscapeRight: 
      transition.subtype = kCATransitionFromTop; 
      break; 

     default: 
      transition.subtype = kCATransitionFromRight; 
      break; 
    } 

    [source.view.window.layer addAnimation:transition forKey:nil]; 

    [source presentViewController:destination animated:NO completion:nil]; 
    */ 
} 

static UIImageView* screenShotOfView(UIView* view) 
{ 
    // Create a snapshot for animation 
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, 0.0); 
    CGContextRef context = UIGraphicsGetCurrentContext(); 

    [view.layer renderInContext:context]; 
    UIImageView* screenShot = [[UIImageView alloc] initWithImage:UIGraphicsGetImageFromCurrentImageContext()]; 

    UIGraphicsEndImageContext(); 

    return screenShot; 
} 
@end 

/* 
@implementation TransitionDelegate 
{ 
    UIView* screenshot; 
} 

- (id) initWithScreenshot: (UIView*) screenshot 
{ 
    if (self = [super init]) 
    { 
     self->screenshot = screenshot; 
    } 
    return self; 
} 

- (void) animationDidStop: (CAAnimation*) theAnimation 
       finished: (BOOL) flag 
{ 
    [screenshot removeFromSuperview]; 
} 
@end 
*/ 
相關問題