iOS自定义转场动画

标签 ios swift uiviewanimation uiviewanimationtransition

我已经开始使用 UIViewControllerAnimatedTransitioning 协议(protocol)学习自定义过渡动画。我在 youtube 上找到的大部分视频都是基于当我们有新的 ViewController 呈现圆形动画或类似动画时的流程。

我在实现过渡方式时遇到问题。大多数情况下,我需要的是类似于 facebook 应用程序 以及它们如何打开全屏图像查看器。

那么,假设我们有 VC1VC2。在 VC1 上,我们调用操作来呈现 VC2。在两个 VC 上,我们都有相同的 UI 元素。在我的例子中是 UIImageView。就像您在 VC1 上单击 imageView 一样,它会打开某个对象的详细信息页面,其图像位于顶部。我想要动画,看起来应该像来自 VC1 的图像正在将帧更改为来自 VC2 的图像的最终帧,然后是其他内容(如标签、按钮、等)应该出现在详细信息页面上。

但我在训练过程中遇到了一些问题
1、首先,我不理解transitionContextcontainerView的思想。但正如我所见,它有点像转换之间的中间状态 View 。那是对的吗?但这很奇怪 对我来说,因为即使 backgroundColor 属性也不适用于 containerView
2. 我不明白在转换过程中我到底需要什么动画,containerView subview 的结构应该是什么。在我的示例中,当呈现 VC2 时,据我所知,我需要隐藏它的所有 subview 。然后将 VC1 的 imageView 动画到 VC2imageView 的框架,然后再次使所有 subview 可见。那么,在这种情况下,应该将 imageView 添加到 containerView 中吗?如果是这样,那么它应该是 VC1 中的实际 imageView,还是 imageView 的全新副本,具有相同的帧/图像,只是在过渡期间临时使用...

将我链接到具有类似动画的示例/教程/代码会很有帮助

Here is link to how that works in facebook

最佳答案

了解自定义过渡动画

如果你从 VCA 导航到 VCB 然后

  1. 首先,您需要使用 UIViewControllerTransitioningDelegate

transitioning delegate 负责提供用于自定义过渡的动画 Controller 。您指定的委托(delegate)对象必须符合 UIViewControllerTransitioningDelegate 协议(protocol)。

  1. 现在你必须使用 UIViewControllerAnimatedTransitioning

它负责根据动画 View 的持续时间实际逻辑 进行转换。

这些代表的工作方式就像您在两个 VC 之间并与他们一起玩一样。

要成功完成转换,您必须执行以下步骤:

  1. 所以首先你需要使用它

    • 设置 modalPresentationStyle = .custom
    • 分配 transitonDelegate 属性。
  2. func animateTransition(_ : ) 中你必须使用上下文 containerView 因为你在两个 VC 之间 所以你需要可以制作任何动画的任何容器,因此上下文为您提供了可以制作动画的容器。

  3. 现在您需要 fromViewtoViewVCA.viewVCB.view 响应。现在将这两个 View 添加到containerView中,编写动画核心逻辑。

  4. 最后要注意的是在转换上下文对象上调用的 completeTransition(_:) 方法。动画完成后必须调用此方法,让系统知道您的 View Controller 已完成转换。

这是过渡动画的核心基础。

我不知道 FB 动画,所以我只是解释了你剩下的问题。

引用

您可以询问任何进一步的信息。

Code Addition

关于图片选择

加入VC_A

var selectedImage: UIImageView?
 let transition = PopAnimator()

  override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransition(to: size, with: coordinator)

        coordinator.animate(
          alongsideTransition: {context in
            self.bgImage.alpha = (size.width>size.height) ? 0.25 : 0.55
            self.positionListItems()
          },
          completion: nil
        )
      }
//position all images inside the list
  func positionListItems() {
    let listHeight = listView.frame.height
    let itemHeight: CGFloat = listHeight * 1.33
    let aspectRatio = UIScreen.main.bounds.height / UIScreen.main.bounds.width
    let itemWidth: CGFloat = itemHeight / aspectRatio

    let horizontalPadding: CGFloat = 10.0

    for i in herbs.indices {
      let imageView = listView.viewWithTag(i) as! UIImageView
      imageView.frame = CGRect(
        x: CGFloat(i) * itemWidth + CGFloat(i+1) * horizontalPadding, y: 0.0,
        width: itemWidth, height: itemHeight)
    }

    listView.contentSize = CGSize(
      width: CGFloat(herbs.count) * (itemWidth + horizontalPadding) + horizontalPadding,
      height:  0)
  }

// On image selection
VC_B.transitioningDelegate = self
    present(VC_B, animated: true, completion: nil)



   // add extension
extension VC_A: UIViewControllerTransitioningDelegate {

  func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
    transition.originFrame = selectedImage!.superview!.convert(selectedImage!.frame, to: nil)

    transition.presenting = true
    selectedImage!.isHidden = true

    return transition
  }

  func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
    transition.presenting = false
    return transition
  }
}

和动画类

class PopAnimator: NSObject, UIViewControllerAnimatedTransitioning {

  let duration = 1.0
  var presenting = true
  var originFrame = CGRect.zero

  var dismissCompletion: (()->Void)?

  func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
    return duration
  }

  func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
    let containerView = transitionContext.containerView

    let toView = transitionContext.view(forKey: .to)!

    let herbView = presenting ? toView : transitionContext.view(forKey: .from)!

    let initialFrame = presenting ? originFrame : herbView.frame
    let finalFrame = presenting ? herbView.frame : originFrame

    let xScaleFactor = presenting ?

      initialFrame.width / finalFrame.width :
      finalFrame.width / initialFrame.width

    let yScaleFactor = presenting ?

      initialFrame.height / finalFrame.height :
      finalFrame.height / initialFrame.height

    let scaleTransform = CGAffineTransform(scaleX: xScaleFactor, y: yScaleFactor)

    if presenting {
      herbView.transform = scaleTransform
      herbView.center = CGPoint(
        x: initialFrame.midX,
        y: initialFrame.midY)
      herbView.clipsToBounds = true
    }

    containerView.addSubview(toView)
    containerView.bringSubview(toFront: herbView)

    UIView.animate(withDuration: duration, delay:0.0, usingSpringWithDamping: 0.4,
      initialSpringVelocity: 0.0,
      animations: {
        herbView.transform = self.presenting ?
          CGAffineTransform.identity : scaleTransform
        herbView.center = CGPoint(x: finalFrame.midX,
                                  y: finalFrame.midY)
      },
      completion:{_ in
        if !self.presenting {
          self.dismissCompletion?()
        }
        transitionContext.completeTransition(true)
      }
    )
  }

}

输出:

enter image description here

Git-hub repo : https://github.com/thedahiyaboy/TDCustomTransitions

  • xcode:9.2

  • swift :4

关于iOS自定义转场动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44134648/

相关文章:

ios - Q : Spritekit SKPhysics

ios - OS X 服务器机器人的文件存储在哪里

iOS : Connected to wifi but no internet access

ios - Objective-C 后台任务 UIBackgroundTaskIdentifier 重复

ios - Firebase ios : get list of users by IDs

ios - 如何在所有 UIView 完成动画后调用完成 block 来为 UIView 数组设置动画?

ios - UIView 页面 curl 动画不适用于 block

ios - 在 iOS 中暂停动画( Objective-C )

ios - 查询包含字符串值列表的几个字段(Realm Swift)

ios - Swift SpriteKit : Game won't restart properly? 怎么回事?