Tab Bars are an essential component and one of the most commonly used features in iOS app design. It provides easy navigation and enhances the look and feel.

Enhancing the Tab bar with customized sleek designs can instantly make your app stand out.

Set up the storyboard…

I assume you have created your new iOS project. Before we start, just set up your viewcontrollers.

  1. Add a TabBarController into your Storyboard.
  2. Add 3 or 5 ViewControllers and link them to the TabBarController

Create a new class MyTabBarCtrl.swift

import UIKit
class MyTabBarCtrl: UITabBarController, UITabBarControllerDelegate {
    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)!

    override func viewDidLoad() {
        self.delegate = self

Go back to storyboard, and change your TabBarController class to MyTabBarCtrl.

Draw the TabBar shape

We need to subclass the TabBar. Create a new class MyTabBar.swift

import UIKit
class MyTabBar: UITabBar {


The shape layer was inspired from this article. Add the following to MyTabBar class.

private var shapeLayer: CALayer?
private func addShape() {
    let shapeLayer = CAShapeLayer()
    shapeLayer.path = createPath()
    shapeLayer.strokeColor = UIColor.lightGray.cgColor
    shapeLayer.fillColor = UIColor.white.cgColor
    shapeLayer.lineWidth = 1.0
    //The below 4 lines are for shadow above the bar. you can skip them if you do not want a shadow
    shapeLayer.shadowOffset = CGSize(width:0, height:0)
    shapeLayer.shadowRadius = 10
    shapeLayer.shadowColor = UIColor.gray.cgColor
    shapeLayer.shadowOpacity = 0.3

    if let oldShapeLayer = self.shapeLayer {
        self.layer.replaceSublayer(oldShapeLayer, with: shapeLayer)
    } else {
        self.layer.insertSublayer(shapeLayer, at: 0)
    self.shapeLayer = shapeLayer
override func draw(_ rect: CGRect) {
func createPath() -> CGPath {
    let height: CGFloat = 37.0
    let path = UIBezierPath()
    let centerWidth = self.frame.width / 2
    path.move(to: CGPoint(x: 0, y: 0)) // start top left
    path.addLine(to: CGPoint(x: (centerWidth - height * 2), y: 0)) // the beginning of the trough

    path.addCurve(to: CGPoint(x: centerWidth, y: height),
    controlPoint1: CGPoint(x: (centerWidth - 30), y: 0), controlPoint2: CGPoint(x: centerWidth - 35, y: height))

    path.addCurve(to: CGPoint(x: (centerWidth + height * 2), y: 0),
    controlPoint1: CGPoint(x: centerWidth + 35, y: height), controlPoint2: CGPoint(x: (centerWidth + 30), y: 0))

    path.addLine(to: CGPoint(x: self.frame.width, y: 0))
    path.addLine(to: CGPoint(x: self.frame.width, y: self.frame.height))
    path.addLine(to: CGPoint(x: 0, y: self.frame.height))

    return path.cgPath

That’s all for the shape!

But there’s a tiny problem. The middle button is raised a little beyond the bounds of the TabBar view. By default, click events won’t be caught on views outside of the bounds of it’s superview. To solve this, we override hitTest:withEvent: method. Add thin in the same MyTabBar class

    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        guard !clipsToBounds && !isHidden && alpha > 0 else { return nil }
        for member in subviews.reversed() {
            let subPoint = member.convert(point, from: self)
            guard let result = member.hitTest(subPoint, with: event) else { continue }
            return result
        return nil

Go back to your storyboard. Select TabBar object under MyTabBarCtrl. and under Identity Inspector, Select MyTabBar,

Screenshot 2019-02-22 at 11.46.29 PM.pngScreenshot 2019-02-22 at 11.48.43 PM.png

The shape of the tab bar should now be visible in your view controller in the storyboard.

Design the middle button

Open MyTabBarCtrl.swift and add this function

    // TabBarButton – Setup Middle Button
    func setupMiddleButton() {

        let middleBtn = UIButton(frame: CGRect(x: (self.view.bounds.width / 2)-25, y: -20, width: 50, height: 50))
        middleBtn.setIcon(icon: .fontAwesomeSolid(.home), iconSize: 20.0, color: UIColor.white, backgroundColor: UIColor.white, forState: .normal)
        middleBtn.applyGradient(colors: colorBlueDark.cgColor,colorBlueLight.cgColor])
        //add to the tabbar and add click event
        middleBtn.addTarget(self, action: #selector(self.menuButtonAction), for: .touchUpInside)


    // Menu Button Touch Action
    @objc func menuButtonAction(sender: UIButton) {
        self.selectedIndex = 2   //to select the middle tab. use "1" if you have only 3 tabs.

For setIcon, I used this library.

For the button gradient, check out this tutorial.

Call this function in your TabBarController’s viewDidLoad().

That’s all!