A simple customizable side bar menu with swift
ModularSidebarView
ModularSidebarView is a customizable menu for displaying options on the side of the screen for iOS. It is meant to act as a substitute to the usual UINavigation bar items and tool bar items.
Usage
Displaying the SidebarView
First, initialize the SideBarView
private lazy var sidebarView: SidebarView = {
let sbv = SidebarView(delegate: self)
// Make desired configurations
return sbv
}()
Then create some sort of UIButton, UIBarButtonItem or any view with userInteraction enabled. Create the selector and function however you choose.
// It is NOT required to a use a UIBarButtonItem to display the SidebarView.
// Provide your own implementation for triggering the SidebarView to show.
private lazy var sidebarButton: UIBarButtonItem = {
let btn = UIBarButtonItem(title: "Sidebar",
style: .done,
target: self,
action: #selector(openSidebarView(_:)))
return btn
}()
// Here, we call the "showSidebarView()" function to display the SidebarView
@objc private func openSidebarView(_ sender: Any) {
sidebarView.show()
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
// ... Other UI setup
// Place the sidebarButton in the navigationBar if desired.
self.navigationItem.leftBarButtonItem = sidebarButton
}
Dismissing the SidebarView
private func dismissSidebarView() {
sidebarView.dismiss()
}
Simply tap the background view
Or pressing one of the options in the SidebarView will also dismiss on selection if dismissesOnSelection set to TRUE
Adding items to the SidebarView
The SidebarView uses a View-Model approach to laying out items.
You may subclass the default provided classes or conform to the underlying protocol for more customization
Step 1: Creating View-Models
Subclassing the SidebarViewCellModel
, SidebarViewReusableViewSectionModel
and SidebarViewReusableViewModel
// SidebarViewCellModel is the View-Model that represents a SidebarView cell
// CustomSidebarCellModel is a custom subclass. You may provide your own subclass
class CustomSidebarCellModel: SidebarViewCellModel {
var image: UIImage?
var title: String
init(image: UIImage?, title: String) {
self.image = image
self.title = title
// This is very imporant. Provide the cell class you wish for this model to display
// This must be a UICollectionViewCell
super.init(cellClass: CustomSidebarCell.self)
}
}
// At heart, SidebarView is a UICollectionView.
// As such, may render both a header and footer supplementaryView for each section.
// The SidebarViewReusableViewSectionModel provides a container for both the header and footer in each section.
SidebarViewReusableViewSectionModel(headerViewModel: SidebarViewReusableViewModelProtocol?, footerViewModel: SidebarViewReusableViewModelProtocol?)
// You create your own header and footer supplementary view-models that conform to SidebarViewReusableViewModelProtocol or subclass the default SidebarViewReusableViewModel:
class CustomHeaderModel: SidebarViewReusableViewModel {
init() {
super.init(reusableViewClass: CustomSidebarSectionHeader.self, elementType: .header)
}
}
class CustomFooterModel: SidebarViewReusableViewModel {
init() {
super.init(reusableViewClass: CustomSidebarSectionHeader.self, elementType: .footer)
}
}
Step 2: Creating Views (Cells and ReusableViews)
Subclassing the SidebarViewCell
and SidebarReusableView
class CustomSidebarCell: SidebarViewCell {
// Important to override this function to configure the cells as desired
override func configure(with item: SidebarViewCellModelProtocol, at indexPath: IndexPath) {
super.configure(with: item, at: indexPath)
guard let customViewModel = item as? CustomSidebarCellModel else {
return
}
// configure the cell with your custom View-Model data
self.imageView.image = customViewModel.image
self.titleLabel.text = customViewModel.title
}
}
class CustomSidebarSectionHeader: SidebarReusableView {
// Important to override this function to configure the view as desired
override func configure(with item: SidebarViewReusableViewModelProtocol, at indexPath: IndexPath) {
super.configure(with: item, at: indexPath)
guard let customViewModel = item as? CustomHeaderModel else {
return
}
// configure the cell with your custom header View-Model data
}
}
Step 3: Inserting the View-Models into the SidebarView
Use these two functions to insert Cell and ReusableView View-Models at desired indexPaths
func insertSidebarView(models: [SidebarViewCellModelProtocol], atIndexPaths indexPaths: [IndexPath])
func insertReusableView(reusableSectionModels: [SidebarViewReusableViewSectionProtocol], atIndices indices: [Int])
Example
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
setupSidebarViewItems()
}
private func setupSidebarViewItems() {
// Create Cell View-Models
let sectionOneIndexPaths: [IndexPath = // ... Construct array of IndexPaths for section 0
let sectionOneItems: [SidebarViewCellModelProtocol] = // ... Construct array of View-Models for section 0
let sectionTwoIndexPaths: [IndexPath = // ... Construct array of IndexPaths for section 1
let sectionTwoItems: [SidebarViewCellModelProtocol] = // ... Construct array of View-Models for section 1
let completeListOfItems: [SidebarViewCellModelProtocol] = (sectionOneItems + sectionTwoItems)
let completeListOfIndexPaths = (sectionOneIndexPaths + sectionTwoIndexPaths)
sidebarView.insertSidebarView(models: completeListOfItems, atIndexPaths: completeListOfIndexPaths)
// Create ReusableView View-Models
let reusableSectionItems: [SidebarViewReusableViewSectionModel] = // ... Construct array of ReusableView Section View-Models
let sectionIndices: [Int] = // ... Construct of section indices (positive integers)
sidebarView.insertReusableView(reusableSectionModels: reusableSectionItems, atIndices: sectionIndices)
}
Extending the SidebarViewDelegate
You may extend the class:
class ViewController: SidebarViewDelegate {
func sidebarView(_ sidebarView: SidebarView, didSelectItemAt indexPath: IndexPath) {
// Provide custom action/functionality when tapping a SidebarView cell at each indexPath
}
func sidebarView(_ sidebarView: SidebarView, heightForHeaderIn section: Int) -> CGFloat {
// Provide height for supplementary header reusableView at each section
}
func sidebarView(_ sidebarView: SidebarView, heightForFooterIn section: Int) -> CGFloat {
// Provide height for supplementary footer reusableView at each section
}
func sidebarView(_ view: SidebarView, heightForItemAt indexPath: IndexPath) -> CGFloat {
// Provide heights for items at each IndexPath
}
}
Example
To run the example project, clone the repo, and run pod install
from the Example directory first.
Requirements
Installation
ModularSidebarView is available through CocoaPods. To install
it, simply add the following line to your Podfile:
pod 'ModularSidebarView'
Author
ChrishonWyllie, chrishon595@yahoo.com