iOS 利用UIPresentationController自定义转场动画
1. 系统默认modal出来的动画效果默认是从屏幕底部爬出来的
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
secondVC *second = [[secondVC alloc] init];
[self presentViewController:second animated:YES completion:nil];
}
2. 想自定义转场动画,首先设置 展示样式 和 过渡代理
secondVC *second = [[secondVC alloc] init];
second.modalPresentationStyle = UIModalPresentationCustom;
second.transitioningDelegate = self;
[self presentViewController:second animated:YES completion:nil];
3.实现过渡代理方法,告诉程序" 哪个对象管理控制器的展示 "
- (UIPresentationController *)presentationControllerForPresentedViewController:(UIViewController *)presented presentingViewController:(UIViewController *)presenting sourceViewController:(UIViewController *)source
{
return [[MYPresentationController alloc]initWithPresentedViewController:presented presentingViewController:presenting];
}
4.自定义UIPresentationController
// MYPresentationController.h
@interface MYPresentationController : UIPresentationController
@end
// MYPresentationController.m
#import "MYPresentationController.h"
@implementation MYPresentationController
- (CGRect)frameOfPresentedViewInContainerView
{
return CGRectMake(100, 100, 150, 300); //设置modal出来控制器的frame
}
// 下面这几个方法,监听Modal控制器时的各种状态
- (void)presentationTransitionWillBegin
{
NSLog(@"presentationTransitionWillBegin");
}
- (void)presentationTransitionDidEnd:(BOOL)completed
{
NSLog(@"presentationTransitionDidEnd");
}
- (void)dismissalTransitionWillBegin
{
NSLog(@"presentationTransitionDidEnd");
}
- (void)dismissalTransitionDidEnd:(BOOL)completed
{
NSLog(@"dismissalTransitionDidEnd");
}
@end
5. 到了第4步,也只是做到了自定义展示,可以监听展示的过程,可以设置展示的frame.
要想实现自定义转场动画,可以考虑设置second.modalTransitionStyle,但是没有UIModalTransitionStyleCustom,是因为
只要设置了UIModalPresentationCustom,也就相当于设置了"UIModalTransitionStyleCustom",要想实现自定义转场动画,只要实现相应的代理方法即可
secondVC *second = [[secondVC alloc] init];
second.modalPresentationStyle = UIModalPresentationCustom;
second.transitioningDelegate = self;
second.modalTransitionStyle = UIModalTransitionStyleCoverVertical; // 要实现自定义转场动画,不是在这里设置
[self presentViewController:second animated:YES completion:nil];
#pragma mark - 自定义转场动画的代理方法,两个,分别控制显示和消失
- (id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source
{
return self; // 简单处理,返回self,只要self遵守<UIViewControllerAnimatedTransitioning>协议
}
- (id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed
{
return self;
}
6.实现<UIViewControllerAnimatedTransitioning>协议方法,下面两个协议方法是必须实现的
- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext{
return 0.3;
}
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext{
UIView *toView = [transitionContext viewForKey:UITransitionContextToViewKey];
toView.y = -toView.height;
[UIView animateWithDuration:0.3 animations:^{
toView.y = 0;
} completion:^(BOOL finished) {
[transitionContext completeTransition:YES]; //这个必须写,否则程序 认为动画还在执行中,会导致展示完界面后,无法处理用户的点击事件
}];
}
这样就实现了modal出来的控制器,是从屏幕顶部下来的转场动画
7. 要实现 控制器消失时的动画,怎么办
7.1 新增一个类,该类遵守<UIViewControllerAnimatedTransitioning>,新增一个属性,用来区别 显示或消失
// MYAnimatedTransition.h
@interface MYAnimatedTransition : NSObject<UIViewControllerAnimatedTransitioning>
@property (assign,nonatomic) BOOL show;
@end
// MYAnimatedTransition.m
@implementation MYAnimatedTransition
- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext
{
return 0.3;
}
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext
{
if (self.show == YES) { // 显示
UIView *toView = [transitionContext viewForKey:UITransitionContextToViewKey];
toView.y = -toView.height;
[UIView animateWithDuration:0.3 animations:^{
toView.y = 0;
} completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
}];
}else{ // 消失
UIView *fromView = [transitionContext viewForKey:UITransitionContextFromViewKey];
[UIView animateWithDuration:0.3 animations:^{
fromView.y = fromView.height;
} completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
}];
}
}
@end
7.2 修改自定义转场动画的代理方法,返回MYAnimatedTransition类对象
#pragma mark - 自定义转场动画的代理方法,两个,分别控制显示和消失
- (id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source
{
MYAnimatedTransition *anima = [[MYAnimatedTransition alloc]init];
anima.show = YES;
return anima;
}
- (id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed
{
MYAnimatedTransition *anima = [[MYAnimatedTransition alloc]init];
anima.show = NO;
return anima;
}
7.3 修改自定义UIPresentationController的.m文件
- (void)presentationTransitionWillBegin{
NSLog(@"presentationTransitionWillBegin");
[self.containerView addSubview:self.presentedView]; // 因为是自定义转场动画,所以添加视图的工作也需要自行实现
}
而且下面这个方法作废了,程序是不会执行的,因为你是自定义转场动画,动画前后的Frame都已经在这个方法实现了: - (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext
- (CGRect)frameOfPresentedViewInContainerView
{
return CGRectMake(100, 100, 150, 300);
}
7.4 要实现更复杂的转场动画,只要改下面这个方法,比如改成3D旋转
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext
{
UIView *toView = [transitionContext viewForKey:UITransitionContextToViewKey];
// toView.y = -toView.height;
toView.layer.transform = CATransform3DMakeRotation(M_PI_2, 0, 1, 0);
[UIView animateWithDuration:0.3 animations:^{
// toView.y = 0;
toView.layer.transform = CATransform3DIdentity;
} completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
}];
}else{
UIView *fromView = [transitionContext viewForKey:UITransitionContextFromViewKey];
[UIView animateWithDuration:0.3 animations:^{
// fromView.y = fromView.height;
fromView.layer.transform = CATransform3DMakeRotation(M_PI_2, 0, 1, 0);
} completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
}];
}
}
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。