转换 1.3.0

Transition 1.3.0

测试已测试
语言语言 SwiftSwift
许可证 MIT
发布最新发布2020 年 5 月
SPM支持 SPM

Toine Heuvelmans 维护。



Transition

CocoaPods version Carthage compatible license platform

介绍

Transition 是一个库,帮助您构建 iOS 视图控制器转换。实现一个漂亮的自定义视图控制器转换需要相当多的组件。您必须实现正确的代理,处理被动动画和主动交互阶段之间的切换,确保时机正确,考虑中断和取消,保持职责分离……这很快就会变得混乱!这就是 Transition 帮助您的时刻:您只需要定义动画和交互,Transition 将这一切串联起来。

简而言之

  • 您指定单一职责的组件(动画、交互、...)
  • Transition 将它们组合在一起

示例

有几个示例(可在 Examples/ 中找到)

  1. SimpleExample:实现了本 README 中解释的基本步骤。
  2. TabBarTransitionsExample:向您展示了如何使用自定义交互实现自定义 UITabBarController 转换动画。
  3. ModalTransitionsExample:向您展示了如何实现包含与 共享元素 交互的定制的 modal 转换动画。
  4. BuiltInTransitionsCatalog:显示了一些内置转换动画的小集合。

要运行示例项目,克隆仓库,导航到以下示例目录之一,并从该目录中首先运行 pod install



需求

  • iOS 10.0+
  • Swift 3.0+

用法

1. 动画层

AnimationLayer 是设置动画最基本的一部分;没有它,就没有动画。一个 AnimationLayer 是一个简单的结构体,它接受两个参数

1. 动画函数

这是一个简单的闭包,其签名为 () -> Void。在其中定义动画,就像使用一个 UIViewUIViewPropertyAnimator 动画一样。对于每个 AnimationLayer,过渡将实例化一个 UIViewPropertyAnimator,并向其传递动画块。

2. 时间参数

它定义了动画的时间。它必须是 UITimingCurveProvider,如 UICubicTimingParametersUISpringTimingParameters 的实例。

(3. 动画范围)

此外,您可以设置一个动画范围 AnimationRange,默认设置为 AnimationRange.full。这个范围定义了动画层的动画开始的结束点(以总过渡动画持续时间的分数表示),在这两个点之间运行。

您可以通过以下方式创建 AnimationLayer:

let animationLayer = AnimationLayer(timingParameters: UICubicTimingParameters(animationCurve: .easeOut)
                                           animation: { topView?.transform = targetTransform })

😦... 嘿,等等!那个 topViewtargetTransform 从哪里来?

2. 过渡动画

AnimationLayer 被定义为您 TransitionAnimation 的一部分。这代表过渡期间的所有(非交互式)动画。TransitionAnimation 协议暴露了一组 AnimationLayer。此外,它还包含两个函数;一个是设置函数,另一个是完成函数。在开始动画之前,将调用设置函数,并将过渡上下文传递给您,其中包含过渡期间的 fromViewtoView。当整个过渡完成时,完成函数将被调用,这样您就可以清理在设置中添加的任何临时视图。

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'

您的反馈欢迎!

如果您有任何建议,请与我们联系 联系。请随意分支并提交拉取请求。此外,我们是荷兰人,因此如果任何命名显得奇怪,可能会有所改进或只是不合适,请告诉我们!

待办事项清单

许可

该过渡功能可在 MIT 许可证下使用。有关更多信息,请参阅 LICENSE 文件。