iOS自定义转场动画
来源:互联网 发布:兄弟绣花机软件 编辑:程序博客网 时间:2024/05/01 23:12
iOS自定义转场动画
本文主要简单讲解iOS中的自定义转场动画,也主要是源于自己在开发过程中,自己的一点感悟。其实,转场使我们开发中经常遇到的事情,大多数情况下,我们使用模态显示或者UINavigationController的push和pop操作实现转场,不过这两种形式的转场效果是固定的,没法自定义转场动画,因此,如果需要实现自定义动画效果,这些显然很难实现。
UIView基于block实现的转场动画
其实,UIView也提供了可以转场的方法,其实下面这几个方法也可以实现转场,根据UIViewAnimationOptions的不同,也可以实现不同的转场动画,也可以算是一种简单的自定义转场,具体的用法大家可以查阅官方文档。
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay usingSpringWithDamping:(CGFloat)dampingRatio initialSpringVelocity:(CGFloat)velocity options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(7_0);+ (void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^ __nullable)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(4_0);+ (void)transitionFromView:(UIView *)fromView toView:(UIView *)toView duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(4_0); // toView added to fromView.superview, fromView removed from its superview
使用这种block的形式,其实最大的好处就是比较直观,转场需要的元素都能够清晰的看见,比如:fromView,toView,duration,animation等,但是也有一个缺陷,就是重用性不高,基本每次转场都需要重新写一遍,再者,也不能真正的实现自定义动画,毕竟,options的选择是有限的,动画效果就那几种。
From和To的概念
通过上面的方法,我们反复看见fromView和toView,这个其实很好理解,fromView也就是当前视图,toView也就是需要跳转的视图。如果是从A视图控制器present到B,则A是from,B是to。从B视图控制器dismiss到A时,B变成了from,A是to,如下:
自定义present转场动画
首先,需要简单介绍几个概念:
1.The Transitioning Delegate
要想实现自定的转场效果,首先必须理解transitionDelegate的概念,以往的模态显示时候,我们没有关注这个,因为我们不需要实现自定转场效果,如果要实现自定义转场动画效果,需要借助transitionDelegate提供的方法:
@optional- (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source;- (nullable id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed;- (nullable id <UIViewControllerInteractiveTransitioning>)interactionControllerForPresentation:(id <UIViewControllerAnimatedTransitioning>)animator;- (nullable id <UIViewControllerInteractiveTransitioning>)interactionControllerForDismissal:(id <UIViewControllerAnimatedTransitioning>)animator;- (nullable UIPresentationController *)presentationControllerForPresentedViewController:(UIViewController *)presented presentingViewController:(UIViewController *)presenting sourceViewController:(UIViewController *)source NS_AVAILABLE_IOS(8_0);
这里的方法还是比较容易理解的,我们就是需要自己实现这些方法,来实现自定义动画效果。
2.Animator objects
在animator中我们可以自定义动画的实现效果,转场动画长什么样子,就要看我们怎么去实现animator,在其中我们要控制动画时间和动画逻辑。
3.Interactive animator objects
这个跟animator一样,只是适用交互式动画,主要就是根据手势动作控制转场的变化。
4.Presentation controller
它可以对present过程更加彻底的自定义,比如修改被展示视图的大小,新增自定义视图等,也可以自定实现。
下图详细介绍了transitioning delegate和animator objects,以及presentation controller之间的层级关系,
实现过程
1.创建代理
如果是从A present 到B,可以使用A 或者 B 实现UIViewControllerTransitioningDelegate,
2.设置代理
需要将1中实现delegate的viewController赋值给B的transitioningDelegate。
3.调用Present方法
调用presentViewController:animated:completion:并把参数animated设置为true
4.提供Animator
在实现UIViewControllerTransitioningDelegate的方法中,需要提供实现动画的animator
具体实现如下:
这里是跳转的相关设置
- (IBAction)toMyView:(UIButton *)sender { self.myController.modalPresentationStyle = UIModalPresentationCustom; //设置代理 self.myController.transitioningDelegate = self.myController; [self presentViewController:self.myController animated:YES completion:nil];}
接下来最终的就是提供实现具体转场动画的animatior:这里只提供了一个animator,读者也可以根据present和dismiss实现不同的animator。
#import "MyAnimator.h"@implementation MyAnimator- (NSTimeInterval)transitionDuration:(nullable id <UIViewControllerContextTransitioning>)transitionContext{ return [transitionContext isAnimated] ? 0.5 : 0.5;}- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext{ // Get the set of relevant objects. UIView *containerView = [transitionContext containerView]; UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]; UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; UIView *toView = [transitionContext viewForKey:UITransitionContextToViewKey]; UIView *fromView = [transitionContext viewForKey:UITransitionContextFromViewKey]; // Set up some variables for the animation. CGRect containerFrame = containerView.frame; CGRect toViewStartFrame = [transitionContext initialFrameForViewController:toVC]; CGRect toViewFinalFrame = [transitionContext finalFrameForViewController:toVC]; CGRect fromViewFinalFrame = [transitionContext finalFrameForViewController:fromVC]; // Set up the animation parameters. if (self.isPresented) { // Modify the frame of the presented view so that it starts // offscreen at the lower-right corner of the container. toViewStartFrame.origin.x = containerFrame.size.width; toViewStartFrame.origin.y = containerFrame.size.height; } else { // Modify the frame of the dismissed view so it ends in // the lower-right corner of the container view. fromViewFinalFrame = CGRectMake(containerFrame.size.width, containerFrame.size.height, toView.frame.size.width, toView.frame.size.height); } // Always add the "to" view to the container. // And it doesn't hurt to set its start frame. [containerView addSubview:toView]; toView.frame = toViewStartFrame; // Animate using the animator's own duration value. [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{ if (self.isPresented) { // Move the presented view into position. [toView setFrame:toViewFinalFrame]; } else { // Move the dismissed view offscreen. [fromView setFrame:fromViewFinalFrame]; } } completion:^(BOOL finished){ BOOL success = ![transitionContext transitionWasCancelled]; // After a failed presentation or successful dismissal, remove the view. if ((self.isPresented && !success) || (!self.isPresented && success)) { [toView removeFromSuperview]; } // Notify UIKit that the transition has finished [transitionContext completeTransition:success]; }];}
这里,大家可能注意到了一个核心的概念,那就是transitionContext,这个是实现转场的上下文,从中我们可以获取转场需要的基本信息,例如fromView和toView等,下图介绍了transitionContext和其他objects之间的关系:
其实转场需要的基本信息,都可以通过transitionContext获取,然后实现自定的转场动画,动画的实现形式不同,自然转场的效果也就不一样,其实,最关键的也就是animator的实现方式。
到此,一个简单的自定义转场动画就实现了,大家可以参考一下。
总结
这里只是简单讲解了非交互式的转场动画实现效果,对于交互式动画的实现形式跟这个差不多,只是实现的animator不一样,更详细的讲解,大家可以参考以下资料:
iOS自定义转场动画实战讲解
官网介绍
大家可以去我的github上下载demo:CustomTransitionTest,如果觉得有帮助还望给个star以示支持。自定义动画中要学习的东西还很多,本文只是基于个人的理解,有不合适的地方,欢迎互相交流。
- iOS自定义转场动画
- iOS自定义转场动画
- IOS 自定义转场动画。
- iOS自定义转场动画
- iOS 自定义转场动画
- iOS自定义转场动画
- iOS - 自定义转场动画
- iOS自定义转场动画
- iOS自定义转场动画
- iOS自定义转场动画
- iOS之转场动画/自定义转场动画
- iOS 自定义push转场动画
- iOS 自定义转场动画篇
- 关于 iOS自定义转场动画
- iOS 自定义转场动画初探
- ios-自定义转场动画基础
- iOS 8自定义动画转场上手指南
- iOS 8自定义动画转场上手指南
- 动态网站访问过程——php语言
- bzoj2287【POJ Challenge】消失之物
- JavaScript特效5-完整tab选项卡
- poj 3259 Wormholes (Bellman-ford)
- bzoj1996【HNOI2010】chorus 合唱队
- iOS自定义转场动画
- quartz系列(三):定时任务的集群使用
- 使用CircularReveal动画效果切换页面
- bzoj1584【Usaco2009 Mar】Cleaning Up 打扫卫生
- CodeForces 611 D. New Year and Ancient Prophecy(dp)
- sublime text 3 快捷键汇总
- 机器学习(Machine Learning)&深度学习(Deep Learning)资料(Chapter 1)
- Typedef和define
- LeetCode题解:Number of 1 Bits