2013-06-29 6 views
2

사용자 정의 segue를 사용하여 UIViewController 사이에 간단한 푸시 애니메이션을 추가하려고합니다.UIGavigationController없이 Segue 애니메이션 푸시

탐색 컨트롤러를 사용하지 않을 때까지 탐색 컨트롤러와 잘 작동 발견

대답을하지만, 실패의 (a은 UINavigationController를 사용하여 내 컨트롤러를 변환하지 않고). 7/5/12

#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]; 

} 

만약에 (ZHCustomSegue.m) Zakir에

내 사용자 정의로 자연스럽게하는 .m 덕분에 (난 아직도 스택 오버플로 여기에 본 적이 다른 답변을 읽고 노력하고 있어요) 나는 Zakir의 원래 예에 따라 네비게이션 컨트롤러를 사용하고 함께 지난 2 개 라인을 교체 :

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

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

의미가 있습니다 ....

애플의 문서는 말한다 (통지하지 탐색 컨트롤러 및 사용하고 odal segue) :

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

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

작동하지 않으면 애니메이션이 없습니다. Zakir의 코드에서 4.0 초 사용하면 4.0 초가 걸리고 원하는 애니메이션을 얻습니다. 물론, 내비게이션 컨트롤러를 사용하면 푸시 전환이 기본 설정입니다. 이 코드에서는 애니메이션이 없으며 0 초가 걸립니다.

누구나 UIViewControllers에서 작동하도록 맞춤형 segue 애니메이션을 얻었습니까?

답변

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 : 완료 :을 사용하십시오.

일반적인 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 
*/ 
관련 문제