0

I have some troubles to get the views transitions animated when I change the UITabBarController.selectedIndex changed programmatically.

When I tap on a TabBar icon the animation works fine, but when I change the selectedIndex from a gestureRecognizer action.

The transition code at the TabBar controller class is the following:

func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
    if CanChangeTab {
        guard let fromView = tabBarController.selectedViewController!.view, let toView = viewController.view else {
            return false // Make sure you want this as false
        }

        if fromView != toView {
            if (tabBarController.prevIndex > tabBarController.selectedIndex) {
                UIView.transition(from: fromView, to: toView, duration: 0.3, options: [.transitionFlipFromLeft], completion: nil)
            } else {
                UIView.transition(from: fromView, to: toView, duration: 0.3, options: [.transitionFlipFromRight], completion: nil)
            }
        }
        return true
    } else {
        return false
    }
}

The gesture recogniser is calling the following function, from which the above code is not called:

@objc func swiped(_ gesture: UISwipeGestureRecognizer) {
    if (CanChangeTab) {
        self.tabBarController?.prevIndex = (self.tabBarController?.selectedIndex)!
        if gesture.direction == .left {
            if (self.tabBarController?.selectedIndex)! < 4 { // set your total tabs here
                self.tabBarController?.selectedIndex += 1
            }
        } else if gesture.direction == .right {
            if (self.tabBarController?.selectedIndex)! > 0 {
                self.tabBarController?.selectedIndex -= 1
            }
        }
    }
}

I cannot see what should be called or overridden to get the animations for the gesture base change too.

Zoe
  • 27,060
  • 21
  • 118
  • 148
Endre Olah
  • 875
  • 2
  • 9
  • 25
  • This does not solve my problem. I think you misunderstood my problem. The animation works fine with your and with my solution too when you tap on the TabBar icons. But when you programmatically change tabs, the shouldSelect method is not called. I could not find what should I override to get the same effect when I change the tabs with a swipe. – Endre Olah Feb 23 '19 at 16:47

2 Answers2

0

The problem is that what you are doing is not how to do a tab bar controller animation. You have to write a formally structured custom animation transition.

This means that:

  • Your tab bar controller has a delegate implementing animationControllerForTransitionFrom to return a UIViewControllerAnimatedTransitioning object, and interactionControllerFor to return a UIViewControllerInteractiveTransitioning object.

  • These objects implement startInteractiveTransition, interruptibleAnimator(using:), transitionDuration(using:), animateTransition(using:), and animationEnded to perform the animation through a UIViewPropertyAnimator.

The gesture recognizer will then be able to trigger the animation by setting the selectedIndex and will be able to track and update the animation through the supplied UIViewControllerContextTransitioning object and the UIViewPropertyAnimator.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • For actual code, see https://github.com/mattneub/Programming-iOS-Book-Examples/blob/master/bk2ch06p300customAnimation3/ch19p620customAnimation1/AppDelegate.swift. – matt Feb 23 '19 at 17:02
0

Ok. I have found the solution, using ViewController slide animation

as Matt proposed.

So using the extension + the animateToTab function in the extension and changing my swipe method it works just as expected.

   @objc func swiped(_ gesture: UISwipeGestureRecognizer) {
    if (CanChangeTab) {
        let thisTabController = self.tabBarController as! iBayTabController

        thisTabController.prevIndex = (thisTabController.selectedIndex)
        if gesture.direction == .left {
            if thisTabController.selectedIndex < 4 { // set your total tabs here
                thisTabController.animateToTab(toIndex: thisTabController.selectedIndex+1)
            }
        } else if gesture.direction == .right {
            if (self.tabBarController?.selectedIndex)! > 0 {
                thisTabController.animateToTab(toIndex: thisTabController.selectedIndex-1)
            }
        }
    }
}
Endre Olah
  • 875
  • 2
  • 9
  • 25