iOS Custom Tabbar

How to make Custom TabBar?

As an example, it was written with two items.

You can branch to the tag depending on the selected item in didSelect() method.

In viewWillAppear(), I wrote the title of first item because the first item is selected when the app is first launched. (initialization)

I hope my answer is helpful to you.

TabBarController.swift

import UIKit

class TabBarController: UITabBarController, UITabBarControllerDelegate {

override func viewDidLoad() {
super.viewDidLoad()

self.delegate = self
}

override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)

//Setting the UITabBarItem

let tab1 = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(identifier: "ViewController")
let tab1BarItem = UITabBarItem(title: "home", image: UIImage(systemName: "seal"), selectedImage: UIImage(systemName: "seal.fill"))
tab1.tabBarItem = tab1BarItem
tab1.tabBarItem.tag = 0

let tab2 = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(identifier: "SearchViewController")
let tab2BarItem = UITabBarItem(title: "", image: UIImage(systemName: "checkmark.seal"), selectedImage: UIImage(systemName: "checkmark.seal.fill"))
tab2.tabBarItem = tab2BarItem
tab2.tabBarItem.tag = 1

self.viewControllers = [tab1, tab2]
}


override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {

if item.tag == 0 { // tab1(home)
item.title = "home"
tabBar.items?[1].title = ""
}

if item.tag == 1 { // tab2(search)
item.title = "search"
tabBar.items?[0].title = ""
}
}

}

Preview

Sample Image

Custom tab bar items

Maybe this will help, I tried to recreate your app:

import UIKit

class ViewController: UIViewController {

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

override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let tabBarVc = UITabBarController()

let vc1 = UINavigationController(rootViewController: vc1())
let vc2 = UINavigationController(rootViewController: vc2())
let vc3 = UINavigationController(rootViewController: vc3())
let vc4 = UINavigationController(rootViewController: vc4())
let vc5 = UINavigationController(rootViewController: vc5())

vc1.title = "home"
vc2.title = "contacts"
vc3.title = "create"
vc4.title = "contacts"
vc5.title = "contacts"

tabBarVc.setViewControllers([vc1,vc2,vc3,vc4,vc5], animated: false)
tabBarVc.tabBar.backgroundColor = .white

guard let items = tabBarVc.tabBar.items else {
return
}

let images = ["house","person.crop.circle.fill","plus.rectangle.fill","person.crop.circle.fill","person.crop.circle.fill"]
for x in 0..<items.count {
items[x].image = UIImage(systemName: images[x])
}

tabBarVc.modalPresentationStyle = .fullScreen
self.present(tabBarVc, animated: false, completion: nil)
}


}

class vc1: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .red
let app = UINavigationBarAppearance()
app.backgroundColor = .white
self.navigationController?.navigationBar.scrollEdgeAppearance = app
title = "home"

}
}

class vc2: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .purple
title = "contacts"
}
}

class vc3: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .blue
title = "Create"
}
}

class vc4: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()

view.backgroundColor = .green
title = "contacts"
}
}

class vc5: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()

view.backgroundColor = .yellow
title = "contacts"
}
}

Swift: Custom TabBar with center rounded button

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

Sample Image

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

How to create custom curved iOS UITabBar?

To create a UIBezierPath for your desired shape...

Sample Image

  • move to 1
  • add 90° clockwise arc with center c1
  • add line to 2
  • add 90° clockwise arc with center c2
  • add 180° counter-clockwise arc with center c3
  • add 90° clockwise arc with center c4
  • add line to 3
  • add 90° clockwise arc with center c5
  • add line to 4
  • add 90° clockwise arc with center c6
  • add line to 5
  • add 90° clockwise arc with center c7
  • close path

Here is some sample code - it's a UIView subclass, with all the path elements in layoutSubviews():

class TabBarShapeView: UIView {
var shapeLayer: CAShapeLayer!
override class var layerClass: AnyClass {
return CAShapeLayer.self
}

override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
private func commonInit() {
shapeLayer = self.layer as? CAShapeLayer
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.strokeColor = UIColor.gray.cgColor
shapeLayer.lineWidth = 1
}
override func layoutSubviews() {
super.layoutSubviews()

let middleRad: CGFloat = bounds.height - 10.0

let cornerRad: CGFloat = 12.0

let pth = UIBezierPath()

let topLeftC: CGPoint = CGPoint(x: bounds.minX + cornerRad, y: bounds.minY + cornerRad)
let topRightC: CGPoint = CGPoint(x: bounds.maxX - cornerRad, y: bounds.minY + cornerRad)
let botRightC: CGPoint = CGPoint(x: bounds.maxX - cornerRad, y: bounds.maxY - cornerRad)
let botLeftC: CGPoint = CGPoint(x: bounds.minX + cornerRad, y: bounds.maxY - cornerRad)

var pt: CGPoint!

// 1
pt = CGPoint(x: bounds.minX, y: bounds.minY + cornerRad)
pth.move(to: pt)

// c1
pth.addArc(withCenter: topLeftC, radius: cornerRad, startAngle: .pi * 1.0, endAngle: .pi * 1.5, clockwise: true)

// 2
pt = CGPoint(x: bounds.midX - middleRad, y: bounds.minY)
pth.addLine(to: pt)

// c2
pt.y += middleRad * 0.5
pth.addArc(withCenter: pt, radius: middleRad * 0.5, startAngle: -.pi * 0.5, endAngle: 0.0, clockwise: true)

// c3
pt.x += middleRad * 1.0
pth.addArc(withCenter: pt, radius: middleRad * 0.5, startAngle: .pi * 1.0, endAngle: 0.0, clockwise: false)

// c4
pt.x += middleRad * 1.0
pth.addArc(withCenter: pt, radius: middleRad * 0.5, startAngle: .pi * 1.0, endAngle: .pi * 1.5, clockwise: true)

// 3
pt = CGPoint(x: bounds.maxX - cornerRad, y: bounds.minY)
pth.addLine(to: pt)

// c5
pth.addArc(withCenter: topRightC, radius: cornerRad, startAngle: -.pi * 0.5, endAngle: 0.0, clockwise: true)

// 4
pt = CGPoint(x: bounds.maxX, y: bounds.maxY - cornerRad)
pth.addLine(to: pt)

// c6
pth.addArc(withCenter: botRightC, radius: cornerRad, startAngle: 0.0, endAngle: .pi * 0.5, clockwise: true)

// 5
pt = CGPoint(x: bounds.minX + cornerRad, y: bounds.maxY)
pth.addLine(to: pt)

// c7
pth.addArc(withCenter: botLeftC, radius: cornerRad, startAngle: .pi * 0.5, endAngle: .pi * 1.0, clockwise: true)

pth.close()

shapeLayer.path = pth.cgPath

}
}

Custom TabBar in top

Welcome to this world, well there's no such native control in iOS kit by which you can get a top tab bar, but lucikly there is a 3rd party library which will fulfill your design needs

https://github.com/xmartlabs/XLPagerTabStrip

Here's it is, all you need is to add it into your project using cocoapods after that follow its demo project and you will have a top tab bar in your project.
:)

How to set a custom tabBar to my custom TabBarController?

I managed to that by setting the value of 'tabBar' to my custom tabBar.

setValue(MycustomTabBar(frame: tabBar.frame), forKey: "tabBar")

class MyCustomTabBarController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
setValue(TBar(frame: tabBar.frame), forKey: "tabBar")
view.backgroundColor = .white
createShape()
}
}


Related Topics



Leave a reply



Submit