Animated top menu for UITableView / UICollectionView / UIScrollView written in Swift

Overview

Persei

Build Status License

Preview

Animated top menu for UITableView / UICollectionView / UIScrollView written in Swift!

Made in Yalantis.

Check this project on Dribbble

Check this project on Behance

Supported Swift versions

Swift Version Persei
1.x 1.1
2.x 2.0
3.x 3.0
4.x 3.1
5.x 4.0

Installation

CocoaPods

use_frameworks!

pod 'Persei', '~> 4.0'

Carthage

github "Yalantis/Persei" ~> 4.0

Manual Installation

For application targets that do not support embedded frameworks, such as iOS 7, Persei can be integrated by including source files from the Persei folder directly, optionally wrapping the top-level types into struct Persei to simulate a namespace. Yes, this sucks.

  1. Add Persei as a submodule by opening the Terminal, cd-ing into your top-level project directory, and entering the command git submodule add https://github.com/yalantis/Persei.git
  2. Open the Persei folder, and drag Persei.xcodeproj into the file navigator of your app project.
  3. In Xcode, navigate to the target configuration window by clicking on the blue project icon, and selecting the application target under the "Targets" heading in the sidebar.
  4. Ensure that the deployment target of Persei.framework matches that of the application target.
  5. In the tab bar at the top of that window, open the "Build Phases" panel.
  6. Expand the "Target Dependencies" group, and add Persei.framework.
  7. Expand the "Link Binary With Libraries" group, and add SideMenu.framework
  8. Click on the + button at the top left of the panel and select "New Copy Files Phase". Rename this new phase to "Copy Frameworks", set the "Destination" to "Frameworks", and add Persei.framework.

Usage

Import Persei module

import Persei

Init

let menu = MenuView()    
tableView.addSubview(menu)

Configuring items

In order to set items you need to instantiate array of MenuItem:

let items = feedModes.map { mode: SomeYourCustomFeedMode -> MenuItem in
	return MenuItem(image: mode.image)
}

menu.items = items

Handling selection

You can specify selected item manually:

menu.selectedIndex = 3

Note, that selectedIndex declared as Int? and will be nil in case of menu.items = nil.

Also, you can implement MenuViewDelegate to be notified about selection change:

// during init
menu.delegate = self

// actual implementation
extension FeedViewController: MenuViewDelegate {
    func menu(menu: MenuView, didSelectItemAt index: Int) {
    	dataSource.mode = feedModes[index] // alter mode of dataSource

    	tableView.reload() // update tableView
    }
}

Reveal menu manually

Menu can be reveal as a result of button tap:

func menuButtonSelected(sender: UIControl) {
	menu.revealed = !menu.revealed

	// or animated
	menu.setRevealed(true, animated: true)
}

Content Gravity

Use contentViewGravity to control sticking behavior. There are 3 available options:

  • Top: contentView sticked to the top position of the view
  • Center: contentView is aligned to the middle of the streched view
  • Bottom: contentView sticked to the bottom

Customization

MenuItem declares set of attributes, that allow you to customize appearance of items:

struct MenuItem {
    var image: UIImage // default image
    var highlightedImage: UIImage? // image used during selection

    var backgroundColor: UIColor // default background color
    var highlightedBackgroundColor: UIColor // background color used during selection

    var shadowColor: UIColor // color of bottom 2px shadow line
}

Also you're free to configure background of MenuView by utilizing backgroundColor or backgroundImage. Note, that image should be resizeable:

let menu = MenuView()
menu.backgroundImage = UIImage(named: "top_menu_background")

Advanced customization

  • Can I place the UIImageView instead?
  • Sure! Just subclass / use StickyHeaderView directly. It offers layout, positioning and reveal control. All you have to do is to assign your custom view (animated nian-cat UIImageView) to contentView:
let headerView = StickyHeaderView()
let imageView = UIImageView(...)

headerView.contentView = imageView

Obviously, your custom view can have heigh different from default:

headerView.contentHeight = image.size.height

As well as control distance to trigger open/close of the header:

headerView.threshold = 0.5

Threshold is a float value from 0 to 1, specifies how much user needs to drag header for reveal.

Let us know!

We’d be really happy if you sent us links to your projects where you use our component. Just send an email to [email protected] And do let us know if you have any questions or suggestion regarding the animation.

P.S. We’re going to publish more awesomeness wrapped in code and a tutorial on how to make UI for iOS (Android) better than better. Stay tuned!

License

The MIT License (MIT)

Copyright © 2017 Yalantis

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Comments
  • No interaction on item click using iOS 7 iPhone 5 simulator

    No interaction on item click using iOS 7 iPhone 5 simulator

    Hello,

    First of all, thanks you for this project.

    I'm using Persei on my app and it works fine on iOS 8. However, the "didSelectRow" doesn't seems to work on iOS 7. It reveal normally the menu but there is no action when clicking on items.

    Do you have an idea about this problem ?

    Edited: The items thumbnails are also reduced.

    opened by Aymenworks 6
  • Crashes on Device.

    Crashes on Device.

    This is crashing in device but running fine in simulator , i also checked in your Example project but its also crashing in Example app when using with device, I am using 10.0.2 (iPhone 6s) Xcode 8.0 .

    Error: - fatal error: unexpectedly found nil while unwrapping an Optional value (Menu View is nil always)

    opened by ErAbhishekChandani 4
  • NSInternalInconsistencyException - UITableView was deallocated while key value observers were still registered with it.

    NSInternalInconsistencyException - UITableView was deallocated while key value observers were still registered with it.

    I have a TableViewController that uses Persei. I push the TableViewController when I select a button on my starting view. When I hit the back button in the navigation bar I get the following error:

    Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'An instance of class UITableView was deallocated while key value observers were still registered with it. Current observation info: <NSKeyValueObservationInfo 0x7fd003571060> ( <NSKeyValueObservance 0x7fd003576350: Observer: 0x7fd00370e800, Key path: contentOffset, Options: <New: YES, Old: NO, Prior: NO> Context: 0x103111190, Property: 0x7fd00378e3a0>

    It looks like in StickyHeaderView is setting the observer here:

    public weak var scrollView: UIScrollView! {
        willSet {
            self.scrollView?.removeObserver(self, forKeyPath: "contentOffset", context: &ContentOffsetContext)
            self.scrollView?.panGestureRecognizer.removeTarget(self, action: "handlePan:")
    
            appliedInsets = UIEdgeInsetsZero
        }
    
        didSet {
            scrollView?.addObserver(self, forKeyPath: "contentOffset", options: .Initial | .New, context: &ContentOffsetContext)
            scrollView?.panGestureRecognizer.addTarget(self, action: "handlePan:")
        }
    }
    

    How can I fix this issue? Thanks!

    opened by rankinit 4
  • Unable to update to 3.0 with cocoapods

    Unable to update to 3.0 with cocoapods

    Hi!

    I'm trying to update the Persei pod with cocoapods to use swift 3.0, in my Podfile I've added this line, like the readme file describes:

    use_frameworks! 
    
    pod 'Persei', '~> 3.0'
    

    but I've this error

    [!] Unable to satisfy the following requirements:
    
    - `Persei (~> 3.0)` required by `Podfile`
    - `Persei (~> 3.0)` required by `Podfile`
    
    None of your spec sources contain a spec satisfying the dependency: `Persei (~> 3.0)`.
    
    You have either:
     * out-of-date source repos which you can update with `pod repo update`.
     * mistyped the name or version.
     * not added the source repo that hosts the Podspec to your Podfile.
    

    What can I do?

    Thanks! \m

    opened by mrigo 3
  • setRevealed throwing as nil optional

    setRevealed throwing as nil optional

    When I attempt to set the revealed state, the initialized MenuView returns as a nil optional.

    My code

    // TableViewController properties
    var picker: MenuView {
        let m = MenuView()
        // Init other options and add items
        return m
    }
    // -----------------------
    override func viewWillAppear(animated: Bool) {
        picker.setRevealed(true, animated: true)
    }
    

    I have also tried setting m.revealed when initializing the property. I get the same error every time

    Also good to note that this TVC is sometimes a child VC and sometimes not

    priority: medium status: queued type: enhancement 
    opened by MatrixSenpai 3
  • How to replace UIImage by UIView

    How to replace UIImage by UIView

    Hi, I've just git this project and I was wondering how do I change/replace the UIImage by something like an UIView ?

    I Hope you will answer me soon, Regards.

    opened by Twelve57 3
  • Keeping menu collectionview top to of tableview at all times

    Keeping menu collectionview top to of tableview at all times

    I noticed that if you pull the collectionview down further it will move down. Is there a way to lock the menu collectionview so it stays on the top regardless?

    opened by johnamcruz 3
  • Sticky header View observer crash

    Sticky header View observer crash

    Hello, i am currently developing a project which uses this awesome library. Actually, i am developing with swift 3, using the xcode betas, and i was able to make it working without any trouble. My project is very close to be completed, but after i ve updated to xcode beta 6, ( and made some changes to library in order to make happy the compiler), my app is crashing every time i try to present the persei table. Through an exception breakpoint, the problem seems to be caused by

    public override func didMoveToSuperview() {
            super.didMoveToSuperview()
    
            if let view = superview as? UIScrollView {
    //AddObserver makes the app crash
                view.addObserver(self, forKeyPath: "contentOffset", options: [.initial, .new], context: &ContentOffsetContext)
                view.panGestureRecognizer.addTarget(self, action: #selector(StickyHeaderView.handlePan(_:)))
                view.sendSubview(toBack: self)
            }
        }
    

    Do you have any suggestion in order to make it work again as expected? The persei controller was totally integrated in my app, if i can t find a solution i will have to switch library for a new one and i wanna be sure it will be the last option. Thanks for your attention, hope all is gonna be solved

    opened by siideffect 2
  • Objective-c version

    Objective-c version

    Your component looks pretty good. And i'd like to include it in one of my application going soon in production. But i, for the moment, don't want to use swift so does a objective-c version exists ?

    opened by loicgriffie 2
  • ios 7 support

    ios 7 support

    Dear friend,

    Thank you for your masterpiece of work. I've tried to use your nice library in my project which is support ios 7, but I got this error when updating pod:

    [!] The platform of the target TabDemo (iOS 7.0) is not compatible with Persei (1.0) which has a minimum requirement of iOS 8.0.

    Below is my podfile's content:

    platform :ios, '7.0'

    target 'TabDemo' do use_frameworks! pod 'Persei' end

    target 'TabDemoTests' do

    end

    Do your library still support ios 7?

    Thank you so much

    opened by hpchemgio 2
  • use Persei in objc project

    use Persei in objc project

    I want to use Persei in my objc project, but can't define MenuItem because it's Struct. So I simply changed MenuItem to class and subclass of NSObject. Maybe the requirement is a little weired and the solution has potential risk. What's your suggestion? @Yalantis Whatever, thanks for sharing Persei!

    opened by NilStack 2
  • equal spacing

    equal spacing

    Report

    If I have less than 4 icons they all get aligned to the left How can I align them with equal spacing?

    ⚠️ Select what you want - a feature request or report a bug. Please remove the section you aren't interested in.

    A feature request

    What do you want to add?

    Please describe what you want to add to the component.

    How should it look like?

    Please add images.

    Report a bug

    What did you do?

    Please replace this with what you did.

    What did you expect to happen?

    Please replace this with what you expected to happen.

    What happened instead?

    Please replace this with what happened instead.

    Your Environment

    • Version of the component: insert here
    • Swift version: insert here
    • iOS version: insert here
    • Device: insert here
    • Xcode version: insert here
    • If you use Cocoapods: run pod env | pbcopy and insert here
    • If you use Carthage: run carthage version | pbcopy and insert here

    Project that demonstrates the bug

    Please add a link to a project we can download that reproduces the bug.

    opened by galblank 0
  • Scroll from Bot to Top

    Scroll from Bot to Top

    A feature request

    Hi Guys ! I would like to know if it's possible to inverse menu fade-in ? For example if I scroll from bot to top, the menu appear on the bot of my tableview.

    status: pending type: enhancement 
    opened by Ze-ro-G 1
Releases(3.1.1)
Owner
Yalantis
Knowledge is power and the way to get power is by sharing knowledge. We are open source because this is a smart way to live, work and play.
Yalantis
An iOS App dev menu always on top window

An iOS App dev menu always on top window

Frank Lu 1 Nov 12, 2021
A Slide Menu, written in Swift, inspired by Slide Menu Material Design

Swift-Slide-Menu (Material Design Inspired) A Slide Menu, written in Swift 2, inspired by Navigation Drawer on Material Design (inspired by Google Mat

Boisney Philippe 90 Oct 17, 2020
Animated side menu with customizable UI

Side Menu Animated side menu with customizable UI. Made in Yalantis. Check this project on dribbble. Check this project on Behance. Requirements iOS 7

Yalantis 2.7k Dec 27, 2022
You can easily add awesome animated context menu to your app.

Context-Menu.iOS You can easily add awesome animated context menu to your app. Made in Check this [project on dribbble] (https://dribbble.com/shots/17

Yalantis 1.8k Nov 17, 2022
Swift-sidebar-menu-example - Create amazing sidebar menu with animation using swift

 SWIFT SIDEBAR MENU EXAMPLE In this project I create a awesome side bar menu fo

Paolo Prodossimo Lopes 4 Jul 25, 2022
Slide-Menu - A Simple Slide Menu With Swift

Slide Menu!! Весь интерфейс создан через код

Kirill 0 Jan 8, 2022
SwiftySideMenu is a lightweight and easy to use side menu controller to add left menu and center view controllers with scale animation based on Pop framework.

SwiftySideMenu SwiftySideMenu is a lightweight, fully customizable, and easy to use controller to add left menu and center view controllers with scale

Hossam Ghareeb 84 Feb 4, 2022
EasyMenu - SwiftUI Menu but not only button (similar to the native Menu)

EasyMenu SwiftUI Menu but not only button (similar to the native Menu) You can c

null 10 Oct 7, 2022
Hamburger Menu Button - A hamburger menu button with full customization

Hamburger Menu Button A hamburger menu button with full customization. Inspired by VinhLe's idea on the Dribble How to use it You can config the looks

Toan Nguyen 114 Jun 12, 2022
A simple side menu for iOS written in Swift.

ENSwiftSideMenu A lightweight flyover side menu component for iOS with the UIDynamic's bouncing animation, UIGestures and UIBlurEffect. Allows you to

Evgeny Nazarov 1.8k Dec 21, 2022
iOS Interactive Side Menu written in Swift.

Interactive Side Menu A customizable, interactive, auto expanding and collapsing side menu for iOS written in Swift. Here are some of the ways Interac

Handsome 706 Dec 15, 2022
iOS Slide Menu View based on Google+, iQON, Feedly, Ameba iOS app. It is written in pure swift.

SlideMenuControllerSwift iOS Slide View based on iQON, Feedly, Google+, Ameba iPhone app. Installation CocoaPods pod 'SlideMenuControllerSwift' Carth

Yuji Hato 3.3k Dec 29, 2022
The elegant yet functional dropdown menu, written in Swift, appears underneath the navigation bar to display a list of defined items when a user clicks on the navigation title.

Introduction The elegant yet functional dropdown menu, written in Swift, appears underneath the navigation bar to display a list of defined items when

Tho Pham 2.7k Dec 28, 2022
ExpandingMenu is menu button for iOS written in Swift.

ExpandingMenu ExpandingMenu is written in Swift. Requirements iOS 8.0+ Xcode 10.0+ Swift 3.x+ Installation CocoaPods You can install CocoaPods with th

null 454 Dec 7, 2022
A side menu controller written in Swift for iOS

Description SideMenuController is a custom container view controller written in Swift which will display the main content within a center panel and th

Teo 1.2k Dec 29, 2022
UIKit drop down menu, simple yet flexible and written in Swift

DropDownMenuKit DropDownMenuKit is a custom UIKit control to show a menu attached to the navigation bar or toolbar. The menu appears with a sliding an

Quentin Mathé 258 Dec 27, 2022
Menu controller with expandable item groups, custom position and appearance animation written with Swift. Similar to ActionSheet style of UIAlertController.

Easy to implement controller with expanding menu items. Design is very similar to iOS native ActionSheet presentation style of a UIAlertController. As

Anatoliy Voropay 22 Dec 27, 2022
Rotating circle menu written in Swift 3

Swift-CircleMenu A rotating circle menu written in Swift 3. Features Gesture based rotation Configurable rotatability High customisability Simple intu

Shoaib Ahmed 123 Jul 29, 2022
Beautiful iOS side menu library with parallax effect. Written in Swift

AKSideMenu AKSideMenu is a double side menu library with parallax effect. Example Project See the contained examples to get a sample of how AKSideMenu

Diogo Autilio 280 Dec 6, 2022