我已经开始使用UIViewControllerAnimatedTransitioning
协议学习自定义过渡动画。我们在youtube上找到的所有视频都是基于流程的,当我们有新的ViewController呈现圆形动画或类似的时候。
我在实现转换方式时遇到问题。大多数情况下,我需要的是类似于facebook应用程序以及它们如何打开全屏图像查看器。
所以,让我们说我们有VC1
和VC2
。在VC1
,我们称行动提出VC2
。在两个VC
s上我们都有相同的UI元素。在我的情况下,这是UIImageView
。就像你点击imageView
上的VC1
一样,它打开一些对象的详细页面,顶部是图像。我希望有动画,看起来像VC1
的图像正在将帧更改为VC2
的最终图像帧,然后应该出现详细页面上的其他内容(如标签,按钮等)。
但是我在训练中遇到了一些问题。
1.首先,我不理解containerView
的transitionContext
的想法。但正如我所看到的,它就像转换之间的中间状态。那是对的吗?但这对我来说很奇怪,因为即使backgroundColor
财产不适用于containerView
。
2.我不明白在转换过程中我需要做什么动画,以及containerView
子视图的结构应该是什么。在我的例子中,当提出VC2
时,我需要,据我所知,有点隐藏它的所有子视图。然后将图像从VC1
动画到imageView
的VC2
框架,然后再次显示所有子视图。那么,在这种情况下,imageView
应该添加到containerView?如果是这样,那么它应该是来自imageView
的实际VC1
,还是imageView的全新副本,具有相同的帧/图像,仅在转换期间暂时使用...
将我链接到带有类似动画的examples / tutorial / code会很有帮助
就像你从VCA
导航到VCB
那样
UIViewControllerTransitioningDelegate
。转换委托负责提供用于自定义转换的动画控制器。您指定的委托对象必须符合UIViewControllerTransitioningDelegate
协议。
UIViewControllerAnimatedTransitioning
它负责在动画视图的持续时间和实际逻辑方面的转换。
这些代表的工作就像你在两个VC's
之间和他们一起玩。
要使完成过渡成功,您必须执行以下步骤:
modalPresentationStyle = .custom
分配transitonDelegate
财产。func animateTransition(_ : )
你必须使用上下文containerView
,因为你在两个VC's
之间,所以你需要任何容器,你可以做任何动画,所以上下文提供了你可以做动画的容器。fromView
和toView
,即VCA.view
和VCB.view
resp。现在在containerView
中添加这两个视图并编写动画的核心逻辑。这是过渡动画的核心基础。
我不知道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)
}
)
}
}
输出:
Github Repo:qazxsw poi
https://github.com/thedahiyaboy/TDCustomTransitions的核心方法是UIViewControllerAnimatedTransitioning
。我在试图解释基本想法时添加了评论。
animateTransition