Skip to content

Instantly share code, notes, and snippets.

@vurgunmert
Created August 21, 2024 08:59
Show Gist options
  • Save vurgunmert/dd5b5a249d160fe217c698304dd23b85 to your computer and use it in GitHub Desktop.
Save vurgunmert/dd5b5a249d160fe217c698304dd23b85 to your computer and use it in GitHub Desktop.
UIKit TabBar Storybook
//
// 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