使用核心动画实现UIView翻转动画

4

亲爱的核心动画/iOS专家们,

我正在尝试实现与下面问题类似的效果。

Core animation animating the layer to flip horizontally

接受的答案似乎描述了我需要的内容,但是这个答案没有代码,而且我写的任何代码都无法工作。

这就是我想做的:
1)有一个主视图控制器/视图,在主视图的一部分上有两个UIView重叠,只显示一个(一个在“前面”,一个在“后面”)
2)单独的UIControl/UIButton被按下,然后发生3D翻转过渡,将前面(可见)的视图旋转到视野之外,同时将背面(隐藏)的视图旋转到前面...就像看到纸牌的反面。
3)能够继续按UIControl来在两个视图之间切换
4)能够仅与前面视图上的控件交互(即按下前面的层不会意外地触发位于点击下方的后面的控件)

我可能走了一条错误的路,所以请告诉我。理想情况下,我想使用核心动画(Core Animation),而不是UIView内置的翻转事务,因为我希望动画是3D的,并且想将此任务作为做更复杂CA内容的跳板。

目前,我可以很好地翻转正面视图(仅一次),但背面视图没有显示。

谢谢,
安迪

以下是我的代码:

MainViewController.h

@interface MainViewController : UIViewController
    - (IBAction)changeViewTapped:(UITapGestureRecognizer *)recognizer;
@end

MainViewController.m

#import "MainViewController.h"
#import <QuartzCore/QuartzCore.h>

@interface MainViewController ()

@property (weak, nonatomic) IBOutlet UIView *detailView;
@property (weak, nonatomic) IBOutlet UIView *listView;
@property (nonatomic) CATransform3D rotationAndPerspectiveTransform;

@end

@implementation MainViewController

@synthesize detailView = _detailView;
@synthesize listView = _listView;
@synthesize rotationAndPerspectiveTransform = _rotationAndPerspectiveTransform;

- (void)viewDidLoad {
    [super viewDidLoad];

    CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity;
    rotationAndPerspectiveTransform.m34 = 1.0 / -500;
    rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, M_PI, 0.0f, 1.0f, 0.0f);
    self.rotationAndPerspectiveTransform = rotationAndPerspectiveTransform;

    CALayer *listLayer = self.listView.layer;
    listLayer.doubleSided = NO;
    listLayer.transform = self.rotationAndPerspectiveTransform;
}

- (IBAction)changeViewTapped:(UITapGestureRecognizer *)recognizer {
    CALayer *detailLayer = self.detailView.layer;
    CALayer *listLayer = self.listView.layer;

    detailLayer.doubleSided = NO;
    listLayer.doubleSided = NO;

    [UIView animateWithDuration:0.5 animations:^{
        detailLayer.transform = self.rotationAndPerspectiveTransform;
        listLayer.transform = self.rotationAndPerspectiveTransform;
    } completion:^(BOOL finished){
        // code to be executed when flip is completed
    }];
}

@end
2个回答

3

iOS中翻转动画的一个小技巧——在启动翻转动画之前,系统需要时间来渲染背面视图(将要翻转到的视图)。因此,如果您尝试更改该视图的内容,并在同一方法中触发翻转动画,您将会遇到问题。

为了解决这个问题,我成功地使用了以下代码:

- (void)flipView {
   // Setup the view for the back side of the flip

   [self performSelector:@selector(performFlip) withObject:nil afterDelay: 0.1];
}

- (void)performFlip {
    [UIView transitionWithView: tileToFlip
                      duration: 0.5
                       options: UIViewAnimationOptionTransitionFlipFromLeft
                    animations:^{
                        // My flip specific code
                    }
                    completion:^(BOOL finished) {
                    }
     ];
}

简而言之,我正在flipView方法中设置一切,将控制权返回给iOS以便有时间进行渲染,然后在十分之一秒后启动flipTile选择器来执行实际的动画。
祝你好运!

2
这不应该是[self performSelector:@selector(performFlip) withObject:nil afterDelay: 0.1];吗?使用performFlip而不是flipTile? - Wesley Smith

0
- (void)perform
{
   UIViewController *src = (UIViewController *) self.sourceViewController;
   UIViewController *dst = (UIViewController *) self.destinationViewController;    

  [UIView beginAnimations:@"LeftFlip" context:nil];
  [UIView setAnimationDuration:0.8];
  [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
  [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft    forView:src.view.superview cache:YES];
  [UIView commitAnimations];

  [src presentViewController:dst animated:NO completion:nil];
 }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接