#
SwiftyMenu is simple yet powerfull drop down menu component for iOS. It allow you to have drop down menu that doesn't appear over your views, which give you awesome user experience.
CocoaPods is a dependency manager for Cocoa projects. For usage and installation instructions, visit their website. To integrate SwiftyMenu into your Xcode project using CocoaPods, specify it in your Podfile
:
pod 'SwiftyMenu', '~> 1.1.0'
Automatically in Xcode:
https://github.com/KarimEbrahemAbdelaziz/SwiftyMenu
to add TimelaneCombine to your project.Manually in your Package.swift file add:
.package(url: "https://github.com/KarimEbrahemAbdelaziz/SwiftyMenu", from: "1.1.0")
SwiftyMenu
supports initialization from Storyboard
and Code
.
Setup your view controller:
// Connect view in storyboard with you outlet
@IBOutlet private weak var dropDownMenu: SwiftyMenu!
Then connect IBOutlet
to Storyboard
, and connect the Height
Constraints of the menu as shown below.
SwiftyMenu
/// Init SwiftyMenu from Code
let dropDownCode = SwiftyMenu(frame: CGRect(x: 0, y: 0, width: 0, height: 40))
SwiftyMenu
as Subview
/// Add it as subview
view.addSubview(dropDownCode)
/// Add constraints to SwiftyMenu
/// You must take care of `hegiht` constraint, please.
dropDownCode.translatesAutoresizingMaskIntoConstraints = false
let horizontalConstraint = NSLayoutConstraint(item: dropDownCode, attribute: NSLayoutConstraint.Attribute.centerX, relatedBy: NSLayoutConstraint.Relation.equal, toItem: view, attribute: NSLayoutConstraint.Attribute.centerX, multiplier: 1, constant: 0)
let topConstraint = NSLayoutConstraint(item: dropDownCode, attribute: NSLayoutConstraint.Attribute.top, relatedBy: NSLayoutConstraint.Relation.equal, toItem: otherView, attribute: NSLayoutConstraint.Attribute.top, multiplier: 1, constant: 64)
let widthConstraint = NSLayoutConstraint(item: dropDownCode, attribute: NSLayoutConstraint.Attribute.width, relatedBy: NSLayoutConstraint.Relation.equal, toItem: nil, attribute: NSLayoutConstraint.Attribute.notAnAttribute, multiplier: 1, constant: 255)
dropDownCode.heightConstraint = NSLayoutConstraint(item: dropDownCode, attribute: NSLayoutConstraint.Attribute.height, relatedBy: NSLayoutConstraint.Relation.equal, toItem: nil, attribute: NSLayoutConstraint.Attribute.notAnAttribute, multiplier: 1, constant: 40)
NSLayoutConstraint.activate(
[
horizontalConstraint,
topConstraint,
widthConstraint,
dropDownCode.heightConstraint
]
)
To configure SwiftyMenu
DataSource, you'll need to prepare your Model
to be able to presented and retrived from the menu. Then, create and assign the DataSource to SwiftyMenu
.
We are supporting Generic Data Source, all you have to do is conforming to our Generic Protocol on which type you want to add to the menu.
String
extension String: SwiftyMenuDisplayable {
public var displayableValue: String {
return self
}
public var retrivableValue: Any {
return self
}
}
Struct
struct MealSize {
let id: Int
let name: String
}
extension MealSize: SwiftyMenuDisplayable {
public var displayableValue: String {
return self.name
}
public var retrievableValue: Any {
return self.id
}
}
Array
of your models/// Define menu data source
/// The data source type must conform to `SwiftyMenuDisplayable`
private let dropDownOptionsDataSource = [
MealSize(id: 1, name: "Small"),
MealSize(id: 2, name: "Medium"),
MealSize(id: 3, name: "Large"),
MealSize(id: 4, name: "Combo Large")
]
SwiftyMenu
DataSource propertydropDownCode.items = dropDownOptionsDataSource
SwiftyMenu
supports 2 ways to capture the selected items, Delegate
and Closure
s. You can use one or both of them at the same time.
SwiftyMenu
Delegate protocolextension ViewController: SwiftyMenuDelegate {
// Get selected option from SwiftyMenu
func swiftyMenu(_ swiftyMenu: SwiftyMenu, didSelectItem item: SwiftyMenuDisplayable, atIndex index: Int) {
print("Selected item: \(item), at index: \(index)")
}
// NEW - Get selected option from SwiftyMenu
func swiftyMenu(_ swiftyMenu: SwiftyMenu, didDeselectItem item: SwiftyMenuDisplayable, atIndex index: Int){
print("deselected item: \(item), at index: \(index)")
}
// SwiftyMenu drop down menu will expand
func swiftyMenu(willExpand swiftyMenu: SwiftyMenu) {
print("SwiftyMenu willExpand.")
}
// SwiftyMenu drop down menu did expand
func swiftyMenu(didExpand swiftyMenu: SwiftyMenu) {
print("SwiftyMenu didExpand.")
}
// SwiftyMenu drop down menu will collapse
func swiftyMenu(willCollapse swiftyMenu: SwiftyMenu) {
print("SwiftyMenu willCollapse.")
}
// SwiftyMenu drop down menu did collapse
func swiftyMenu(didCollapse swiftyMenu: SwiftyMenu) {
print("SwiftyMenu didCollapse.")
}
}
SwiftyMenu
delegatedropDownCode.delegate = self
You can use callbacks to know what happen:
/// SwiftyMenu also supports `CallBacks`
dropDownCode.didSelectItem = { menu, item, index in
print("Selected \(item) at index: \(index)")
}
dropDownCode.willExpand = {
print("SwiftyMenu Will Expand!")
}
dropDownCode.didExpand = {
print("SwiftyMenu Expanded!")
}
dropDownCode.willCollapse = {
print("SwiftyMenu Will Collapse!")
}
dropDownCode.didCollapse = {
print("SwiftyMenu Collapsed!")
}
Having an amazing drop down menu is essential. So, there're a lot of UI customization for SwiftyMenu
(More to be added soon).
To configure UI customization for SwiftyMenu
:
SwiftyMenuAttributes
propertyprivate var codeMenuAttributes = SwiftyMenuAttributes()
SwiftyMenu
/// Configure SwiftyMenu with the attributes
dropDownCode.configure(with: codeMenuAttributes)
Also before assigning it to SwiftyMenu
you could customize the menu look using following attributes.
attributes.placeHolderStyle = .value(text: "Please Select Size", textColor: .lightGray)
attributes.textStyle = .value(color: .gray, separator: " & ", font: .systemFont(ofSize: 12))
attributes.scroll = .disabled
//NEW - Single selection disallowing deselection clicking the same item
attributes.multiSelect = .disabled(allowSingleDeselection: false)
//NEW - Single selection allowing deselection clicking the same item
attributes.multiSelect = .disabled(allowSingleDeselection: true)
//Multi selection enable
attributes.multiSelect = .enabled
attributes.hideOptionsWhenSelect = .enabled
attributes.rowStyle = .value(height: 40, backgroundColor: .white, selectedColor: .white)
/// Rounded Corners
attributes.roundCorners = .all(radius: 8)
/// Menu Maximum Height
attributes.height = .value(height: 300)
/// Menu Border
attributes.border = .value(color: .gray, width: 0.5)
/// `SwiftyMenu` have default arrow
attributes.arrowStyle = .value(isEnabled: true)
/// NEW - Now able to add a custom image, tint color and space between icon and text
attributes.arrowStyle = .value(isEnabled: true, image: image, tintColor: .purple, spacingBetweenText: 10.0)
attributes.separatorStyle = .value(color: .black, isBlured: false, style: .singleLine)
attributes.headerStyle = .value(backgroundColor: .white, height: 40)
attributes.accessory = .disabled
attributes.expandingAnimation = .linear
attributes.expandingTiming = .value(duration: 0.5, delay: 0)
attributes.collapsingAnimation = .linear
attributes.collapsingTiming = .value(duration: 0.5, delay: 0)
/// Margin leading and trailing for title / placeholder
attributes.titleMarginHorizontal = .value(leading: 10, trailing: 20)
/// Margin leading and trailing for item list
attributes.itemMarginHorizontal = .value(leading: 10, trailing: 10)
/// Default use the .red color
attributes.errorInfo = .default
/// Custom color for placeholder and icon if it's enabled
attributes.errorInfo = .custom(placeholderTextColor: .red, iconTintColor: .red)
/// Enabling this will show the config in errorInfo
dropDown.setError(hasError: true)
You could check the full Example
project Here.
You could check the full new Example
project Here New Example.
And much more ideas to make it solid drop down menu for iOS projects 😎💪🏻
Karim Ebrahem, karimabdelazizmansour@gmail.com
SwiftyMenu is available under the MIT license. See the LICENSE
file for more info.
You can find me on Twitter @kebrahem.
It will be updated when necessary and fixes will be done as soon as discovered to keep it up to date.
Enjoy!