[IOS 开发] 格瓦拉 控制器之间的换场动画。
2016-06-08 17:13
465 查看
先上框架类HYAwesomeTransition
HYAwesomeTransition.h
//
// HYAwesomTransition.h
// HYAwesomeTransitionDemo
//
// Created by nathan on 15/7/30.
// Copyright (c) 2015年 nathan. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface HYAwesomeTransition : NSObject<UIViewControllerAnimatedTransitioning>
@property (nonatomic, assign)CGFloat duration;
@property (nonatomic, assign)CGRect finalFrame;
@property (nonatomic, strong)UIView *containerBackgroundView;
@property (nonatomic, getter=isPresent)BOOL present;
- (void)registerStartFrame:(CGRect)startFrame
finalFrame:(CGRect)finalFrame
transitionView:(UIView *)transitionView;
@end
// 版权属于原作者
// http://code4app.com (cn) http://code4app.net (en)
// 发布代码于最专业的源码分享网站: Code4App.com
HYAwesomeTransition.m
//
// HYAwesomTransition.m
// HYAwesomeTransitionDemo
//
// Created by nathan on 15/7/30.
// Copyright (c) 2015年 nathan. All rights reserved.
//
#import "HYAwesomeTransition.h"
@interface HYAwesomeTransition()
@property (nonatomic, strong)UIView *snapshotView;
@property (nonatomic, assign)CGRect startFrame;
@property (nonatomic, copy) void (^completion)(BOOL finished);
@end
@implementation HYAwesomeTransition
- (void)registerStartFrame:(CGRect)startFrame
finalFrame:(CGRect)finalFrame
transitionView:(UIView *)transitionView {
_startFrame = startFrame;
_finalFrame = finalFrame;
_snapshotView = [transitionView snapshotViewAfterScreenUpdates:NO];
_snapshotView.layer.shadowOpacity = 0.5;
_snapshotView.layer.shadowRadius = 3;
_snapshotView.layer.shadowColor = [UIColor lightGrayColor].CGColor;
_snapshotView.layer.shadowOffset = CGSizeMake(5, 5);
}
- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext
{
return self.duration;
}
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext
{
if (self.present) {
[self presentWithTransiton:transitionContext];
}else{
[self dismissWithTranstion:transitionContext];
}
}
- (void)presentWithTransiton:(id <UIViewControllerContextTransitioning>)transitionContext{
UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIView *containerView = [transitionContext containerView];
if (self.containerBackgroundView) {
self.containerBackgroundView.frame = containerView.bounds;
self.containerBackgroundView.alpha = 0.0;
[containerView addSubview:self.containerBackgroundView];
}
[containerView addSubview:toVC.view];
NSTimeInterval duration = [self transitionDuration:transitionContext];
CGFloat x = _finalFrame.origin.x - _startFrame.origin.x;
CGFloat y = _finalFrame.origin.y - _startFrame.origin.y;
UIView *snapshotView = self.snapshotView;
snapshotView.frame = _startFrame;
[containerView addSubview:snapshotView];
CATransform3D upViewTransfrom = CATransform3DIdentity;
upViewTransfrom.m34 = 1.0 / -1000;
upViewTransfrom = CATransform3DTranslate(upViewTransfrom, 0, 0, 100);
CATransform3D middleViewTranfrom = CATransform3DTranslate(upViewTransfrom, x, y, 0);
CATransform3D downViewTranfrom = CATransform3DTranslate(middleViewTranfrom, 0, 0, -100);
toVC.view.hidden = YES;
NSTimeInterval partDuration = duration / 3;
[UIView animateKeyframesWithDuration:partDuration * 3 delay:0 options:UIViewKeyframeAnimationOptionCalculationModeLinear animations:^{
[UIView addKeyframeWithRelativeStartTime:0 relativeDuration:0.5 animations:^{
snapshotView.layer.transform = upViewTransfrom;
fromVC.view.alpha = 0.0;
if (self.containerBackgroundView) {
self.containerBackgroundView.alpha = 1.0;
}
}];
[UIView addKeyframeWithRelativeStartTime:0.5 relativeDuration:0.5 animations:^{
snapshotView.layer.transform = middleViewTranfrom;
}];
} completion:^(BOOL finished) {
toVC.view.hidden = NO;
CGRect rect = CGRectInset(_finalFrame, -500, -500);
CGPathRef startPath = CGPathCreateWithEllipseInRect(rect, NULL);
CGPathRef endPath = CGPathCreateWithEllipseInRect(_finalFrame, NULL);
CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
maskLayer.path = startPath;
toVC.view.layer.mask = maskLayer;
CABasicAnimation *pingAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
pingAnimation.fromValue = (__bridge id)(endPath);
pingAnimation.toValue = (__bridge id)(startPath);
pingAnimation.duration = partDuration;
pingAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[maskLayer addAnimation:pingAnimation forKey:@"pingInvert"];
CGPathRelease(startPath);
CGPathRelease(endPath);
[UIView animateWithDuration:partDuration animations:^{
snapshotView.layer.transform = downViewTranfrom;
} completion:^(BOOL finished) {
fromVC.view.alpha = 1.0;
if (self.containerBackgroundView) {
[self.containerBackgroundView removeFromSuperview];
}
[maskLayer removeFromSuperlayer];
[snapshotView removeFromSuperview];
[transitionContext completeTransition:YES];
}];
}];
}
- (void)dismissWithTranstion:(id <UIViewControllerContextTransitioning>)transitionContext{
UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIView *containerView = [transitionContext containerView];
[containerView addSubview:toVC.view];
if (self.containerBackgroundView) {
self.containerBackgroundView.frame = containerView.bounds;
[containerView addSubview:self.containerBackgroundView];
}
[containerView addSubview:fromVC.view];
CGFloat x = _startFrame.origin.x - _finalFrame.origin.x;
CGFloat y = _startFrame.origin.y - _finalFrame.origin.y;
UIView *snapshotView = self.snapshotView;
snapshotView.transform = CGAffineTransformIdentity;
snapshotView.frame = _finalFrame;
[containerView addSubview:snapshotView];
toVC.view.hidden = YES;
CATransform3D upViewTransfrom = CATransform3DIdentity;
upViewTransfrom.m34 = 1.0 / -1000;
upViewTransfrom = CATransform3DTranslate(upViewTransfrom, 0, 0, 100);
CATransform3D middleViewTranfrom = CATransform3DTranslate(upViewTransfrom, x, y, 0);
CATransform3D downViewTranfrom = CATransform3DTranslate(middleViewTranfrom, 0, 0, -100);
NSTimeInterval partDuration = [self transitionDuration:transitionContext] / 3;
CGRect rect = CGRectInset(_finalFrame, -500, -500);
CGPathRef endPath = CGPathCreateWithEllipseInRect(rect, NULL);
CGPathRef startPath = CGPathCreateWithEllipseInRect(_finalFrame, NULL);
CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
maskLayer.path = startPath;
fromVC.view.layer.mask = maskLayer;
CABasicAnimation *pingAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
pingAnimation.fromValue = (__bridge id)(endPath);
pingAnimation.toValue = (__bridge id)(startPath);
pingAnimation.duration = partDuration;
pingAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[maskLayer addAnimation:pingAnimation forKey:@"pingInvert"];
CGPathRelease(startPath);
CGPathRelease(endPath);
[UIView animateWithDuration:partDuration anima
4000
tions:^{
snapshotView.layer.transform = upViewTransfrom;
} completion:^(BOOL finished) {
[fromVC.view removeFromSuperview];
toVC.view.hidden = NO;
[UIView animateKeyframesWithDuration:partDuration * 2 delay:0 options:UIViewKeyframeAnimationOptionCalculationModeLinear animations:^{
[UIView addKeyframeWithRelativeStartTime:0 relativeDuration:0.5 animations:^{
snapshotView.layer.transform = middleViewTranfrom;
}];
[UIView addKeyframeWithRelativeStartTime:0.5 relativeDuration:0.5 animations:^{
snapshotView.layer.transform = downViewTranfrom;
if (self.containerBackgroundView) {
self.containerBackgroundView.alpha = 0.0;
}
}];
} completion:^(BOOL finished) {
if (self.containerBackgroundView) {
[self.containerBackgroundView removeFromSuperview];
}
[snapshotView removeFromSuperview];
[transitionContext completeTransition:YES];
}];
}];
}
@end
// 版权属于原作者
// http://code4app.com (cn) http://code4app.net (en)
// 发布代码于最专业的源码分享网站: Code4App.com
Example
self.awesometransition = [[HYAwesomeTransition alloc] init]; self.awesometransition.duration = 2.0f; self.awesometransition.containerBackgroundView = customView; [self.awesometransition registerStartFrame:startFrame finalFrame:finalFrame transitionView:cell]; [self presentViewController:vc animated:YES completion:^{ vc.avatar.hidden = NO; }];
Implement
UIViewControllerTransitioningDelegateand this delegate method:
- (id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source { self.awesometransition.present = YES; return self.awesometransition; } - (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed { self.awesometransition.present = NO; return self.awesometransition; }
If you use
UINavigationController,you have to implement
UINavigationControllerDelegateinstead of
UIViewControllerTransitioningDelegate, but interactive gesture is not suppored yet.
- (id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC{ if (operation != UINavigationControllerOperationPush) { self.awesometransition.present = NO; }else{ self.awesometransition.present = YES; } return self.awesometransition; }
相关文章推荐
- iOS应用崩溃日志揭秘
- iOS监听电话来电、挂断、拨号等
- 【iOS开发】事件处理之响应链(二)
- ios开发经典语录锦集
- 第三方解决键盘遮挡问题总结(IQKeyboardManager)
- 【雕虫小计win PE】使用GHOST备份还原操作系统(转载)
- iOS单元测试UnitTest
- iOS开发 关于MD5加密的相关使用
- IOS 内支付那点事
- iOS Xcode中SVN的配置
- iOS - 二维码扫描和应用跳转
- ios开源框架--iOS-Universal-Framework的配置环境和使用
- LaunchImage和LaunchScreen.xib混用出现的坑
- iOS 音乐播放器(一)
- iOS Alcatraz 插件管理
- iOS学习应用开发就业课:第7章_060:导航控制器动画
- iOS改变系统中的英文为汉语
- 【iOS】获取视图的中心和宽高
- iOS:你真的理解你在用的自定义NSLog吗?
- iOS GCD dispatch多线程 同步异步