Last active
March 7, 2023 07:57
-
-
Save dsoike/caa34a2605306f28c3061efc4920ba13 to your computer and use it in GitHub Desktop.
Swift UITabBarController with Custom Transition Animation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} | |
} |
When you switch very fast between tabs you got a black screen
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
thanks