0
votes

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?

1

1 Answers

0
votes

You can simply use this library to achieve drop d https://github.com/AssistoLab/DropDown