How to animate Tab bar tab switch with a CrossDissolve slide transition?

后端 未结 5 778
既然无缘
既然无缘 2020-12-04 11:20

I\'m trying to create a transition effect on a UITabBarController somewhat similar to the Facebook app. I managed to get a \"scrolling effect\" working on tab s

5条回答
  •  不思量自难忘°
    2020-12-04 12:00

    If you want to use UIViewControllerAnimatedTransitioning to do something more custom than UIView.transition, take a look at this gist.

    // MyTabController.swift
    
    import UIKit
    
    class MyTabBarController: UITabBarController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
            delegate = self
        }
    }
    
    extension MyTabBarController: UITabBarControllerDelegate {
    
        func tabBarController(_ tabBarController: UITabBarController, animationControllerForTransitionFrom fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
            return MyTransition(viewControllers: tabBarController.viewControllers)
        }
    }
    
    class MyTransition: NSObject, UIViewControllerAnimatedTransitioning {
    
        let viewControllers: [UIViewController]?
        let transitionDuration: Double = 1
    
        init(viewControllers: [UIViewController]?) {
            self.viewControllers = viewControllers
        }
    
        func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
            return TimeInterval(transitionDuration)
        }
    
        func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
    
            guard
                let fromVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from),
                let fromView = fromVC.view,
                let fromIndex = getIndex(forViewController: fromVC),
                let toVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to),
                let toView = toVC.view,
                let toIndex = getIndex(forViewController: toVC)
                else {
                    transitionContext.completeTransition(false)
                    return
            }
    
            let frame = transitionContext.initialFrame(for: fromVC)
            var fromFrameEnd = frame
            var toFrameStart = frame
            fromFrameEnd.origin.x = toIndex > fromIndex ? frame.origin.x - frame.width : frame.origin.x + frame.width
            toFrameStart.origin.x = toIndex > fromIndex ? frame.origin.x + frame.width : frame.origin.x - frame.width
            toView.frame = toFrameStart
    
            DispatchQueue.main.async {
                transitionContext.containerView.addSubview(toView)
                UIView.animate(withDuration: self.transitionDuration, animations: {
                    fromView.frame = fromFrameEnd
                    toView.frame = frame
                }, completion: {success in
                    fromView.removeFromSuperview()
                    transitionContext.completeTransition(success)
                })
            }
        }
    
        func getIndex(forViewController vc: UIViewController) -> Int? {
            guard let vcs = self.viewControllers else { return nil }
            for (index, thisVC) in vcs.enumerated() {
                if thisVC == vc { return index }
            }
            return nil
        }
    }
    

提交回复
热议问题