Animated Custom TabBar View/ Swift / UIKit / Programmatically

Khayala Hasanli
3 min readFeb 19, 2023

--

While searching for a custom Tab Bar design for my own project, I realized that there are not many code resources on this subject. For this reason, I decided to prepare an explanatory example on custom Tab Bar with animation.

We will need several things and lets go step by step:

  1. UITabBarController → It contains other UIViewController
import UIKit

class MainViewController: UITabBarController {

override func viewDidLoad() {
super.viewDidLoad()
}

}

2. TabbarView → It will contain buttons and animated (moving) background view for items.

import UIKit

class MainViewController: UITabBarController {

let tabbarView = UIView()

override func viewDidLoad() {
super.viewDidLoad()
setView()
}

private func setView(){
view.addSubview(tabbarView)
tabbarView.backgroundColor = .quaternarySystemFill
tabbarView.translatesAutoresizingMaskIntoConstraints = false
tabbarView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -60).isActive = true
tabbarView.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -60).isActive = true
tabbarView.heightAnchor.constraint(equalToConstant: 60).isActive = true
tabbarView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
tabbarView.layer.cornerRadius = 30
}
}

3. Generator function → for creating UIViewControllers and Buttons. Also we need a variable to contain buttons for using later.

var buttons : [UIButton] = []

private func generateControllers(){
let home = generateViewControllers(image: UIImage(systemName: "house.fill")!, vc: UIViewController())
let profile = generateViewControllers(image: UIImage(systemName: "person.fill")!, vc: UIViewController())
let setting = generateViewControllers(image: UIImage(systemName: "gearshape.fill")!, vc: UIViewController())
let bookmark = generateViewControllers(image: UIImage(systemName: "bookmark.fill")!, vc: UIViewController())
viewControllers = [home, profile, setting, bookmark]
}

private func generateViewControllers(image: UIImage, vc: UIViewController) -> UIViewController {
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
button.tintColor = .orange
let image = image.resize(targetSize: CGSize(width: 25, height: 25)).withRenderingMode(.alwaysTemplate)
button.setImage(image, for: .normal)
buttons.append(button)
return vc
}

4. After creating UIViewControllers and buttons we need to show them. First, lets show buttons by looping them on setView() function.

 for x in 0..<buttons.count {
view.addSubview(buttons[x])
buttons[x].tag = x
buttons[x].centerYAnchor.constraint(equalTo: tabbarView.centerYAnchor).isActive = true
buttons[x].widthAnchor.constraint(equalTo: tabbarView.widthAnchor, multiplier: 1/CGFloat(buttons.count)).isActive = true
buttons[x].heightAnchor.constraint(equalTo: tabbarView.heightAnchor).isActive = true
buttons[x].addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
centerConstraint = tabbarItemBackgroundView.centerXAnchor.constraint(equalTo: buttons[x].centerXAnchor)
centerConstraint?.isActive = true
if x == 0 {
buttons[x].leftAnchor.constraint(equalTo: tabbarView.leftAnchor).isActive = true
} else {
buttons[x].leftAnchor.constraint(equalTo: buttons[x-1].rightAnchor).isActive = true
}
}

5. Tabbar Item Background View → Now we need a UIView which will move between buttons and show better view. Also for moving we need a NSLayoutConstraint.

 let tabbarItemBackgroundView = UIView()
var centerConstraint: NSLayoutConstraint?

! Do not forget to add it to setView() function.

   tabbarView.addSubview(tabbarItemBackgroundView)
tabbarItemBackgroundView.translatesAutoresizingMaskIntoConstraints = false
tabbarItemBackgroundView.widthAnchor.constraint(equalTo: tabbarView.widthAnchor, multiplier: 1/CGFloat(buttons.count), constant: -10).isActive = true
tabbarItemBackgroundView.heightAnchor.constraint(equalTo: tabbarView.heightAnchor, constant: -10).isActive = true
tabbarItemBackgroundView.centerYAnchor.constraint(equalTo: tabbarView.centerYAnchor).isActive = true
tabbarItemBackgroundView.layer.cornerRadius = 25
tabbarItemBackgroundView.backgroundColor = .orange

6. Final step is adding animation for tabbarItemBackgroundView.

@objc private func buttonTapped(sender: UIButton) {
selectedIndex = sender.tag

for button in buttons {
button.tintColor = .orange
}

UIView.animate(withDuration: 0.5, delay: 0 , options: .beginFromCurrentState) {
self.centerConstraint?.isActive = false
self.centerConstraint = self.tabbarItemBackgroundView.centerXAnchor.constraint(equalTo: self.buttons[sender.tag].centerXAnchor)
self.centerConstraint?.isActive = true
self.buttons[sender.tag].tintColor = .black
self.tabbarView.layoutIfNeeded()
}
}

7. Resize image.

extension UIImage {
func resize(targetSize: CGSize) -> UIImage {
return UIGraphicsImageRenderer(size:targetSize).image { _ in
self.draw(in: CGRect(origin: .zero, size: targetSize))
}
}
}

Congrulation 🎉 you have animated tabbar view.

Please do not forget to write comment and share your opinions.

--

--