我写了一个自定义滑动过渡,在模态演示文稿中工作正常。但在推送演示中,“到”视图位置不是动画。
我尝试了相同的代码,用alpha切换翻译,它的工作原理。
从视图完美运行,它只是在动画期间保持固定的视图。
func transitionAnimator(using transitionContext: UIViewControllerContextTransitioning) -> UIViewImplicitlyAnimating {
let duration = transitionDuration(using: transitionContext)
let container = transitionContext.containerView
let toController = transitionContext.viewController(forKey: .to)
toController?.beginAppearanceTransition(true, animated: true)
guard
let to = transitionContext.view(forKey: .to),
let from = transitionContext.view(forKey: .from)
else {
print("To or from view are nil!")
fatalError()
}
container.addSubview(to)
let animator = UIViewPropertyAnimator(duration: duration, curve: .linear)
var toStartingPoint: CGPoint
var fromEndingPoint: CGPoint
switch self.from {
case .down:
toStartingPoint = CGPoint(x: 0, y: -from.bounds.height)
fromEndingPoint = CGPoint(x: 0, y: from.bounds.height)
case .top:
toStartingPoint = CGPoint(x: 0, y: from.bounds.height)
fromEndingPoint = CGPoint(x: 0, y: -from.bounds.height)
case .right:
toStartingPoint = CGPoint(x: from.bounds.width, y: 0)
fromEndingPoint = CGPoint(x: -from.bounds.width, y: 0)
case .left:
toStartingPoint = CGPoint(x: -from.bounds.width, y: 0)
fromEndingPoint = CGPoint(x: from.bounds.width, y: 0)
}
to.transform = CGAffineTransform(translationX: toStartingPoint.x, y: toStartingPoint.y)
animator.addAnimations({
from.transform = CGAffineTransform(translationX: fromEndingPoint.x, y: fromEndingPoint.y)
}, delayFactor: 0.0)
animator.addAnimations({
to.transform = .identity
}, delayFactor: 0.0)
animator.addCompletion { [weak self] position in
switch position {
case .start:
self?.auxCancelCompletion?()
transitionContext.completeTransition(false)
self?.auxAnimationsCancel?()
case .end:
self?.auxEndCompletion?()
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
from.transform = .identity
to.transform = .identity
default:
transitionContext.completeTransition(false)
self?.auxAnimationsCancel?()
}
}
if let auxAnimations = auxAnimations {
animator.addAnimations(auxAnimations)
}
self.animator = animator
self.context = transitionContext
animator.addCompletion { [unowned self] _ in
self.animator = nil
self.context = nil
}
animator.isUserInteractionEnabled = true
return animator
}
我认为这是代理问题,但navigationDelgate设置正确,否则我想我不会看到任何动画..
代表设置:
override func viewDidLoad() {
super.viewDidLoad()
transitionHelper = SwipeInteractiveTransitionHelper(withDelegate: self)
}
extension TodayViewController: UINavigationControllerDelegate {
func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationController.Operation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return transitionHelper?.swipeTransition
}
func navigationController(_ navigationController: UINavigationController, interactionControllerFor animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
return transitionHelper?.swipeTransition
}
}
这是自定义推送协调器,其中viewController是下一个视图控制器,我附加委托的位置。
case .pushCustom:
guard let navigationController = currentViewController.navigationController else {
fatalError("Can't push a view controller without a current navigation controller")
}
guard let current = currentViewController as? UINavigationControllerDelegate else {
fatalError("Can't push a view controller without a current navigation delegate")
}
navigationController.delegate = current
navigationController.pushViewController(viewController, animated: true) { [weak self] in
self?.currentViewController = SceneCoordinator.actualViewController(for: viewController)
completion?()
}
解决了为目标视图设置快照的动画,而不是直接设置目标视图的动画。
let to = transitionContext.view(forKey:.to)let toViewSnapshot = to.snapshotView(afterScreenUpdates:true)
只需使用toViewSnapshot作为动画即可
我这样做的是什么。希望它会对你有所帮助。
VC:UIViewController
{
@IBAction func test(_ sender: Any){
navigationController?.delegate = self
let destine = storyboard?.instantiateViewController(withIdentifier: "target")
navigationController?.pushViewController(destine!, animated: true)
}
func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationController.Operation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning?{
return Traistion()
}
}
class Traistion: NSObject, UIViewControllerAnimatedTransitioning{
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let animator = transitionAnimator(using: transitionContext)
animator.startAnimation()
}
var animator: UIViewPropertyAnimator!
var context: UIViewControllerContextTransitioning!
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval{
return 1.0
}
enum Direction {
case down
case top
case left
case right
}
var from : Direction = .left
var auxCancelCompletion :(()->())? = {
return nil
}()
var auxAnimationsCancel :(()->())? = {
return nil
}()
var auxEndCompletion :(()->())? = {
return nil
}()
var auxAnimations : (()->())?
func transitionAnimator(using transitionContext: UIViewControllerContextTransitioning) -> UIViewImplicitlyAnimating {
let duration = transitionDuration(using: transitionContext)
let container = transitionContext.containerView
let toController = transitionContext.viewController(forKey: .to)
toController?.beginAppearanceTransition(true, animated: true)
guard
let to = transitionContext.view(forKey: .to),
let from = transitionContext.view(forKey: .from)
else {
print("To or from view are nil!")
fatalError()
}
container.addSubview(to)
let animator = UIViewPropertyAnimator(duration: duration, curve: .linear)
var toStartingPoint: CGPoint
var fromEndingPoint: CGPoint
switch self.from {
case .down:
toStartingPoint = CGPoint(x: 0, y: -from.bounds.height)
fromEndingPoint = CGPoint(x: 0, y: from.bounds.height)
case .top:
toStartingPoint = CGPoint(x: 0, y: from.bounds.height)
fromEndingPoint = CGPoint(x: 0, y: -from.bounds.height)
case .right:
toStartingPoint = CGPoint(x: from.bounds.width, y: 0)
fromEndingPoint = CGPoint(x: -from.bounds.width, y: 0)
case .left:
toStartingPoint = CGPoint(x: -from.bounds.width, y: 0)
fromEndingPoint = CGPoint(x: from.bounds.width, y: 0)
}
to.transform = CGAffineTransform(translationX: toStartingPoint.x, y: toStartingPoint.y)
animator.addAnimations({
from.transform = CGAffineTransform(translationX: fromEndingPoint.x, y: fromEndingPoint.y)
}, delayFactor: 0.0)
animator.addAnimations({
to.transform = .identity
}, delayFactor: 0.0)
animator.addCompletion { [weak self] position in
switch position {
case .start:
self?.auxCancelCompletion?()
transitionContext.completeTransition(false)
self?.auxAnimationsCancel?()
case .end:
self?.auxEndCompletion?()
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
from.transform = .identity
to.transform = .identity
default:
transitionContext.completeTransition(false)
self?.auxAnimationsCancel?()
}
}
if let auxAnimations = auxAnimations {
animator.addAnimations(auxAnimations)
}
self.animator = animator
self.context = transitionContext
animator.addCompletion { [unowned self] _ in
//self.animator = nil
// self.context = nil
}
animator.isUserInteractionEnabled = true
return animator
}
}
使用interruptibleAnimator
时。它将至少调用此函数两次,你应该提供相同的动画师但不同的动画师。所以你必须这样称呼它:
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
animator = transitionAnimator(using: transitionContext) as! UIViewPropertyAnimator
animator.startAnimation()
}
func interruptibleAnimator(using transitionContext: UIViewControllerContextTransitioning) -> UIViewImplicitlyAnimating {
return animator
}
var animator: UIViewPropertyAnimator!
var context: UIViewControllerContextTransitioning!
或者更简单:
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
}
func interruptibleAnimator(using transitionContext: UIViewControllerContextTransitioning) -> UIViewImplicitlyAnimating {
if animator == nil {animator = transitionAnimator(using: transitionContext) as! UIViewPropertyAnimator
animator.startAnimation()}
return animator
}
这里animator
将被调用两次,这是同一个。如果
func interruptibleAnimator(using transitionContext: UIViewControllerContextTransitioning) -> UIViewImplicitlyAnimating {
return transitionAnimator(using: transitionContext) }
这不是正确的使用方法,因为动画师会有所不同。
请参阅文档中的最后一行。