Skip to content

Instantly share code, notes, and snippets.

@egzonpllana
Last active July 26, 2023 19:03
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save egzonpllana/cc5538f388d8a530e7c393e7344e57a5 to your computer and use it in GitHub Desktop.
Save egzonpllana/cc5538f388d8a530e7c393e7344e57a5 to your computer and use it in GitHub Desktop.
Add Indicator View over tab bar item. (Swift 5)
//
// Created by Egzon Pllana on 13.4.23.
// Copyright © 2023 Native Coders. All rights reserved.
//
import UIKit
class IndicatingTabBarController: UITabBarController, UITabBarControllerDelegate {
// MARK: - Properties -
private let indicatorView: UIView = {
let view = UIView()
view.backgroundColor = .black
return view
}()
// Set attributes as you need here
private lazy var indicatorWidth: Double = tabBar.bounds.width / CGFloat(tabBar.items?.count ?? 1)
private var indicatorColor: UIColor = .black
// MARK: - Life cycle -
override func viewDidLoad() {
super.viewDidLoad()
// Add the line indicator as a subview of the tab bar
tabBar.addSubview(indicatorView)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
// Position the line indicator at the bottom of the selected tab item
moveIndicator()
}
// MARK: - Methods -
func moveIndicator(at index: Int=0) {
let itemWidth = (tabBar.bounds.width / CGFloat(tabBar.items?.count ?? 1))
let xPosition = (CGFloat(index) * itemWidth) + ((itemWidth / 2) - (indicatorWidth / 2))
UIView.animate(withDuration: 0.3) { [self] in
self.indicatorView.frame = CGRect(x: xPosition,
y: 1,
width: self.indicatorWidth,
height: 1)
self.indicatorView.backgroundColor = self.indicatorColor
}
}
// MARK: - UITabBarControllerDelegate -
override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
guard let items = tabBar.items else { return }
moveIndicator(at: items.firstIndex(of: item) ?? 0)
}
}
// ------- How to use ------- //
// Step 1:
// Create new file: TabBarController
class TabBarController: IndicatingTabBarController {
// MARK: - Life cycle -
override func viewDidLoad() {
super.viewDidLoad()
}
}
// Step 2:
// In storyboard, select tab bar controller and set its class to TabBarController.
// ------- Additional ------- //
// If you need to listen to tab bar delegate method didSelect, please do:
class TabBarController: IndicatingTabBarController {
// MARK: - Life cycle -
override func viewDidLoad() {
super.viewDidLoad()
}
// MARK: - UITabBarControllerDelegate
override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
guard let items = tabBar.items else { return }
moveIndicator(at: items.firstIndex(of: item) ?? 0)
}
}
// Note:
// If you want to customize tab bar indicating view color, width, height, position,
// please do it inside IndicatingTabBarController.
@arjunshukla22
Copy link

Hey Buddy ,

Can you please tell where you define customizeTabBarUI this Function

@egzonpllana
Copy link
Author

Hi @arjunshukla22, you should create a new class of type "UITabBarController" and use it for your tab bar controller. See line 66 on the current code snipet.

@arjunshukla22
Copy link

Hey Buddy ,
I got An issue When User leave Tab Bar Controller & Back to Same Controller TabBarIndicatorView view is hide.

@egzonpllana
Copy link
Author

Hi @arjunshukla22, it's a known issue by other users but I don't have time to find a fix for that. You should layout TabBarIndicatorView somewhere in TabBarViewController class. If you find any good fix for this, please let us know so we can update this gist for future users. Thank you!

@arjunshukla22
Copy link

Thanx For the Update .

@uzair045
Copy link

Hi @egzonpllana, Where are you adding indicator view into tab bar?

@egzonpllana
Copy link
Author

@uzair045 update the whole implementation, now it should be working fine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment