Skip to content

Instantly share code, notes, and snippets.

@churabou
Created October 29, 2019 11:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save churabou/29e59e02a93f3640b5d3e47890042609 to your computer and use it in GitHub Desktop.
Save churabou/29e59e02a93f3640b5d3e47890042609 to your computer and use it in GitHub Desktop.
Custom TabBarViewController
import UIKit
extension UIColor {
convenience init(hex: UInt32, alpha: CGFloat = 1) {
let r = CGFloat((hex & 0xFF0000) >> 16) / 255
let g = CGFloat((hex & 0x00FF00) >> 8) / 255
let b = CGFloat(hex & 0x0000FF) / 255
self.init(red: r, green: g, blue: b, alpha: alpha)
}
}
final class DummyViewController: UIViewController {
private var text: String
private var color: UIColor
init(text: String, color: UIColor) {
self.text = text
self.color = color
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func loadView() {
let label = UILabel()
label.text = text
label.backgroundColor = color
label.font = .boldSystemFont(ofSize: 40)
label.textColor = .white
label.textAlignment = .center
view = label
}
override func viewDidLoad() {
super.viewDidLoad()
print(#function, text)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
print(#function, text)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
print(#function, text)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillAppear(animated)
print(#function, text)
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
print(#function, text)
}
}
protocol TabViewDelegate: AnyObject {
func didSelectTab(_ selectedIndex: Int)
}
final class TabView: UIView {
weak var delegate: TabViewDelegate?
private var buttons: [UIButton] = []
override init(frame: CGRect) {
super.init(frame: frame)
initializeView()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
let width = bounds.width / CGFloat(buttons.count)
let height = bounds.height
buttons.enumerated().forEach { index, button in
button.frame = CGRect(
origin: CGPoint(x: width * CGFloat(index), y: 0),
size: CGSize(width: width, height: height)
)
}
}
}
private extension TabView {
func initializeView() {
buttons = (0...3).map { index in
let button = UIButton()
button.tag = index
button.setTitle(index.description, for: .normal)
button.titleLabel?.font = .boldSystemFont(ofSize: 28)
button.setTitleColor(.white, for: .normal)
button.backgroundColor = .black
button.addTarget(self, action: #selector(selectButton), for: .touchUpInside)
addSubview(button )
return button
}
}
@objc func selectButton(_ sender: UIButton) {
delegate?.didSelectTab(sender.tag)
}
}
final class TabViewController: UIViewController {
private let contentView = UIView()
private let tabView = TabView()
private let viewControllers = [
DummyViewController(text: "0", color: UIColor(hex: 0xffc4e4)),
DummyViewController(text: "1", color: UIColor(hex: 0xc4f4ff)),
DummyViewController(text: "2", color: UIColor(hex: 0xcfffd9)),
DummyViewController(text: "3", color: UIColor(hex: 0xddd1ff))
]
private var selectedViewController: UIViewController?
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(contentView)
tabView.delegate = self
view.addSubview(tabView)
if let firstViewController = viewControllers.first {
selectedViewController = firstViewController
add(controller: firstViewController)
}
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let tabviewHeight: CGFloat = 80
contentView.frame = CGRect(
origin: .zero,
size: CGSize(width: view.bounds.width, height: view.bounds.height - tabviewHeight)
)
tabView.frame = CGRect(
origin: CGPoint(x: 0, y: contentView.bounds.height),
size: CGSize(width: view.bounds.width, height: tabviewHeight)
)
}
}
extension TabViewController: TabViewDelegate {
func didSelectTab(_ selectedIndex: Int) {
guard let fromViewController = selectedViewController,
viewControllers.count > selectedIndex else {
return
}
let toViewController = viewControllers[selectedIndex]
if fromViewController !== toViewController {
toViewController.beginAppearanceTransition(true, animated: true)
fromViewController.beginAppearanceTransition(false, animated: true)
add(controller: toViewController)
remove(controller: fromViewController)
fromViewController.endAppearanceTransition()
toViewController.endAppearanceTransition()
selectedViewController = toViewController
}
}
}
private extension TabViewController {
func add(controller: UIViewController) {
controller.willMove(toParent: self)
addChild(controller)
controller.view.frame = view.bounds
contentView.addSubview(controller.view)
}
func remove(controller: UIViewController) {
controller.willMove(toParent: nil)
controller.removeFromParent()
controller.view.removeFromSuperview()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment