Swift: Custom TabBar with center rounded button

14,248

You need to customise the tabbar of your CustomTabBarController

Just assign the AppTabBar to the tabbar of your tabBarController for storyboard like this it should works

enter image description here

@IBDesignable
class AppTabBar: UITabBar {

    private var shapeLayer: CALayer?

    override func draw(_ rect: CGRect) {
        self.addShape()
    }

    private func addShape() {
        let shapeLayer = CAShapeLayer()
        shapeLayer.path = createPath()
        shapeLayer.strokeColor = UIColor.lightGray.cgColor
        shapeLayer.fillColor = #colorLiteral(red: 0.9782002568, green: 0.9782230258, blue: 0.9782107472, alpha: 1)
        shapeLayer.lineWidth = 0.5
        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
    }

    func createPath() -> CGPath {
        let height: CGFloat = 86.0
        let path = UIBezierPath()
        let centerWidth = self.frame.width / 2
        path.move(to: CGPoint(x: 0, y: 0))
        path.addLine(to: CGPoint(x: (centerWidth - height ), y: 0))
        path.addCurve(to: CGPoint(x: centerWidth, y: height - 40),
                      controlPoint1: CGPoint(x: (centerWidth - 30), y: 0), controlPoint2: CGPoint(x: centerWidth - 35, y: height - 40))
        path.addCurve(to: CGPoint(x: (centerWidth + height ), y: 0),
                      controlPoint1: CGPoint(x: centerWidth + 35, y: height - 40), 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))
        path.close()
        return path.cgPath
    }

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

extension UITabBar {
    override open func sizeThatFits(_ size: CGSize) -> CGSize {
        var sizeThatFits = super.sizeThatFits(size)
        sizeThatFits.height = 74
        return sizeThatFits
    }
}
Share:
14,248
Mickael Belhassen
Author by

Mickael Belhassen

Updated on June 09, 2022

Comments

  • Mickael Belhassen
    Mickael Belhassen almost 2 years

    I try to create custom tabbar like the below picture: enter image description here

    Below is the result i get: enter image description here

    Below is my current code:

    class CustomTabBarController: UITabBarController {
    
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            let controller1 = UIViewController()
            controller1.tabBarItem = UITabBarItem(tabBarSystemItem: .contacts, tag: 1)
            let nav1 = UINavigationController(rootViewController: controller1)
    
            let controller2 = UIViewController()
            controller2.tabBarItem = UITabBarItem(tabBarSystemItem: .contacts, tag: 2)
            let nav2 = UINavigationController(rootViewController: controller2)
    
            let controller3 = UIViewController()
            let nav3 = UINavigationController(rootViewController: controller3)
            nav3.title = ""
    
            let controller4 = UIViewController()
            controller4.tabBarItem = UITabBarItem(tabBarSystemItem: .contacts, tag: 4)
            let nav4 = UINavigationController(rootViewController: controller4)
    
            let controller5 = UIViewController()
            controller5.tabBarItem = UITabBarItem(tabBarSystemItem: .contacts, tag: 5)
            let nav5 = UINavigationController(rootViewController: controller5)
    
            viewControllers = [nav1, nav2, nav3, nav4, nav5]
            setupMiddleButton()  
        }
    
        func setupMiddleButton() {
            let menuButton = UIButton(frame: CGRect(x: 0, y: 0, width: 64, height: 64))
            var menuButtonFrame = menuButton.frame
            menuButtonFrame.origin.y = view.bounds.height - menuButtonFrame.height - 50
            menuButtonFrame.origin.x = view.bounds.width/2 - menuButtonFrame.size.width/2
            menuButton.frame = menuButtonFrame
    
            menuButton.backgroundColor = UIColor.red
            menuButton.layer.cornerRadius = menuButtonFrame.height/2
            view.addSubview(menuButton)
    
            menuButton.setImage(UIImage(named: "example"), for: .normal)
            menuButton.addTarget(self, action: #selector(menuButtonAction(sender:)), for: .touchUpInside)
    
            view.layoutIfNeeded()
        }
    
    
        // MARK: - Actions
    
        @objc private func menuButtonAction(sender: UIButton) {
            selectedIndex = 2
        }
    
    }
    
    

    How can I draw the shape of the tabbar of the first picture joint

    I'm stuck on it that makes several thanks for your help