2010-07-01 109 views
6

我想在視圖的兩種狀態之間動畫。比如說,我有一個帶有標籤的視圖,當我更改標籤的文本時,動畫會呈現頁面翻轉時發生的變化。使用自定義動畫在視圖的兩種狀態之間動畫

現在你當然可以做到這一點與[UIView setAnimationTransition:forView:cache:]

- (IBAction)nextPage { 
    [UIView beginAnimation:nil context:nil]; 
    [UIView setAnimationDuration:1]; 
    [UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:pageView cache:NO]; 
    label.text = @"page 2"; 
    [UIView commitAnimations]; 
} 

- (IBAction)previousPage { 
    [UIView beginAnimation:nil context:nil]; 
    [UIView setAnimationDuration:1]; 
    [UIView setAnimationTransition:UIViewAnimationTransitionCurlDown forView:pageView cache:NO]; 
    label.text = @"page 1"; 
    [UIView commitAnimations]; 
} 

...但你不能使用你自己的自定義動畫,你被卡住的內置動畫(他們是好的,但它們並不適合我的需求)。

因此,另一種選擇是一個CAAnimation添加到視圖中的層:

- (IBAction)nextPage { 
    CAAnimation *animation = [self animationWithDuration:1 forward:NO]; 
    [pageView.layer addAnimation:animation forKey:@"pageTransition"]; 
    label.text = @"page 2"; 
} 

- (IBAction)previousPage { 
    CAAnimation *animation = [self animationWithDuration:1 forward:YES]; 
    [pageView.layer addAnimation:animation forKey:@"pageTransition"]; 
    label.text = @"page 1"; 
} 

然後你可以隨意設置任何動畫核心動畫讓你做。如果我定義一個CATransition動畫,例如kCATransitionReveal,則此效果很好:在「頁面2」狀態下的視圖出現在「頁面1」狀態下的視圖下方時,它將滑出。

- (CAAnimation *)animationWithDuration:(float)duration forward:(BOOL)forward { 
    CATransition *animation = [CATransition animation]; 
    [animation setType:kCATransitionReveal]; 
    [animation setSubtype:forward?kCATransitionFromLeft:kCATransitionFromRight]; 
    [animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]]; 

    animation.duration = duration; 
    return animation; 
} 

但是,當我定義動畫是例如CABasicAnimation,僅一個視圖的狀態是可見的。

- (CAAnimation *)animationWithDuration:(float)duration forward:(BOOL)forward { 
    CATransform3D transform = CATransform3DIdentity; 
    transform.m34 = 1.0/-1000; 
    transform = CATransform3DRotate(transform, M_PI, 0.0f, 1.0f, 0.0f); 
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform"]; 
    if(forward) { 
     animation.fromValue = [NSValue valueWithCATransform3D:transform]; 
    } else { 
     animation.toValue = [NSValue valueWithCATransform3D:transform]; 
    } 

    animation.duration = duration; 
    return animation; 
} 

相反,我想在「頁面1」狀態的視圖保持可見,直到動畫結束而在「頁面2」狀態的視圖進入幀,正是因爲它與行爲過渡動畫。

當然,我總是可以在複製視圖的同時讓其中一個顯示爲兄弟視圖,同時爲最前面的視圖製作動畫並在完成時將其從超視圖中移除...但是必須有更直接的方法才能實現這個相當簡單的動畫效果而不影響視圖。

可能的事情告訴了一層,但我不知道是什麼,而這也正是我需要你的幫助,球員:)

謝謝!

回答

0

那麼,您可以創建一個圖層,將其內容設置爲代表您的視圖最終狀態的圖像,而不是將動畫應用於此圖層。動畫完成後,您可以移除圖層並切換視圖狀態。

我認爲這會比實例化整個視圖更好。

1

我最近在控制器中的子視圖之間做了自定義幻燈片切換。我的方法是抓取視圖和視圖的位圖,將它們添加到視圖併爲該視圖添加動畫。最後,您可以刪除轉場視圖並顯示視圖。這裏有一個片斷的過渡方法:

-(void) transitionToView:(UIView *)viewIn lastView:(UIView *)viewOut slideRight:(BOOL)isRight { 
UIGraphicsBeginImageContext(viewOut.frame.size); 

UIImageView *bitmapOut = [[UIImageView alloc] initWithFrame: viewOut.frame]; 

[viewOut.layer renderInContext:UIGraphicsGetCurrentContext()]; 
UIImage *viewOutImage = UIGraphicsGetImageFromCurrentImageContext(); 
UIGraphicsEndImageContext(); 
bitmapOut.image = viewOutImage; 

UIImageView *bitmapIn = [[UIImageView alloc] initWithFrame: viewIn.frame ]; 
bitmapIn.frame = CGRectMake(isRight ? 320 : -320, bitmapIn.frame.origin.y, bitmapIn.frame.size.width, bitmapIn.frame.size.height); 
UIGraphicsBeginImageContext(viewIn.frame.size); 

[viewIn.layer renderInContext:UIGraphicsGetCurrentContext()]; 
UIImage *viewInImage = UIGraphicsGetImageFromCurrentImageContext(); 
UIGraphicsEndImageContext(); 

bitmapIn.image = viewInImage; 

[self.view addSubview:transitionContainer]; 

[transitionContainer addSubview:bitmapIn]; 
[transitionContainer addSubview:bitmapOut]; 

[self removeAllViews]; 

[UIView beginAnimations:nil context:nil]; 
[UIView setAnimationDuration:0.5f]; 
[UIView setAnimationDelegate:self]; 
[UIView setAnimationDidStopSelector:@selector(swapViewsAtEndOfTransition:)]; 
transitionContainer.frame = CGRectMake(isRight ? -320 : 320, 0, 640, 411); 
[UIView commitAnimations]; 

[bitmapOut release]; bitmapOut = nil; 
[bitmapIn release]; bitmapIn = nil;} 

然後,在swapViewsAtEndOfTransition選擇可以相應地更新視圖。

0

幾年過去了,但我想我找到了一個解決方案。只需使用kCATransitionPush而不是kCATransitionReveal。像這樣:

- (CAAnimation *)animationWithDuration:(float)duration forward:(BOOL)forward { 
    CATransition *animation = [CATransition animation]; 
    [animation setType:kCATransitionPush]; 
    [animation setSubtype:forward?kCATransitionFromLeft:kCATransitionFromRight]; 
    [animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]]; 

    animation.duration = duration; 
    return animation; 
}