How to create Custom UITabBarController in Swift with round button in the center

0 votes

I'm looking to implement a custom UITabBarController in Swift. I have searched if there is a library or something that can be used to implement exactly same design, but couldn't find any. Most of the answers or libraries are outdated (after some changes that Apple made on NavigationBar and TabBar on iOS 15), or are not doing the exact same functionality as needed.

So, the TabBar should be with a rounded button in the center, between the button and TabBar should be some transparent space (padding). When that button is tapped it will popup a view.

The design can be seen on the image below.

enter image description here

Similar logic and UX has Binance app. So, when the button in the center is tapped, it popups a view to navigate to another View Controllers.

enter image description here

My Implementation

One of my implementations that worked best is the following one. I have two classes CustomTabBarController and CustomTabBar.

CustomTabBarController

import UIKit

class CustomTabBarController: UITabBarController, UITabBarControllerDelegate {
    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)!
    }

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

    // TabBarButton – Setup Middle Button
    func setupMiddleButton() {
    
        let middleBtn = UIButton(frame: CGRect(x: (self.view.bounds.width / 2)-25, y: -20, width: 50, height: 50))
    
        //STYLE THE BUTTON YOUR OWN WAY
        
        middleBtn.backgroundColor = .blue
        middleBtn.layer.cornerRadius = (middleBtn.layer.frame.width / 2)
    
        //add to the tabbar and add click event
        self.tabBar.addSubview(middleBtn)
        middleBtn.addTarget(self, action: #selector(self.menuButtonAction), for: .touchUpInside)
    
        self.view.layoutIfNeeded()
}

// 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.
    print("MenuButton")
}
}

CustomTabBar

import UIKit

@IBDesignable
class CustomTabBar: UITabBar {
    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) {
        self.addShape()
    }
    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))
        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
    }
}

Results

The results are not quite as expected. It's not creating a transparency on the curve in center. It's taking background color or sometimes adding just white background. This can be noticed mostly on TableView or any other scrolling UI

enter image description here

As for popup view when Floating Button is pressed I would like to hear any suggestion from you. What would be the best option for that?

Thank you in advance for your contribution.

Apr 27, 2023 in UI UX Design by Ashwini
• 5,430 points
2,334 views

1 answer to this question.

0 votes

Your implementation is almost correct, you just need to add a few modifications to achieve the desired result.

To create the transparent space in the center of the tab bar, you can modify the createPath function in the CustomTabBar class to create a curve with a smaller height and add a transparent sublayer to it.

answered Apr 27, 2023 by vishalini

Related Questions In UI UX Design

0 votes
1 answer

Trying to create a design system/kit with Swift

I can certainly guide you on where ...READ MORE

answered Apr 26, 2023 in UI UX Design by Tanishqa
• 1,170 points
727 views
0 votes
1 answer
0 votes
1 answer

UI/UX design or audit - how to measure the costs?

When it comes to charging for a ...READ MORE

answered Apr 25, 2023 in UI UX Design by Tej
644 views
0 votes
1 answer

How do I make it where when I change my window size, the content adjusts with it?

To make the content adjust with the ...READ MORE

answered Apr 26, 2023 in UI UX Design by Tanishqa
• 1,170 points
567 views
0 votes
0 answers

Tab Bar Appearances before ios 13

I have upgraded to Xcode 13, I'm ...READ MORE

Nov 10, 2022 in Mobile Development by gaurav
• 23,260 points
463 views
0 votes
1 answer

Get User Group in Swift using AWS Cognito

The groups are exposed in the ID ...READ MORE

answered Nov 12, 2018 in AWS by Priyaj
• 58,020 points
1,567 views
0 votes
1 answer

URL Scheme for iOS Home App

I think you could try doing it ...READ MORE

answered Nov 16, 2018 in IoT (Internet of Things) by nirvana
• 3,130 points
1,173 views
0 votes
1 answer

iOS App : Porting Code to App

If you make a post, missing parameters ...READ MORE

answered Jan 18, 2019 in IoT (Internet of Things) by Shubham
• 13,490 points
679 views
0 votes
1 answer

Is there a way to create a list that auto populates with the the required articles?

Yes, there are several ways to auto-populate ...READ MORE

answered Apr 27, 2023 in UI UX Design by Anitha
662 views
0 votes
1 answer
webinar REGISTER FOR FREE WEBINAR X
REGISTER NOW
webinar_success Thank you for registering Join Edureka Meetup community for 100+ Free Webinars each month JOIN MEETUP GROUP