Created
August 21, 2024 08:59
-
-
Save vurgunmert/dd5b5a249d160fe217c698304dd23b85 to your computer and use it in GitHub Desktop.
UIKit TabBar Storybook
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
// | |
// UIKitTabBarStorybookController.swift | |
// | |
// Created by Mert Vurgun on 21.08.2024. | |
// | |
import Foundation | |
import UIKit | |
class UIKitTabBarStorybookController: UIViewController { | |
//MARK: 1. Create presentation | |
private let tabBar = UITabBar() | |
//MARK: 2. Create subitems presentations | |
private let tabItems = [ | |
UITabBarItem(title: "Home", image: UIImage(systemName: "house"), tag: 0), | |
UITabBarItem(title: "Search", image: UIImage(systemName: "magnifyingglass"), tag: 1), | |
UITabBarItem(title: "Settings", image: UIImage(systemName: "gearshape"), tag: 2), | |
UITabBarItem(title: "Move Top", image: UIImage(systemName: "arrow.up"), tag: 3), | |
UITabBarItem(title: nil, image: UIImage(systemName: "arrow.down"), tag: 4) | |
] | |
//MARK: 3. Constraint references for updating | |
private var tabBarTopConstraint: NSLayoutConstraint! | |
private var tabBarBottomConstraint: NSLayoutConstraint! | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
view.backgroundColor = .black | |
//MARK: 4. Load tab initial data & properties | |
tabBar.items = tabItems | |
tabBar.selectedItem = tabItems.first | |
tabBar.delegate = self | |
//MARK: 5. Add tab to presenting view | |
view.addSubview(tabBar) | |
//MARK: 6. Position tab with initial constraints | |
tabBar.translatesAutoresizingMaskIntoConstraints = false | |
tabBarTopConstraint = tabBar.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor) | |
tabBarBottomConstraint = tabBar.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) | |
NSLayoutConstraint.activate([ | |
tabBar.leadingAnchor.constraint(equalTo: view.leadingAnchor), | |
tabBar.trailingAnchor.constraint(equalTo: view.trailingAnchor), | |
tabBarTopConstraint | |
]) | |
} | |
} | |
//MARK: 7. Scope tab functionalities e.g listeners | |
extension UIKitTabBarStorybookController: UITabBarDelegate { | |
//MARK: 8. Handle tab selection | |
func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) { | |
switch item.tag { | |
case 0: | |
print("Home tab selected") | |
updateUI(for: "Home") | |
case 1: | |
print("Search tab selected") | |
updateUI(for: "Search") | |
case 2: | |
print("Settings tab selected") | |
updateUI(for: "Settings") | |
case 3: | |
print("Move Top tab selected") | |
moveTabBar(to: .top) | |
case 4: | |
print("Move Bottom tab selected") | |
moveTabBar(to: .bottom) | |
default: | |
break | |
} | |
} | |
//MARK: 9. UI update method | |
private func updateUI(for tab: String) { | |
let label = UILabel() | |
label.text = "\(tab) selected" | |
label.textColor = .white | |
label.textAlignment = .center | |
label.translatesAutoresizingMaskIntoConstraints = false | |
view.subviews.filter { $0 is UILabel }.forEach { $0.removeFromSuperview() } | |
view.addSubview(label) | |
NSLayoutConstraint.activate([ | |
label.centerXAnchor.constraint(equalTo: view.centerXAnchor), | |
label.centerYAnchor.constraint(equalTo: view.centerYAnchor) | |
]) | |
} | |
//MARK: 10. TabBar position update method | |
private func moveTabBar(to position: TabBarPosition) { | |
// Don't forget to deactivate both constraints before updating | |
// This caused some issues on TCH app | |
tabBarTopConstraint.isActive = false | |
tabBarBottomConstraint.isActive = false | |
switch position { | |
case .top: | |
tabBarTopConstraint.isActive = true | |
case .bottom: | |
tabBarBottomConstraint.isActive = true | |
} | |
UIView.animate(withDuration: 0.3) { | |
self.view.layoutIfNeeded() | |
} | |
} | |
enum TabBarPosition { | |
case top | |
case bottom | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment