Name: ios-horizontalmenu
Owner: 3Pillar Global Open Source
Description: Create a menu dynamic number of items on iOS devices.
Created: 2017-03-29 20:38:34.0
Updated: 2017-04-06 10:01:40.0
Pushed: 2017-11-10 09:29:19.0
Size: 13979
Language: Swift
GitHub Committers
User | Most Recent Commit | # Commits |
---|
Other Committers
User | Most Recent Commit | # Commits |
---|
If you're using UIKit, you'll feel at home. It's a UI component similar to UIPageViewController that helps you to create a menu designed for iOS with a dynamic number of items.
Available in iOS 10.0 and later.
CocoaPods Installation
Run Terminal
Navigate to project folder
Use command:
init
form :ios, '10.0'
et 'YourProjectName' do
e_frameworks!
pod 'TPGHorizontalMenu'
install
Remember to open project using workspace
Carthage Installation
Run Terminal
Navigate to project folder
Use command in terminal:
h cartfile
Add code to Cartfile:
ub "3pillarlabs/ios-horizontalmenu"
hage update
A sample project is available on demo brach.
How to use the framework:
rt TPGHorizontalMenu
menuViewController = HorizontalMenuViewController()
ViewController.dataSource = self // to populate the menu
ViewController.layoutDelegate = self // to provide custom layout and alignment
ViewController.willMove(toParentViewController: self)
ViewController.view.frame = view.bounds
.addSubview(menuViewController.view)
hildViewController(menuViewController)
In order to populate the menu you have to conform to data source protocol HorizontalMenuViewControllerDataSource
:
nsion DataSourceImplemeter: HorizontalMenuViewControllerDataSource {
..
then:
horizontalMenuViewControllerNumberOfItems(horizontalMenuViewController: HorizontalMenuViewController) -> Int {
return array.count
horizontalMenuViewController(horizontalMenuViewController: HorizontalMenuViewController,
menuItemFor index: Int) -> MenuItem {
let title = array[index]
return MenuItem(attributedTitle: title) // use the constructor you need
horizontalMenuViewController(horizontalMenuViewController: HorizontalMenuViewController,
viewControllerFor index: Int) -> UIViewController {
let screen = UIViewController()
// customize the screen
return screen
and now you have the menu visible in your application.
If you need to customize any kind of layout, you may do so by implementing LayoutControllerDelegate
:
nsion DelegateType: LayoutControllerDelegate {
..
Insets may be change through MenuGeometry
.
layoutControllerMenuGeometry(layoutController: LayoutController) -> MenuGeometry {
return MenuGeometry(itemsInset: UIEdgeInsets(top: 8.0, left: 12.0, bottom: 8.0, right: 12.0))
Spacing between items may be change through MenuGeometry
.
layoutControllerMenuGeometry(layoutController: LayoutController) -> MenuGeometry {
return MenuGeometry(itemSpacing: 24.0)
The size of menu item can be change to be a fixed size or compute your size to be dependant on the data you want to display on menu item.
ixed size
layoutController(layoutController: LayoutController, geometryForItemAt index: Int) -> ItemGeometry {
return ItemGeometry(size: CGSize(width: 60.0, height: 80.0))
ynamic size
layoutController(layoutController: LayoutController, geometryForItemAt index: Int) -> ItemGeometry {
let view = menuViewController.items[index].view
let size = // compute size
return ItemGeometry(size: size)
f things are getting complicated
CustomItemGeometry.swift
s CustomItemGeometry: ItemGeometry {
init(view: UIView) {
let size = CustomItemGeometry.computeItemSize(for: view)
super.init(size: size)
}
private static func computeItemSize(for view: UIView) -> CGSize {
// additional work
return CGSize()
}
DelegateType.swift
layoutController(layoutController: LayoutController, geometryForItemAt index: Int) -> ItemGeometry {
let view = menuViewController.items[index].view
return CustomItemGeometry(view: view)
The height of scroll indicator view may be customized through ScrollIndicatorGeometry
. An instance of ScrollIndicatorGeometry
can provided as parameter to MenuGeometry
.
layoutControllerMenuGeometry(layoutController: LayoutController) -> MenuGeometry {
let scrollIndicatorGeometry = ScrollIndicatorGeometry(height: 10.0)
return MenuGeometry(scrollIndicatorGeometry: scrollIndicatorGeometry)
As we customize the height of scroll indicator view we can also change the alignment: bottom
or top
. The default is bottom
.
layoutControllerMenuGeometry(layoutController: LayoutController) -> MenuGeometry {
let scrollIndicatorGeometry = ScrollIndicatorGeometry(height: 12.0, verticalAlignment: .top)
return MenuGeometry(scrollIndicatorGeometry: scrollIndicatorGeometry)
The vertical alignment of a menu item can be changed through geometry object. Possible values are:
top
center
(default)bottom
Be aware that you might need to the set a preferred content height of menu.
layoutController(layoutController: LayoutController, geometryForItemAt index: Int) -> ItemGeometry {
return ItemGeometry(size: CGSize(width: 60.0, height: 80.0), verticalAlignment: .bottom)
Height of menu content may be set through MenuGeometry
.
layoutControllerMenuGeometry(layoutController: LayoutController) -> MenuGeometry {
return MenuGeometry(prefferedHeight: 60.0)
Highlighting and selection may be achieved by implementing Highlightable
and Selectable
by the view which is used on menu items.
UIKit classes already implement these protocols, such as UIControl. Others may only implement Highlightable
, such as UILabel.
s MenuItemView: UIView, Highlightable, Selectable {
ar isHighlighted: Bool {
didSet {
// update view for highlighted state
}
ar isSelected: Bool {
didSet {
// update view for selected state
}
MenuItem provides a default initializer which accepts an instance of UIView.
horizontalMenuViewController(horizontalMenuViewController: HorizontalMenuViewController,
menuItemFor index: Int) -> MenuItem {
let data = array[index]
let view = MenuItemView()
view.property = data.otherProperty
return MenuItem(view: view)
In order to customize the animations you need to implement HorizontalMenuViewControllerDelegate
.
horizontalMenuViewController(horizontalMenuViewController: HorizontalMenuViewController,
animationForSelectionOf index: Int) -> Animation {
return Animation(duration: 0.5) // customize animation as you need
As we customize selection animation, we can do it for appearance as well when the current item is not visible and user swipes outside the boundaries (before first item and after the last item) of menu.
horizontalMenuViewControllerAnimationForEdgeAppearance(horizontalMenuViewController: HorizontalMenuViewController) -> Animation {
return Animation(duration: 0.5) // customize animation as you need
The view controller which is provided through HorizontalMenuViewControllerDataSource
may implement HorizontalMenuChild
. The functions from this protocol will be called when user swipes left or right in order to change the current item.
s MenuScreenViewController: UIViewController, HorizontalMenuChild {
unc appearanceProgress(progress: CGFloat) {
// implement logic when view controller appears progressively
unc disappearanceProgress(progress: CGFloat) {
// implement logic when view controller disappears progressively
HorizontalMenuViewControllerDelegate
provides a callback with all information needed for progressive update. To simplify the computation with progress, the framework provide a data type (Segment
) which can compute an intermediate value between 2 values and a given progress.
horizontalMenuViewController(horizontalMenuViewController: HorizontalMenuViewController,
scrollTransition: ScrollTransition) {
uard views.isValid(index: scrollTransition.toIndex),
views.isValid(index: scrollTransition.fromIndex) else { return }
let firstPoint = views[scrollTransition.fromIndex].frame.origin
let secondPoint = views[scrollTransition.toIndex].frame.origin
let segment = Segment<CGPoint>(first: firstPoint, second: secondPoint)
viewProperty.frame.origin = segment.pointProgress(with: scrollTransition.progress)
When user selects an menu item, only 2 callbacks are provided:
If really you need callbacks, you may use CADisplayLink to provide callbacks for you.
An important thing to know is that default animations have a duration of 0.3 seconds.
Also if you feel the need for a small demo please check the demo project branch, add the framework and you are good to go.
Did you find a bug in the framework? Create an issue.
Want to help us implement new features or fix bugs? Create a pull request.
Horizontal Menu is released under MIT license. See LICENSE for details.
Horizontal Menu is developed and maintained by 3Pillar Global.