介绍
Transition 是一个库,帮助您构建 iOS 视图控制器转换。实现一个漂亮的自定义视图控制器转换需要相当多的组件。您必须实现正确的代理,处理被动动画和主动交互阶段之间的切换,确保时机正确,考虑中断和取消,保持职责分离……这很快就会变得混乱!这就是 Transition 帮助您的时刻:您只需要定义动画和交互,Transition 将这一切串联起来。
简而言之
- 您指定单一职责的组件(动画、交互、...)
- Transition 将它们组合在一起
示例
有几个示例(可在 Examples/
中找到)
- SimpleExample:实现了本 README 中解释的基本步骤。
- TabBarTransitionsExample:向您展示了如何使用自定义交互实现自定义
UITabBarController
转换动画。 - ModalTransitionsExample:向您展示了如何实现包含与 共享元素 交互的定制的 modal 转换动画。
- BuiltInTransitionsCatalog:显示了一些内置转换动画的小集合。
要运行示例项目,克隆仓库,导航到以下示例目录之一,并从该目录中首先运行 pod install
。
需求
- iOS 10.0+
- Swift 3.0+
用法
1. 动画层
AnimationLayer
是设置动画最基本的一部分;没有它,就没有动画。一个 AnimationLayer
是一个简单的结构体,它接受两个参数
1. 动画函数
这是一个简单的闭包,其签名为 () -> Void
。在其中定义动画,就像使用一个 UIView
或 UIViewPropertyAnimator
动画一样。对于每个 AnimationLayer
,过渡将实例化一个 UIViewPropertyAnimator
,并向其传递动画块。
2. 时间参数
它定义了动画的时间。它必须是 UITimingCurveProvider
,如 UICubicTimingParameters
或 UISpringTimingParameters
的实例。
(3. 动画范围)
此外,您可以设置一个动画范围 AnimationRange
,默认设置为 AnimationRange.full
。这个范围定义了动画层的动画开始的结束点(以总过渡动画持续时间的分数表示),在这两个点之间运行。
您可以通过以下方式创建 AnimationLayer
:
let animationLayer = AnimationLayer(timingParameters: UICubicTimingParameters(animationCurve: .easeOut)
animation: { topView?.transform = targetTransform })
topView
和 targetTransform
从哪里来?
2. 过渡动画
AnimationLayer
被定义为您 TransitionAnimation
的一部分。这代表过渡期间的所有(非交互式)动画。TransitionAnimation
协议暴露了一组 AnimationLayer
。此外,它还包含两个函数;一个是设置函数,另一个是完成函数。在开始动画之前,将调用设置函数,并将过渡上下文传递给您,其中包含过渡期间的 fromView
和 toView
。当整个过渡完成时,完成函数将被调用,这样您就可以清理在设置中添加的任何临时视图。
class SimpleAnimation : TransitionAnimation {
private weak var topView: UIView?
private var targetTransform: CGAffineTransform = .identity
func setup(in operationContext: TransitionOperationContext) {
let context = operationContext.context
let isPresenting = operationContext.operation.isPresenting
// We have to add the toView to the transitionContext, at the appropriate index:
if isPresenting {
context.containerView.addSubview(context.toView)
} else {
context.containerView.insertSubview(context.toView, at: 0)
}
context.toView.frame = context.finalFrame(for: context.toViewController)
// We only animate the view that will be on top:
topView = isPresenting ? context.toView : context.fromView
let hiddenTransform = CGAffineTransform(translationX: 0, y: -context.containerView.bounds.height)
topView?.transform = isPresenting ? hiddenTransform : .identity
targetTransform = isPresenting ? .identity : hiddenTransform
}
var layers: [AnimationLayer] {
return [AnimationLayer(timingParameters: AnimationTimingParameters(animationCurve: .easeOut), animation: animate)]
}
func animate() {
topView?.transform = targetTransform
}
func completion(position: UIViewAnimatingPosition) {}
}
3. 过渡
您已经定义了过渡的动画。现在创建一个包含 Transition
结构,该结构具有一个 animation
部分(您的 TransitionAnimation
)和一个可选的 sharedElement
部分,您可以在模态和导航示例中看到实现。并且 Transition
有一个持续时间!
let transition = Transition(duration: 2.0, animation: SimpleAnimation())
4. 过渡控制器
就快要完成了。假设您想为 UINavigationController
过渡使用这个过渡。让我们创建一个便利对象,将与 navigationController
相关的功能隔离。
class MyNavigationTransitions {
let transitionController: TransitionController
let transitionsSource = MyNavigationTransitionSource()
init(navigationController: UINavigationController) {
transitionController = TransitionController(forTransitionsIn: navigationController, transitionsSource: transitionsSource)
}
}
class MyNavigationTransitionSource : TransitionsSource {
func transitionFor(operationContext: TransitionOperationContext, interactionController: TransitionInteractionController?) -> Transition {
return Transition(duration: 0.5, animation: SimpleAnimation())
}
}
TransitionController
负责在指定的 navigationController
中动画化过渡,并使用外部 TransitionsSource
来提供特定操作过渡(这里的操作 – 在这种情况下是推送或弹出 – 可以从 TransitionOperationContext
中获取)。这意味着您可以为推送和弹出返回不同的过渡动画。您还可以提供一个根据操作不同行为的单个动画(请参阅 SimpleAnimation
)。
现在,通过传递您的 navigationController
来初始化您的 MyNavigationTransitions
。
是的!
至少,对于自定义视图控制器过渡动画。还有更多可以帮助你设置自定义交互手势和可以在过渡视图之间移动的共享元素。
上面的步骤已在 SimpleExample
中实现,该示例可在 Examples/
目录中找到。
进一步阅读
安装
通过 CocoaPods 可提供过渡功能。要安装它,只需将以下行添加到您的 Podfile 中
pod 'Transition'
您的反馈欢迎!
如果您有任何建议,请与我们联系 联系。请随意分支并提交拉取请求。此外,我们是荷兰人,因此如果任何命名显得奇怪,可能会有所改进或只是不合适,请告诉我们!
待办事项清单
- 添加功能性的
UIPresentationController
支持(它已经提供,但是动画执行不当...) - 编写更多的测试
- 检查是否可以添加非线性刮擦(iOS 11,https://developer.apple.com/videos/play/wwdc2017/230/)
- ...?
许可
该过渡功能可在 MIT 许可证下使用。有关更多信息,请参阅 LICENSE 文件。