自定义dismiss转场动画,实现和pop一样的效果
2016-11-27 本文已影响122人
搬运工开发者
自定义dismiss转场动画,实现和pop一样的效果,如果想实现其他的效果基本思路也差不多
Untitled.gif1、首先实现dismissViewControllerAnimated动画,新建一个DismissTransitionAnimated类继承自NSObject,并遵守UIViewControllerAnimatedTransitioning协议
DismissTransitionAnimated.h文件
#import <Foundation/Foundation.h>
@interface DismissTransitionAnimated : NSObject
@end
DismissTransitionAnimated.m文件
#import "DismissTransitionAnimated.h"
#import <UIKit/UIKit.h>
@interface DismissTransitionAnimated ()<UIViewControllerAnimatedTransitioning>
@end
@implementation DismissTransitionAnimated
/** 动画时间 */
- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext{
return 1.0;
}
/** 定义动画 */
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext{
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIView *containerView = [transitionContext containerView];
UIView *fromView = nil;
UIView *toView = nil;
if ([transitionContext respondsToSelector:@selector(viewForKey:)]) {
fromView = [transitionContext viewForKey:UITransitionContextFromViewKey];
toView = [transitionContext viewForKey:UITransitionContextToViewKey];
}else{
fromView = fromViewController.view;
toView = toViewController.view;
}
BOOL isDismiss = (fromViewController.presentingViewController == toViewController);
CGRect fromFrame = [transitionContext initialFrameForViewController:fromViewController];
CGRect toFrame = [transitionContext finalFrameForViewController:toViewController];
if (isDismiss) {
fromView.frame = fromFrame;
toView.frame = CGRectOffset(toFrame, toFrame.size.width*0.3*-1, 0);
[containerView insertSubview:toView belowSubview:fromView];
}
NSTimeInterval transitionDuration = [self transitionDuration:transitionContext];
[UIView animateWithDuration:transitionDuration animations:^{
if (isDismiss) {
toView.frame = toFrame;
fromView.frame = CGRectOffset(fromFrame, fromFrame.size.width, 0);
}
} completion:^(BOOL finished) {
BOOL isCancel = [transitionContext transitionWasCancelled];
if (isCancel) {
[toView removeFromSuperview];
}
[transitionContext completeTransition:!isCancel];
}];
}
2、新建控制器ViewController, 并遵守UIViewControllerTransitioningDelegate
定义属性
@property (retain, nonatomic) UIPercentDrivenInteractiveTransition *percentDrivenTransition;
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
UIViewController *presentVC = [[UIViewController alloc]init];
presentVC.transitioningDelegate = self;
presentVC.view.backgroundColor = [UIColor redColor];
[self addScreenLeftEdgePanGestureRecognizer:presentVC.view];
[self presentViewController:presentVC animated:YES completion:nil];
}
- (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed {
return [[DismissTransitionAnimated alloc] init];
}
- (id<UIViewControllerInteractiveTransitioning>)interactionControllerForPresentation:(id<UIViewControllerAnimatedTransitioning>)animator{
return _percentDrivenTransition;
}
- (id<UIViewControllerInteractiveTransitioning>)interactionControllerForDismissal:(id<UIViewControllerAnimatedTransitioning>)animator{
return _percentDrivenTransition;
}
presentVC添加左边边缘滑动返回
- (void)addScreenLeftEdgePanGestureRecognizer:(UIView *)view{
UIScreenEdgePanGestureRecognizer *screenEdgePan = [[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:self action:@selector(edgePanGesture:)];
screenEdgePan.edges = UIRectEdgeLeft;
[view addGestureRecognizer:screenEdgePan];
}
- (void)edgePanGesture:(UIScreenEdgePanGestureRecognizer *)edgePan{
CGFloat progress = fabs([edgePan translationInView:[UIApplication sharedApplication].keyWindow].x/[UIApplication sharedApplication].keyWindow.bounds.size.width);
if (edgePan.state == UIGestureRecognizerStateBegan) {
self.percentDrivenTransition = [[UIPercentDrivenInteractiveTransition alloc]init];
if (edgePan.edges == UIRectEdgeLeft) {
[self dismissViewControllerAnimated:YES completion:nil];
}
}else if (edgePan.state == UIGestureRecognizerStateChanged){
[self.percentDrivenTransition updateInteractiveTransition:progress];
}else if (edgePan.state == UIGestureRecognizerStateEnded || edgePan.state == UIGestureRecognizerStateCancelled){
if (progress > 0.5) {
[_percentDrivenTransition finishInteractiveTransition];
}else{
[_percentDrivenTransition cancelInteractiveTransition];
}
_percentDrivenTransition = nil;
}
}