Shift 是一个简单、声明式的动画库,用于在 UIKit 中构建复杂的数据控制器和视图切换。
Shift 可以通过为源视图和目标视图提供 id
自动将匹配的视图从当前视图控制器切换到下一个视图控制器。这种类型的切换可以让人感觉非常自然流畅,并有助于为目标屏幕提供上下文。还可以为切换过程中要运行的未匹配视图添加额外的动画。
在动画视图控制器切换方面,Shift 与 Hero 非常相似。但它不同之处在于它不仅限于视图控制器。这些动画可以应用于两个不同的 UIView
,无论是否实际发生切换。这在您在两个子视图控制器之间切换,或者只是两个普通的 UIView
子视图时非常有用。它还可以轻松集成到需要提供自己的 UIViewControllerAnimatedTransitioning
或 UIPresentationController
的自定义切换中。这对于目标视图控制器不覆盖整个屏幕时非常有用。
示例
所有示例都可以在 /Examples
文件夹中找到,可以通过 /Examples/Examples.xcworkspace
运行。
开始
要在 Shift 中使用,您必须在显示视图控制器之前启用它。
viewController.shift.enable()
present(viewController, animated: true, completion: nil)
这将使 Shift 控制视控的任何切换。如果您在这里停止,当显示视图控制器时,您将看到视图通过淡入动画显示。这是 defaultAnimation
,并且可自定义。如果不需要设置为 nil
停止。还提供了多个其他 默认设置。
viewController.shift.defaultAnimation = DefaultAnimations.Scale(.down)
您可以通过遵循 DefaultShiftAnimation
并在视图中设置所需的动画来制作自定义默认动画。如何添加自定义额外动画将在后面介绍。
基准持续时间
过渡动画的持续时间由提供的 baselineDuration
决定。这是一个持续时间基准,而不是实际将使用的值。每个视图都将根据适用的动画计算其动画的持续时间。换句话说,baselineDuration
是最小持续时间,并且每个视图都需要时将其添加更多时间。
// Transition will now take about 1 second.
viewController.shift.baselineDuration = 1
视图顺序
"toViews" 和 "fromViews",或者我们要过渡到的视图和来自的视图,需要添加到过渡容器中。它们被添加的顺序可以调整,以控制哪些视图在最上面或最下面。这是通过 viewOrder
属性实现的。默认情况下,这将是 auto
。自动按您预期的顺序添加视图。要过渡的视图将位于顶部,并且在消失时,正在消失的视图将位于顶部。然而,这可能不是您想要的。使用视图顺序,您可以选择哪些视图应该位于顶部。
viewController.shift.viewOrder = .fromViewsOnTop
匹配视图
匹配视图是您在源视图中有一个视图需要被动画到目标视图上的地方。这可以通过为每个视图提供匹配的 id
来完成。在过渡过程中,源视图的框架和其他常用属性将被动画到匹配目的地。
firstView.shift.id = "blueView"
secondView.shift.id = "blueView"
就这样!现在 sourceView
将神奇地移动以匹配 destinationView
。注意:实际上没有编辑任何视图,而是使用每个视图的快照。
内容动画
视图匹配后,它们的内容可能不同。从初始内容过渡到新内容的方式可以自定义。内容动画有两种不同的选项,渐变
和 最终
。此选项仅在匹配的视图中有效,因为不匹配的视图没有内容变化。
在 渐变 下,初始内容将渐隐,新内容将渐显。
view.shift.contentAnimation = .fade
在 最终 下,内容将立即显示最终内容。
view.shift.contentAnimation = .final
内容大小
匹配的视图在转换过程中可能会改变大小。由于在调整大小时使用了视图的快照,内容可能会扭曲和拉伸。您可以自定义内容大小调整的行为。有两种不同的大小选项,拉伸
和 最终
。
使用 拉伸,内容的大小将直接匹配在调整到其新最终帧。
view.shift.contentSizing = .stretch
使用 最终,内容的大小将立即设置为最终大小,并且任何大小变化都不会影响它。
view.shift.contentSizing = .final
附加动画
如果一个视图在转换中匹配但需要被动画化,您可以提供多种附加动画。这些动画将在转换期间应用,并在消失时自动反转。
例如,如果您希望一个视图从左边渐隐并向滑动150点,可以通过如下方式应用动画
view.shift.animations
.fade()
.move(.right(150))
要查看潜在动画的完整列表,请查看
这些动画可以设置成根据某些预测条件有条件性地运行。每个动画函数都有一个可选的参数来提供一个 条件
;它总是最后一个参数。如果条件不满足,动画将不会被添加。
如果您只想在视图出现时放大它,而在消失时不缩小,请做以下操作
view.animations.scale(2, .onAppear)
要提供自定义条件,可以使用 .filter
。
view.animations.scale(2, .filter{ ... })
superview
当一个视图在转换期间被动画化时,其快照必须添加到转换中的一个视图内。superview
(父视图)有两种不同的选择:parent
和 container
。每个不同的父视图都可以影响视图到达最终位置的方式。
与父视图相关联时,它的superview
将是一个与原始视图层次结构中视图的实际superview
最相关的视图。如果其superview
的位置正在被动画化,它也会被动画化,因为它是对动画视图的子视图。
star.shift.superview = .parent
在容器中,它将直接添加到过渡的container
视图中,并且不会受到原始superview
位置的影响。parent
是默认选择,但是匹配的视图无论选择如何,始终使用container
。
star.shift.superview = .container
自定义过渡
如果您需要提供自己的UIViewControllerAnimatedTransitioning
或UIPresentationController
,非常简单地将Shift纳入过渡中。每个过渡的核心都是Animator
。它负责执行动画。在您的UIViewControllerAnimatedTransitioning
子类中,在animateTransition(using:transitionContext:)
函数中声明一个新动画器,并调用animate。
let animator = Animator(
fromView: fromViewController,
toView: toViewController,
container: transitionContext.containerView,
isPresenting: true
)
animator.animate { complete in
toViewController.view.alpha = 1
transitionContext.completeTransition(complete)
}
查看默认的模态过渡动画器以了解完整示例。
在示例项目中,“电影”视图使用自定义的UIPresentationController
来显示非全屏的上下文菜单。
安装
Swift包管理器
Shift可以通过Swift包管理器获取。
要使用SPM添加,只需将https://github.com/wickwirew/Shift.git
添加到Xcode中包的列表中。
Carthage
Shift可以通过Carthage获取。要安装它,只需将以下行添加到Cartfile:
github "wickwirew/Shift"
CocoaPods
Shift可以通过CocoaPods使用。要安装它,只需将以下行添加到您的Podfile中
use_frameworks!
pod 'ShiftTransitions'
致谢
- Hero是这个库的灵感的巨大来源,所以很多赞誉应该归于lkzhao和贡献者。这只是Hero不能满足所有需求时的另一个选择。
- SamAtmoreMedia在Dribbble上的这个概念为空间示例设计。