Transition Delegate for Uitabbarcontroller Animation

Transition Delegate for UITabBarController animation

animationControllerForPresentedController is the wrong approach for the tab bar controller.

In the UITabBarController subclass, adopt the UITabBarControllerDelegate protocol and set it as its own delegate. Then, use tabBarController: animationControllerForTransitionFromViewController: toViewController: to return the custom UIViewControllerAnimatedTransitioning object.

To get a better visualization, look at VCTransitionsLibrary in the TabBarDemo folder.

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

There is a simpler way to doing this. Add the following code in the tabbar delegate:

Working on Swift 2, 3 and 4

class MySubclassedTabBarController: UITabBarController {

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

extension MySubclassedTabBarController: UITabBarControllerDelegate {
func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {

guard let fromView = selectedViewController?.view, let toView = viewController.view else {
return false // Make sure you want this as false
}

if fromView != toView {
UIView.transition(from: fromView, to: toView, duration: 0.3, options: [.transitionCrossDissolve], completion: nil)
}

return true
}
}

EDIT (4/23/18)
Since this answer is getting popular, I updated the code to remove the force unwraps, which is a bad practice, and added the guard statement.

EDIT (7/11/18)
@AlbertoGarcía is right. If you tap the tabbar icon twice you get a blank screen. So I added an extra check

How to enable tab bar transition animation to work without initial view controller

You need to subclass UITabBarController and use

class CustomTab:UITabBarController,UITabBarControllerDelegate { 
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self
}
func tabBarController(_ tabBarController: UITabBarController, animationControllerForTransitionFrom fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return MyFadeTransition()
}
}

Then assign CustomTab as class name to the tabBar in IB

iPhone: How to switch tabs with an animation?

Update 04/2016: Justed wanted to update this to say thank you to everyone for all the votes. Please also note that this was originally written way back when ... before ARC, before constraints, before ... a lot of stuff! So please take this into account when deciding whether to use these techniques. There may be more modern approaches. Oh, and if you find one. Please add a response so everyone can see. Thanks.

Some time later ...

After much research I came up with two working solutions. Both of these worked and did the animation between tabs.

Solution 1: transition from view (simple)

This is the easiest and makes use of a predefined UIView transition method. With this solution we don't need to manage the views because the method does the work for us.

// Get views. controllerIndex is passed in as the controller we want to go to. 
UIView * fromView = tabBarController.selectedViewController.view;
UIView * toView = [[tabBarController.viewControllers objectAtIndex:controllerIndex] view];

// Transition using a page curl.
[UIView transitionFromView:fromView
toView:toView
duration:0.5
options:(controllerIndex > tabBarController.selectedIndex ? UIViewAnimationOptionTransitionCurlUp : UIViewAnimationOptionTransitionCurlDown)
completion:^(BOOL finished) {
if (finished) {
tabBarController.selectedIndex = controllerIndex;
}
}];

Solution 2: scroll (more complex)

A more complex solution, but gives you more control of the animation. In this example we get the views to slide on and off. With this one we need to manage the views ourselves.

// Get the views.
UIView * fromView = tabBarController.selectedViewController.view;
UIView * toView = [[tabBarController.viewControllers objectAtIndex:controllerIndex] view];

// Get the size of the view area.
CGRect viewSize = fromView.frame;
BOOL scrollRight = controllerIndex > tabBarController.selectedIndex;

// Add the to view to the tab bar view.
[fromView.superview addSubview:toView];

// Position it off screen.
toView.frame = CGRectMake((scrollRight ? 320 : -320), viewSize.origin.y, 320, viewSize.size.height);

[UIView animateWithDuration:0.3
animations: ^{

// Animate the views on and off the screen. This will appear to slide.
fromView.frame =CGRectMake((scrollRight ? -320 : 320), viewSize.origin.y, 320, viewSize.size.height);
toView.frame =CGRectMake(0, viewSize.origin.y, 320, viewSize.size.height);
}

completion:^(BOOL finished) {
if (finished) {

// Remove the old view from the tabbar view.
[fromView removeFromSuperview];
tabBarController.selectedIndex = controllerIndex;
}
}];

This Solution in Swift:

extension TabViewController: UITabBarControllerDelegate {
public func tabBarController(tabBarController: UITabBarController, shouldSelectViewController viewController: UIViewController) -> Bool {

let fromView: UIView = tabBarController.selectedViewController!.view
let toView : UIView = viewController.view
if fromView == toView {
return false
}

UIView.transitionFromView(fromView, toView: toView, duration: 0.3, options: UIViewAnimationOptions.TransitionCrossDissolve) { (finished:Bool) in

}
return true
}
}

How to change tab bar programmatically with animation?

As a workaround you could trigger your animation manually. I don't know if it is recommended but it is working for me.

    func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
animateTabBarChange(tabBarController: tabBarController, to: viewController)
return true
}

func animateTabBarChange(tabBarController: UITabBarController, to viewController: UIViewController) {
let fromView: UIView = tabBarController.selectedViewController!.view
let toView: UIView = viewController.view

// do whatever animation you like

}

Then you call it like this:

let index = 2
animateTabBarChange(tabBarController: self.tabBarController!, to: self.tabBarController!.viewControllers![index])
self.tabBarController?.selectedIndex = index

View transitions when TabBatController.selectedIndex changed programmatically

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)
}
}
}
}

iOS / Objective c - UITabBarControllerDelegate - Custom tab animation delegates not called

I think you are using the wrong delegate method for what you are trying to accomplish. Try using:

- (nullable id <UIViewControllerAnimatedTransitioning>)tabBarController:(UITabBarController *)tabBarController
animationControllerForTransitionFromViewController:(UIViewController *)fromVC
toViewController:(UIViewController *)toVC;

This will be called when the user taps on a different tab.



Related Topics



Leave a reply



Submit