I would like a dropdown menu to drop once the user taps on the right button inside the Navigation Bar. My go to achieve this is as follow:
(1) Created a custom UIView class, which basically is going to contains the tableView to be displayed (dropped) when the user taps the Navigation Bar right button:
import UIKit
class DropdownUIView: UIView, UITableViewDelegate, UITableViewDataSource {
var dropdownTableSections = ["Ascending Order","Descending Order"]
var ascendingAndDescendingOrderSetionItmes = ["Section Designaion","Depth, h","Width, b","Area of Section, A"]
var dropdownTableView = UITableView()
override init(frame: CGRect) {
super.init(frame: frame)
dropdownTableView.delegate = self
dropdownTableView.dataSource = self
self.addSubview(dropdownTableView)
dropdownTableView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
dropdownTableView.leftAnchor.constraint(equalTo: self.leftAnchor),
dropdownTableView.rightAnchor.constraint(equalTo: self.rightAnchor),
dropdownTableView.topAnchor.constraint(equalTo: self.topAnchor),
dropdownTableView.bottomAnchor.constraint(equalTo: self.bottomAnchor)
])
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func numberOfSections(in tableView: UITableView) -> Int {
return dropdownTableSections.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return ascendingAndDescendingOrderSetionItmes.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = ascendingAndDescendingOrderSetionItmes[indexPath.row]
return cell
}
}
(2) Created a custom UIButton Class, whereby I added to it the above dropdown view as a SubView. This is going to be the button to be added to the custom NavigationBar class as a UIView:
import UIKit
class DropdownUIButton: UIButton {
var dropdownView = DropdownUIView()
var dropdownViewHeight = NSLayoutConstraint()
var isOpen = false
override init(frame: CGRect) {
super.init(frame: frame)
translatesAutoresizingMaskIntoConstraints = false
self.backgroundColor = UIColor.darkGray
dropdownView = DropdownUIView.init(frame: CGRect.init(x: 0, y: 0, width: 0, height: 0))
dropdownView.translatesAutoresizingMaskIntoConstraints = false
self.setTitle("Sort by:", for: .normal)
}
override func didMoveToSuperview() {
self.superview?.addSubview(dropdownView)
self.superview?.bringSubviewToFront(dropdownView)
dropdownView.topAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
dropdownView.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
dropdownView.widthAnchor.constraint(equalTo: self.widthAnchor).isActive = true
dropdownViewHeight = dropdownView.heightAnchor.constraint(equalToConstant: 0)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if isOpen == false {
isOpen = true
NSLayoutConstraint.deactivate([self.dropdownViewHeight])
self.dropdownViewHeight.constant = 300
NSLayoutConstraint.activate([self.dropdownViewHeight])
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.5, options: .curveEaseIn, animations: {
self.dropdownView.layoutIfNeeded()
self.dropdownView.center.y += self.dropdownView.frame.height / 2
}, completion: nil)
} else {
isOpen = false
NSLayoutConstraint.deactivate([self.dropdownViewHeight])
self.dropdownViewHeight.constant = 0
NSLayoutConstraint.activate([self.dropdownViewHeight])
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.5, options: .curveEaseIn, animations: {
self.dropdownView.center.y -= self.dropdownView.frame.height / 2
self.dropdownView.layoutIfNeeded()
}, completion: nil)
}
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
(3) Created a custom Navigation Bar class and added to it the custom UIButton created above as a UIView to be displayed as a rightBarButtonItem:
import UIKit
import ChameleonFramework
class CustomUINavigationBar: UINavigationBar {
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
convenience init(isNavBarTranslucent: Bool, navBarBackgroundColourHexCode: String, navBarBackgroundColourAlphaValue: CGFloat, navBarStyle: UIBarStyle, preferLargeTitles: Bool, navBarDelegate: UINavigationBarDelegate, navBarItemsHexColourCode: String) {
self.init()
addNavBarRightButton()
setupNavigationBarEssentials(isNavBarTranslucent: isNavBarTranslucent, navBarBackgroundColourHexCode: navBarBackgroundColourHexCode, navBarBackgroundColourAlphaValue: navBarBackgroundColourAlphaValue, navBarStyle: navBarStyle, preferLargeTitles: preferLargeTitles, navBarDelegate: navBarDelegate, navBarItemsHexColourCode: navBarItemsHexColourCode)
}
let customNavigationBarItem = UINavigationItem()
func addNavBarRightButton() {
let button = DropdownUIButton()
let navigationBarRightButtonView: UIView = {
let view = UIView()
view.backgroundColor = .yellow
view.addSubview(button)
return view
}()
NSLayoutConstraint.activate([
button.topAnchor.constraint(equalTo: navigationBarRightButtonView.topAnchor),
button.rightAnchor.constraint(equalTo: navigationBarRightButtonView.rightAnchor),
button.leftAnchor.constraint(equalTo: navigationBarRightButtonView.leftAnchor),
button.bottomAnchor.constraint(equalTo: navigationBarRightButtonView.bottomAnchor)
])
let navigationBarRightViewitem = UIBarButtonItem(customView: navigationBarRightButtonView)
customNavigationBarItem.rightBarButtonItem = navigationBarRightViewitem
}
func setupNavigationBarEssentials(isNavBarTranslucent: Bool, navBarBackgroundColourHexCode: String, navBarBackgroundColourAlphaValue: CGFloat, navBarStyle: UIBarStyle, preferLargeTitles: Bool, navBarDelegate: UINavigationBarDelegate, navBarItemsHexColourCode: String) {
items = [customNavigationBarItem]
isTranslucent = isNavBarTranslucent
barTintColor = UIColor(hexString: navBarBackgroundColourHexCode, withAlpha: navBarBackgroundColourAlphaValue)
barStyle = navBarStyle
prefersLargeTitles = preferLargeTitles
delegate = navBarDelegate
tintColor = UIColor(hexString: navBarItemsHexColourCode)
translatesAutoresizingMaskIntoConstraints = false
}
}
(4) Added the above custom NavigationBar to the ViewController class I am interested in as below:
import UIKit
class tableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UINavigationBarDelegate {
lazy var navigationBar = CustomUINavigationBar(isNavBarTranslucent: false, navBarBackgroundColourHexCode: "#FFFFFF", navBarBackgroundColourAlphaValue: 1.0, navBarStyle: .black, preferLargeTitles: false, navBarDelegate: self, navBarItemsHexColourCode: "#FF4F40")
lazy var tableView = CustomTableView(tableViewBackgroundColourHexCode: "#0D0D0D", tableViewDelegate: self, tableViewDataSource: self, tableViewCustomCellClassToBeRegistered: IsectionsCustomTableViewCell.self, tableViewCustomCellReuseIdentifierToBeRegistered: "customCell")
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(navigationBar)
view.addSubview(tableView)
}
override func viewDidLayoutSubviews() {
setupConstraints()
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "customCell") as! IsectionsCustomTableViewCell
cell.sectionDesignationLabel.text = "Number 1"
return cell
}
func position(for bar: UIBarPositioning) -> UIBarPosition {
return UIBarPosition.topAttached
}
func setupConstraints() {
NSLayoutConstraint.activate([
navigationBar.leftAnchor.constraint(equalTo: view.leftAnchor),
navigationBar.rightAnchor.constraint(equalTo: view.rightAnchor),
navigationBar.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
tableView.topAnchor.constraint(equalTo: navigationBar.bottomAnchor),
tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
tableView.leftAnchor.constraint(equalTo: view.leftAnchor),
tableView.rightAnchor.constraint(equalTo: view.rightAnchor)
])
}
}
The button gets added to the NavigationBar on its right hand side as I can see the NavigationBar and the Button. However, however, when I click on the button, nothing happens, the tableview does not get dropped down and up as I expected. Any idea where did I go wrong, and are there any CocoaPods that you can recommend to achieve something similar?