Skip to content

Instantly share code, notes, and snippets.

@dsoike
Last active March 7, 2023 07:57
Show Gist options
  • Star 15 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save dsoike/caa34a2605306f28c3061efc4920ba13 to your computer and use it in GitHub Desktop.
Save dsoike/caa34a2605306f28c3061efc4920ba13 to your computer and use it in GitHub Desktop.
Swift UITabBarController with Custom Transition Animation
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
}
}
@chienpm304
Copy link

thanks

@carlvars88
Copy link

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