iOS自定义过渡动画

问题描述 投票:3回答:2

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

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

所以,让我们说我们有VC1VC2。在VC1,我们称行动提出VC2。在两个VCs上我们都有相同的UI元素。在我的情况下,这是UIImageView。就像你点击imageView上的VC1一样,它打开一些对象的详细页面,顶部是图像。我希望有动画,看起来像VC1的图像正在将帧更改为VC2的最终图像帧,然后应该出现详细页面上的其他内容(如标签,按钮等)。

但是我在训练中遇到了一些问题。 1.首先,我不理解containerViewtransitionContext的想法。但正如我所看到的,它就像转换之间的中间状态。那是对的吗?但这对我来说很奇怪,因为即使backgroundColor财产不适用于containerView。 2.我不明白在转换过程中我需要做什么动画,以及containerView子视图的结构应该是什么。在我的例子中,当提出VC2时,我需要,据我所知,有点隐藏它的所有子视图。然后将图像从VC1动画到imageViewVC2框架,然后再次显示所有子视图。那么,在这种情况下,imageView应该添加到containerView?如果是这样,那么它应该是来自imageView的实际VC1,还是imageView的全新副本,具有相同的帧/图像,仅在转换期间暂时使用...

将我链接到带有类似动画的examples / tutorial / code会很有帮助

Here is link to how that works in facebook

ios swift uiviewanimation uiviewanimationtransition
2个回答
10
投票

了解自定义过渡动画

就像你从VCA导航到VCB那样

  1. 首先,你需要使用UIViewControllerTransitioningDelegate

转换委托负责提供用于自定义转换的动画控制器。您指定的委托对象必须符合UIViewControllerTransitioningDelegate协议。

  1. 现在你必须使用UIViewControllerAnimatedTransitioning

它负责在动画视图的持续时间和实际逻辑方面的转换。

这些代表的工作就像你在两个VC's之间和他们一起玩。

要使完成过渡成功,您必须执行以下步骤:

  1. 因此,首先要使用它 设置modalPresentationStyle = .custom 分配transitonDelegate财产。
  2. func animateTransition(_ : )你必须使用上下文containerView,因为你在两个VC's之间,所以你需要任何容器,你可以做任何动画,所以上下文提供了你可以做动画的容器。
  3. 现在你需要fromViewtoView,即VCA.viewVCB.view resp。现在在containerView中添加这两个视图并编写动画的核心逻辑。
  4. 最后要注意的是在转换上下文对象上调用的completeTransition(_ :)方法。动画完成后,必须调用此方法,让系统知道视图控制器已完成转换。

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

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

参考

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

代码添加

关于图像选择

加入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

Github Repo:qazxsw poi

  • xcode:9.2
  • 迅捷:4

1
投票

https://github.com/thedahiyaboy/TDCustomTransitions的核心方法是UIViewControllerAnimatedTransitioning。我在试图解释基本想法时添加了评论。

animateTransition
© www.soinside.com 2019 - 2024. All rights reserved.