Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to animate tab bar's items

In my Swift app I have this class that handles a UITabBar.

class CustomTabBar: UITabBar {
    override func awakeFromNib() {
        super.awakeFromNib()
    }
}

How can I animate the items when the user tap their? I mean a CGAffine(scaleX: 1.1, y: 1.1) So how I can animate the tab bar's items?

like image 755
Jack K. Avatar asked Oct 24 '18 16:10

Jack K.


3 Answers

First:

create a custom UITabBarController as follows:
import UIKit

enum TabbarItemTag: Int {
    case firstViewController = 101
    case secondViewConroller = 102
}

class CustomTabBarController: UITabBarController {
    var firstTabbarItemImageView: UIImageView!
    var secondTabbarItemImageView: UIImageView!

    override func viewDidLoad() {
        super.viewDidLoad()

        let firstItemView = tabBar.subviews.first!
        firstTabbarItemImageView = firstItemView.subviews.first as? UIImageView
        firstTabbarItemImageView.contentMode = .center

        let secondItemView = self.tabBar.subviews[1]
        self.secondTabbarItemImageView = secondItemView.subviews.first as? UIImageView
        self.secondTabbarItemImageView.contentMode = .center
    }

    private func animate(_ imageView: UIImageView) {
        UIView.animate(withDuration: 0.1, animations: {
            imageView.transform = CGAffineTransform(scaleX: 1.25, y: 1.25)
        }) { _ in
            UIView.animate(withDuration: 0.25, delay: 0.0, usingSpringWithDamping: 0.5, initialSpringVelocity: 3.0, options: .curveEaseInOut, animations: {
                imageView.transform = CGAffineTransform(scaleX: 1.0, y: 1.0)
            }, completion: nil)
        }
    }

    override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
        guard let tabbarItemTag = TabbarItemTag(rawValue: item.tag) else {
            return
        }

        switch tabbarItemTag {
        case .firstViewController:
            animate(firstTabbarItemImageView)
        case .secondViewConroller:
            animate(secondTabbarItemImageView)
        }
    }
}

Second:

Set the tag values for the tabBarItem for each view controller:

First ViewController:

import UIKit

class FirstViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        tabBarItem.tag = TabbarItemTag.firstViewController.rawValue
    }
}

Second ViewController:

import UIKit

class SecondViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        tabBarItem.tag = TabbarItemTag.secondViewConroller.rawValue
    }
}

Make sure that everything has been setup with your storyboard (if you are using one) and that's pretty much it!

Output:

enter image description here

You could check the repo:

https://github.com/AhmadFayyas/Animated-TabbarItem/tree/master

for demonstrating the answer.

like image 176
Ahmad F Avatar answered Nov 20 '22 12:11

Ahmad F


This do the trick for me:

class MyCustomTabController: UITabBarController {

    override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
        guard let barItemView = item.value(forKey: "view") as? UIView else { return }

        let timeInterval: TimeInterval = 0.3
        let propertyAnimator = UIViewPropertyAnimator(duration: timeInterval, dampingRatio: 0.5) {
            barItemView.transform = CGAffineTransform.identity.scaledBy(x: 0.9, y: 0.9)
        }
        propertyAnimator.addAnimations({ barItemView.transform = .identity }, delayFactor: CGFloat(timeInterval))
        propertyAnimator.startAnimation()
    }

}
like image 34
Val Moratalla Avatar answered Nov 20 '22 13:11

Val Moratalla


As UITabBarItem is not a UIView subclass, but an NSObject subclass instead, there is no direct way to animate an item when tapped.

You either have to dig up the UIView that belongs to the item and animate that, or create a custom tab bar.

Here are some ideas for digging up the UIView. And here for example how to get triggered when an item is tapped. But be very careful with this approach:

  • Apple may change the UITabBar implementation, which could break this.
  • You may interfere with iOS animations and get weird effects.

By the way, there's no need to subclass UITabBar. Implementing UITabBarDelegate is all you'd need.

I would actually advise you to just stick with the standard UITabBar behaviour & skinning options, and figure this out later or not at all. Things like this can burn your time without adding much to the app.

like image 37
meaning-matters Avatar answered Nov 20 '22 13:11

meaning-matters