ViewDisappear animation before tabbar click

572 Views Asked by At

I have a TabBarController that has 3 navigationController, where each has a corresponding viewController: AViewController, BViewController and CViewController. First one has a UIView element that I want to run animation against it when viewDisappears using:

UIView.animateWithDuration(duration, delay: 0.0, options: .CurveEaseOut, animations: {

during...

override func viewWillDisappear(animated: Bool) {

If user clicks on item 2 or 3 in the tabbar, I want that animation to take place first and then take the user to the item #2 or #3.

Problem is that that when user clicks a different item, this code in the TabBarController is triggered first before the viewwillDisappears in my ViewController A

override func tabBar(tabBar: UITabBar, didSelectItem item: UITabBarItem) {

and then my animation doesn't run.

Where should I place my animation so it runs before user is taken to a different item in the tabbar?

2

There are 2 best solutions below

1
On BEST ANSWER

You could implement tabBarController:shouldSelectViewController: from UITabBarControllerDelegate, return false, play your animation and then programatically change tab.

0
On

You need to write your own UIViewControllerAnimatedTransitioning (https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIViewControllerAnimatedTransitioning_Protocol/)

try this code:

TabBarController.swift

import UIKit
class TabBarController: UITabBarController, UITabBarControllerDelegate {

var buttons = [UIButton]()

override func viewDidLoad() {
    super.viewDidLoad()
    self.delegate = self

    var newViewControllers = [UIViewController]()

    for index in 0..<2 {
        let viewController = ViewController()
        var tabBarItem = UITabBarItem()

        switch index {
        case 0:
            viewController.view.backgroundColor = UIColor.blueColor()
            viewController.label.textColor = UIColor.whiteColor()
            tabBarItem = UITabBarItem(tabBarSystemItem: .More, tag: index)
        case 1:
            viewController.view.backgroundColor = UIColor.greenColor()
            viewController.label.textColor = UIColor.blackColor()
            tabBarItem = UITabBarItem(tabBarSystemItem: .Favorites, tag: index)
        default:
            break
        }

        viewController.label.text = "Text \(index)"
        viewController.tabBarItem = tabBarItem
        newViewControllers.append(viewController)
        //tabBar.items![index] = tabBarItem

    }

    selectedIndex = 0
   //    = newViewControllers
    setViewControllers(newViewControllers, animated: false)
    // Do any additional setup after loading the view, typically from a nib.
}

func tabBarController(tabBarController: UITabBarController, animationControllerForTransitionFromViewController fromVC: UIViewController, toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
    let fromIndex = tabBarController.viewControllers!.indexOf(fromVC)!
    let toIndex = tabBarController.viewControllers!.indexOf(toVC)!

    let tabChangeDirection: TabOperationDirection = toIndex < fromIndex ? .Left : .Right
    let transitionType = SDETransitionType.TabTransition(tabChangeDirection)
    let slideAnimationController = SlideAnimationController(type: transitionType)
    return slideAnimationController

}
}

ViewController.swift

import UIKit
class ViewController: UIViewController {

let label = UILabel(frame: CGRect(x: 40, y: 60, width: 80, height: 40))

override func viewDidLoad() {
    super.viewDidLoad()
    view.addSubview(label)
}

var labelHidden = false {
    willSet(value) {
        if value {
            self.label.frame.origin.y = -40
        } else {
            self.label.frame.origin.y = 60
        }
    }
}
}

SlideAnimationController.swift (resource: https://github.com/seedante/iOS-ViewController-Transition-Demo)

import UIKit

enum SDETransitionType{
case NavigationTransition(UINavigationControllerOperation)
case TabTransition(TabOperationDirection)
case ModalTransition(ModalOperation)
}

enum TabOperationDirection{
case Left, Right
}

enum ModalOperation{
case Presentation, Dismissal
}

class SlideAnimationController: NSObject, UIViewControllerAnimatedTransitioning {

private var transitionType: SDETransitionType

init(type: SDETransitionType) {
    transitionType = type
    super.init()
}

func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
    return 0.3
}

func animateTransition(transitionContext: UIViewControllerContextTransitioning) {

    guard let containerView = transitionContext.containerView(), fromVC = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey), toVC = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey) else{
        return
    }

    let fromView = fromVC.view
    let toView = toVC.view

    var translation = containerView.frame.width
    var toViewTransform = CGAffineTransformIdentity
    var fromViewTransform = CGAffineTransformIdentity

    switch transitionType{
    case .NavigationTransition(let operation):
        translation = operation == .Push ? translation : -translation
        toViewTransform = CGAffineTransformMakeTranslation(translation, 0)
        fromViewTransform = CGAffineTransformMakeTranslation(-translation, 0)
    case .TabTransition(let direction):
        translation = direction == .Left ? translation : -translation
        fromViewTransform = CGAffineTransformMakeTranslation(translation, 0)
        toViewTransform = CGAffineTransformMakeTranslation(-translation, 0)
    case .ModalTransition(let operation):
        translation =  containerView.frame.height
        toViewTransform = CGAffineTransformMakeTranslation(0, (operation == .Presentation ? translation : 0))
        fromViewTransform = CGAffineTransformMakeTranslation(0, (operation == .Presentation ? 0 : translation))
    }

    switch transitionType{
    case .ModalTransition(let operation):
        switch operation{
        case .Presentation: containerView.addSubview(toView)
        case .Dismissal: break
        }
    default: containerView.addSubview(toView)
    }

    toView.transform = toViewTransform

    if let fromVC = fromVC as? ViewController {
        UIView.animateWithDuration(0.3, delay: 0.0, options: .CurveEaseOut, animations: {
            fromVC.labelHidden = true
            }, completion: {
                bool in
                UIView.animateWithDuration(self.transitionDuration(transitionContext), animations: {
                    fromView.transform = fromViewTransform
                    toView.transform = CGAffineTransformIdentity
                    }, completion: { finished in
                        fromView.transform = CGAffineTransformIdentity
                        toView.transform = CGAffineTransformIdentity

                        let isCancelled = transitionContext.transitionWasCancelled()
                        transitionContext.completeTransition(!isCancelled)

                        fromVC.labelHidden = false
                })
        })
    }
}
}