Last active
July 26, 2023 19:03
-
-
Save egzonpllana/cc5538f388d8a530e7c393e7344e57a5 to your computer and use it in GitHub Desktop.
Add Indicator View over tab bar item. (Swift 5)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@uzair045 update the whole implementation, now it should be working fine.