方法1: 利用控制器的 transitionFromViewController:toViewController: ... 方法转场,from, to两个控制器必须是同一个控制器的子控制器
BigPhotoViewController *bigVc = [[BigPhotoViewController alloc] init];
[self addChildViewController:bigVc];
bigVc.image = self.array[indexPath.item];
// [self presentViewController:bigVc animated:YES completion:nil];
bigVc.view.alpha = 0.0;
// 1. 利用控制器的 transitionFromViewController:toViewController: ... 方法转场,from, to两个控制器必须是同一个控制器的子控制器
[self transitionFromViewController:self.vc1 toViewController:bigVc duration:0.5 options:UIViewAnimationOptionCurveLinear animations:^{
bigVc.view.alpha = 1.0;
} completion:nil];
方法2: 利用CoreAnimation的CATransition
BigPhotoViewController *bigVc = [[BigPhotoViewController alloc] init];
bigVc.image = self.array[indexPath.item];
// 2. 利用CATransition
CATransition *transition = [CATransition animation];
transition.type = @"cube";
[self.view.layer addAnimation:transition forKey:nil];
[self presentViewController:bigVc animated:YES completion:nil];
方法3: 利用转场代理transitioningDelegate
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
BigPhotoViewController *bigVc = [[BigPhotoViewController alloc] init];
bigVc.image = self.array[indexPath.item];
bigVc.modalPresentationStyle = UIModalPresentationCustom;
// 3. 利用转场代理
bigVc.transitioningDelegate = self.animator;
self.animator.delegate = self;
self.animator.indexPath = indexPath;
[self presentViewController:bigVc animated:YES completion:nil];
}
需要遵守<UIViewControllerTransitioningDelegate>协议的对象animator做代理
@interface BigPhotoAnimator : NSObject <UIViewControllerTransitioningDelegate, UIViewControllerAnimatedTransitioning>
// 自定义遵守<UIViewControllerTransitioningDelegate>协议的对象, 实现下面方法(present时 / dismiss时各一个)
#pragma mark - <UIViewControllerTransitioningDelegate>
// 出现时的动画对象
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source
{
self.isPresentAnimate = YES;
return self;
}
/*
* 消失时的动画对象
*/
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed
{
self.isPresentAnimate = NO;
return self;
}
这两个方法的返回对象必须遵守<UIViewControllerAnimatedTransitioning>协议, 可以返回自定义对象本身,让该对象遵守<UIViewControllerAnimatedTransitioning>协议,实现以下方法
#pragma mark - <UIViewControllerAnimatedTransitioning>
// 动画时间
- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext
{
return 0.5;
}
// 具体动画实现
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
// 通过上下文获得from控制器
UIViewController *fromVc = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
// 通过上下文获得to控制器
UIViewController *toVc = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
// 通过上下文获得from的view
UIView *fromView = [transitionContext viewForKey:UITransitionContextFromViewKey];
// 通过上下文获得to的view
UIView *toView = [transitionContext viewForKey:UITransitionContextToViewKey];
// 获取动画时间
NSTimeInterval duration = [self transitionDuration:transitionContext];
if (self.isPresentAnimate) { // 弹出动画
toView.alpha = 0.0;
UIImage *image = nil;
CGRect rect = CGRectZero;
// 自定义协议,通过代理实现协议的方法获得要做动画的imageView的图片和大小
if (_delegate) {
image = [_delegate animator:self ImageForIndexPath:self.indexPath];
rect = [_delegate animator:self RectForIndexPath:self.indexPath];
}
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
imageView.frame = rect;
// 把要动画的view添加到containerView 记得!!
[[transitionContext containerView] addSubview:toView];
[[transitionContext containerView] addSubview:imageView];
toView.alpha = 0.0;
// 动画实现
[UIView animateWithDuration:duration animations:^{
imageView.frame = [UIScreen mainScreen].bounds;
} completion:^(BOOL finished) {
[imageView removeFromSuperview];
toView.alpha = 1.0;
// 通过上下文通知动画结束
[transitionContext completeTransition:YES];
}];
}
else { // 消失动画
toView.alpha = 0.0;
UIImage *image = nil;
CGRect rect = CGRectZero;
// 自定义协议,通过代理实现协议的方法获得要做动画的imageView的图片和大小
if (_delegate) {
image = [_delegate animator:self ImageForIndexPath:self.indexPath];
rect = [_delegate animator:self RectForIndexPath:self.indexPath];
}
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
imageView.frame = [UIScreen mainScreen].bounds;
// 添加到containerView
[[transitionContext containerView] addSubview:imageView];
[[transitionContext containerView] addSubview:fromView];
fromView.alpha = 0.0;
// 动画实现
[UIView animateWithDuration:duration animations:^{
imageView.frame = rect;
} completion:^(BOOL finished) {
[imageView removeFromSuperview];
// 通过上下文通知动画结束
[transitionContext completeTransition:YES];
}];
}