iOS转场动画封装
2024-08-28 08:17:41
写在前面
iOS在modal 或push等操作时有默认的转场动画,但有时候我们又需要特定的转场动画效果,从iOS7开始,苹果就提供了自定义转场的API,模态推送present和dismiss、导航控制器push和pop、标签控制器的控制器切换都可以自定义转场。
自定义转场动画的实现步骤如下:
1、遵循<UIViewControllerAnimatedTransitioning>
协议的动画过渡管理对象,两个必须实现的方法:
public func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval
// This method can only be a nop if the transition is interactive and not a percentDriven interactive transition.
public func animateTransition(transitionContext: UIViewControllerContextTransitioning)
// This is a convenience and if implemented will be invoked by the system when the transition context's completeTransition: method is invoked.
optional public func animationEnded(transitionCompleted: Bool)
2、继承于UIPercentDrivenInteractiveTransition
的手势过渡管理对象,动画的过程是通过百分比控制的。如果不需要手势控制,这一步可不实现。
UIViewControllerInteractiveTransitioning { // This is the non-interactive duration that was returned when the
// animators transitionDuration: method was called when the transition started.
public var duration: CGFloat { get } // The last percentComplete value specified by updateInteractiveTransition:
public var percentComplete: CGFloat { get } // completionSpeed defaults to 1.0 which corresponds to a completion duration of
// (1 - percentComplete)*duration. It must be greater than 0.0. The actual
// completion is inversely proportional to the completionSpeed. This can be set
// before cancelInteractiveTransition or finishInteractiveTransition is called
// in order to speed up or slow down the non interactive part of the
// transition.
public var completionSpeed: CGFloat // When the interactive part of the transition has completed, this property can
// be set to indicate a different animation curve. It defaults to UIViewAnimationCurveEaseInOut.
// Note that during the interactive portion of the animation the timing curve is linear.
public var completionCurve: UIViewAnimationCurve // These methods should be called by the gesture recognizer or some other logic
// to drive the interaction. This style of interaction controller should only be
// used with an animator that implements a CA style transition in the animator's
// animateTransition: method. If this type of interaction controller is
// specified, the animateTransition: method must ensure to call the
// UIViewControllerTransitionParameters completeTransition: method. The other
// interactive methods on UIViewControllerContextTransitioning should NOT be
// called. public func updateInteractiveTransition(percentComplete: CGFloat)
public func cancelInteractiveTransition()
public func finishInteractiveTransition()
3、成为相应的代理,实现UIViewControllerAnimatedTransitioning的代理方法,返回我们前两步自定义的对象。
模态推送实现的代理方法
@available(iOS 2.0, *)
optional public func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? @available(iOS 2.0, *)
optional public func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? optional public func interactionControllerForPresentation(animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? optional public func interactionControllerForDismissal(animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? @available(iOS 8.0, *)
optional public func presentationControllerForPresentedViewController(presented: UIViewController, presentingViewController presenting: UIViewController, sourceViewController source: UIViewController) -> UIPresentationController?
转场动画Demo
下面直接看demo,封装自定义的转场动画实现图片在两个控制器间放大过渡的动画效果,面向协议进行开发,使用时将转场动画代理设置为SZAnimator。
import UIKit
protocol SZAnimatorPresentDelegate: NSObjectProtocol { // 负责提供弹出动画的视图
func presentView() -> UIView
func presentFrameRect() -> CGRect
func presentToRect() -> CGRect
} protocol SZAnimatorDimissDelegate: NSObjectProtocol { // 负责提供dismiss动画的视图
func dismissView() -> UIView
func dismissFrameRect() -> CGRect
func dismissToRect() -> CGRect
} class SZAnimator: NSObject {
var isPresent: Bool = true
weak var presentDelegate: SZAnimatorPresentDelegate?
weak var dismissDelegate: SZAnimatorDimissDelegate?
} extension SZAnimator: UIViewControllerTransitioningDelegate { // 指定弹出时,处理动画的对象
func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
isPresent = true
return self
} // 指定弹下去时候, 处理动画的对象
func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
isPresent = false
return self
}
} // 消失动画
// 弹出动画
extension SZAnimator: UIViewControllerAnimatedTransitioning { // 返回动画的时间
func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
return 2.0
} // 在这里, 实现真正的弹出, 或者消失的动画
// transitionContext
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
isPresent ? present(transitionContext) : dismiss(transitionContext)
} func dismiss(transitionContext: UIViewControllerContextTransitioning) { // 自定义动画
// 面向协议进行开发
// 1. 拿什么界面做动画
// 2. fromRect
// 3. toRect let animationView = dismissDelegate!.dismissView()
transitionContext.containerView()?.addSubview(animationView) // 初始的frame
animationView.frame = dismissDelegate!.dismissFrameRect()
// 最终需要展示的视图
if #available(iOS 8.0, *) {
let fromView = transitionContext.viewForKey(UITransitionContextFromViewKey) // 动画
UIView.animateWithDuration(transitionDuration(transitionContext), animations: {
// toView?.alpha = 1
animationView.frame = self.dismissDelegate!.dismissToRect()
fromView?.alpha =
}) { (flag: Bool) in
animationView.removeFromSuperview()
transitionContext.completeTransition(true)
}
}
} func present(transitionContext: UIViewControllerContextTransitioning) {
// 自定义动画
// 面向协议进行开发
// 1. 拿什么界面做动画
// 2. fromRect
// 3. toRect let animationView = presentDelegate!.presentView()
transitionContext.containerView()?.addSubview(animationView) // 初始的frame
animationView.frame = presentDelegate!.presentFrameRect() // 最终需要展示的视图
if #available(iOS 8.0, *) {
let toView = transitionContext.viewForKey(UITransitionContextToViewKey) toView?.frame = UIScreen.mainScreen().bounds
transitionContext.containerView()?.addSubview(toView!)
toView?.alpha = // 动画
UIView.animateWithDuration(2.0, animations: {
toView?.alpha =
animationView.frame = self.presentDelegate!.presentToRect()
}) { (flag: Bool) in animationView.removeFromSuperview()
transitionContext.completeTransition(true)
}
}
}
}
最新文章
- CSAW2013
- Oracl各个版本的下载地址
- LeetCode49 Group Anagrams
- _doPostBack用法总结
- Poj 3061 Subsequence(二分+前缀和)
- 转:PHP 使用ZipArchive压缩文件并下载
- Android仿微信朋友圈图片浏览器(支持图片手势缩放,拖动)
- 在Debian或Ubuntu中安装和使用&#39;搜狗输入法for linux&#39;
- 中文代码示例之5分钟入门TypeScript
- docker安装小笔记
- Android数据存储引擎---SQLite数据库
- NAVICAT 12.0.24 连接 MYSQL8.0.12 的方法
- 常用的PostBuild Event 脚本
- 记录Ubuntu14.04 LTS版本中使用Docker的过程
- Drools5
- mvc Ajax 跨域请求
- Canal入门
- 查看Memcache运行状况
- 「USACO13MAR」「LuoguP3080」 牛跑The Cow Run (区间dp
- webstorm for mac
热门文章
- spring boot系列02--Thymeleaf+Bootstrap构建页面
- Node学习——开篇
- C语言之for循环
- 使用docker搭建Jenkins 及slave的配置
- nginx反向代理node.js获取客户端IP
- var a=function(){...}与function a(){...}的区别
- 【MySQL疑难杂症】如何将树形结构存储在数据库中(方案一、Adjacency List)
- Centos7 下安装Docke
- 详解spl_autoload_register()函数
- zuul超时的解决方案