Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1e6f192e28 | |||
| 771047f506 | |||
| c8ede5cd76 | |||
| 335130ff7a | |||
| 18fdc7f00e | |||
| e70f37f7b4 | |||
| 21e873cc68 | |||
| d81eb6277d | |||
| 2f6a1b8e6c | |||
| 7d766813fd | |||
| 78fad19e6f | |||
| e91b9be969 | |||
| 02252bc035 | |||
| 4a658269a6 | |||
| b5342a1c7c |
@@ -24,9 +24,12 @@ public class SideMenuManager {
|
||||
case ViewSlideInOut
|
||||
case MenuDissolveIn
|
||||
}
|
||||
|
||||
private static var originalLeftMenuBackgroundColor: UIColor?
|
||||
private static var originalRightMenuBackgroundColor: UIColor?
|
||||
|
||||
// Bounds which has been allocated for the app on the whole device screen
|
||||
internal static var appScreenRect: CGRect {
|
||||
let appWindowRect = UIApplication.sharedApplication().keyWindow?.bounds ?? UIWindow().bounds
|
||||
return appWindowRect
|
||||
}
|
||||
|
||||
/**
|
||||
The presentation mode of the menu.
|
||||
@@ -46,7 +49,7 @@ public class SideMenuManager {
|
||||
public static var menuAllowPopIfPossible = false
|
||||
|
||||
/// Width of the menu when presented on screen, showing the existing view controller in the remaining space. Default is 75% of the screen width.
|
||||
public static var menuWidth: CGFloat = max(round(min(UIScreen.mainScreen().bounds.width, UIScreen.mainScreen().bounds.height) * 0.75), 240)
|
||||
public static var menuWidth: CGFloat = max(round(min((appScreenRect.width), (appScreenRect.height)) * 0.75), 240)
|
||||
|
||||
/// Duration of the animation when the menu is presented without gestures. Default is 0.35 seconds.
|
||||
public static var menuAnimationPresentDuration = 0.35
|
||||
@@ -105,119 +108,120 @@ public class SideMenuManager {
|
||||
*/
|
||||
public static var menuBlurEffectStyle: UIBlurEffectStyle? {
|
||||
didSet {
|
||||
updateMenuBlurIfNecessary()
|
||||
if oldValue != menuBlurEffectStyle {
|
||||
updateMenuBlurIfNecessary()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The left menu.
|
||||
public static var menuLeftNavigationController: UISideMenuNavigationController? {
|
||||
willSet {
|
||||
if menuLeftNavigationController != nil {
|
||||
let originalBlurEffectStyle = menuBlurEffectStyle
|
||||
menuBlurEffectStyle = nil
|
||||
updateMenuBlurIfNecessary()
|
||||
menuBlurEffectStyle = originalBlurEffectStyle
|
||||
if menuLeftNavigationController?.presentingViewController == nil {
|
||||
removeMenuBlurForMenu(menuLeftNavigationController)
|
||||
}
|
||||
}
|
||||
didSet {
|
||||
if let menuLeftNavigationController = menuLeftNavigationController {
|
||||
let exitPanGesture = UIPanGestureRecognizer()
|
||||
exitPanGesture.addTarget(SideMenuTransition.self, action:#selector(SideMenuTransition.handleHideMenuPan(_:)))
|
||||
menuLeftNavigationController.view.addGestureRecognizer(exitPanGesture)
|
||||
menuLeftNavigationController.transitioningDelegate = SideMenuTransition.singleton
|
||||
menuLeftNavigationController.modalPresentationStyle = .OverFullScreen
|
||||
if !menuLeftNavigationController.leftSide {
|
||||
menuLeftNavigationController.leftSide = true
|
||||
}
|
||||
menuLeftSwipeToDismissGesture = exitPanGesture
|
||||
updateMenuBlurIfNecessary()
|
||||
guard oldValue?.presentingViewController == nil else {
|
||||
print("SideMenu Warning: menuLeftNavigationController cannot be modified while it's presented.")
|
||||
menuLeftNavigationController = oldValue
|
||||
return
|
||||
}
|
||||
setupNavigationController(menuLeftNavigationController, leftSide: true)
|
||||
}
|
||||
}
|
||||
|
||||
/// The right menu.
|
||||
public static var menuRightNavigationController: UISideMenuNavigationController? {
|
||||
willSet {
|
||||
if menuRightNavigationController != nil {
|
||||
let originalBlurEffectStyle = menuBlurEffectStyle
|
||||
menuBlurEffectStyle = nil
|
||||
updateMenuBlurIfNecessary()
|
||||
menuBlurEffectStyle = originalBlurEffectStyle
|
||||
if menuRightNavigationController?.presentingViewController == nil {
|
||||
removeMenuBlurForMenu(menuRightNavigationController)
|
||||
}
|
||||
}
|
||||
didSet {
|
||||
if let menuRightNavigationController = menuRightNavigationController {
|
||||
let exitPanGesture = UIPanGestureRecognizer()
|
||||
exitPanGesture.addTarget(SideMenuTransition.self, action:#selector(SideMenuTransition.handleHideMenuPan(_:)))
|
||||
menuRightNavigationController.view.addGestureRecognizer(exitPanGesture)
|
||||
menuRightNavigationController.transitioningDelegate = SideMenuTransition.singleton
|
||||
menuRightNavigationController.modalPresentationStyle = .OverFullScreen
|
||||
if menuRightNavigationController.leftSide {
|
||||
menuRightNavigationController.leftSide = false
|
||||
}
|
||||
menuRightSwipeToDismissGesture = exitPanGesture
|
||||
updateMenuBlurIfNecessary()
|
||||
guard oldValue?.presentingViewController == nil else {
|
||||
print("SideMenu Warning: menuRightNavigationController cannot be modified while it's presented.")
|
||||
menuRightNavigationController = oldValue
|
||||
return
|
||||
}
|
||||
setupNavigationController(menuRightNavigationController, leftSide: false)
|
||||
}
|
||||
}
|
||||
|
||||
private class func setupNavigationController(forMenu: UISideMenuNavigationController?, leftSide: Bool) {
|
||||
guard let forMenu = forMenu else {
|
||||
return
|
||||
}
|
||||
|
||||
let exitPanGesture = UIPanGestureRecognizer()
|
||||
exitPanGesture.addTarget(SideMenuTransition.self, action:#selector(SideMenuTransition.handleHideMenuPan(_:)))
|
||||
forMenu.view.addGestureRecognizer(exitPanGesture)
|
||||
forMenu.transitioningDelegate = SideMenuTransition.singleton
|
||||
forMenu.modalPresentationStyle = .OverFullScreen
|
||||
forMenu.leftSide = leftSide
|
||||
if leftSide {
|
||||
menuLeftSwipeToDismissGesture = exitPanGesture
|
||||
} else {
|
||||
menuRightSwipeToDismissGesture = exitPanGesture
|
||||
}
|
||||
updateMenuBlurIfNecessary()
|
||||
}
|
||||
|
||||
private class func updateMenuBlurIfNecessary() {
|
||||
if let menuLeftNavigationController = menuLeftNavigationController, let view = menuLeftNavigationController.visibleViewController?.view {
|
||||
if !UIAccessibilityIsReduceTransparencyEnabled() && menuBlurEffectStyle != nil {
|
||||
if originalLeftMenuBackgroundColor == nil {
|
||||
originalLeftMenuBackgroundColor = view.backgroundColor
|
||||
}
|
||||
setupMenuBlurForMenu(menuLeftNavigationController)
|
||||
} else if originalLeftMenuBackgroundColor != nil {
|
||||
removeMenuBlurForMenu(menuLeftNavigationController)
|
||||
view.backgroundColor = originalLeftMenuBackgroundColor!
|
||||
originalLeftMenuBackgroundColor = nil
|
||||
let menuBlurBlock = { (forMenu: UISideMenuNavigationController?) in
|
||||
if let forMenu = forMenu {
|
||||
setupMenuBlurForMenu(forMenu)
|
||||
}
|
||||
}
|
||||
|
||||
if let menuRightNavigationController = menuRightNavigationController, let view = menuRightNavigationController.visibleViewController?.view {
|
||||
if !UIAccessibilityIsReduceTransparencyEnabled() && menuBlurEffectStyle != nil {
|
||||
if originalRightMenuBackgroundColor == nil {
|
||||
originalRightMenuBackgroundColor = view.backgroundColor
|
||||
}
|
||||
setupMenuBlurForMenu(menuRightNavigationController)
|
||||
} else if originalRightMenuBackgroundColor != nil {
|
||||
removeMenuBlurForMenu(menuRightNavigationController)
|
||||
view.backgroundColor = originalRightMenuBackgroundColor!
|
||||
originalRightMenuBackgroundColor = nil
|
||||
}
|
||||
}
|
||||
menuBlurBlock(menuLeftNavigationController)
|
||||
menuBlurBlock(menuRightNavigationController)
|
||||
}
|
||||
|
||||
private class func setupMenuBlurForMenu(forMenu: UINavigationController) {
|
||||
private class func setupMenuBlurForMenu(forMenu: UISideMenuNavigationController?) {
|
||||
removeMenuBlurForMenu(forMenu)
|
||||
|
||||
guard let forMenu = forMenu,
|
||||
menuBlurEffectStyle = menuBlurEffectStyle,
|
||||
view = forMenu.visibleViewController?.view
|
||||
where !UIAccessibilityIsReduceTransparencyEnabled() else {
|
||||
return
|
||||
}
|
||||
|
||||
if forMenu.originalMenuBackgroundColor == nil {
|
||||
forMenu.originalMenuBackgroundColor = view.backgroundColor
|
||||
}
|
||||
|
||||
let blurEffect = UIBlurEffect(style: menuBlurEffectStyle)
|
||||
let blurView = UIVisualEffectView(effect: blurEffect)
|
||||
view.backgroundColor = UIColor.clearColor()
|
||||
if let tableViewController = forMenu.visibleViewController as? UITableViewController {
|
||||
tableViewController.tableView.backgroundColor = UIColor.clearColor()
|
||||
|
||||
let blurEffect = UIBlurEffect(style: menuBlurEffectStyle!)
|
||||
tableViewController.tableView.backgroundView = UIVisualEffectView(effect: blurEffect)
|
||||
tableViewController.tableView.backgroundView = blurView
|
||||
tableViewController.tableView.separatorEffect = UIVibrancyEffect(forBlurEffect: blurEffect)
|
||||
tableViewController.tableView.reloadData()
|
||||
} else if let viewController = forMenu.visibleViewController {
|
||||
viewController.view.backgroundColor = UIColor.clearColor()
|
||||
|
||||
let blurView = UIVisualEffectView(effect: UIBlurEffect(style: menuBlurEffectStyle!))
|
||||
} else {
|
||||
blurView.autoresizingMask = [.FlexibleHeight, .FlexibleWidth]
|
||||
blurView.frame = viewController.view.bounds
|
||||
|
||||
viewController.view.insertSubview(blurView, atIndex: 0)
|
||||
blurView.frame = view.bounds
|
||||
view.insertSubview(blurView, atIndex: 0)
|
||||
}
|
||||
}
|
||||
|
||||
private class func removeMenuBlurForMenu(forMenu: UINavigationController) {
|
||||
private class func removeMenuBlurForMenu(forMenu: UISideMenuNavigationController?) {
|
||||
guard let forMenu = forMenu,
|
||||
originalMenuBackgroundColor = forMenu.originalMenuBackgroundColor,
|
||||
view = forMenu.visibleViewController?.view else {
|
||||
return
|
||||
}
|
||||
|
||||
view.backgroundColor = originalMenuBackgroundColor
|
||||
forMenu.originalMenuBackgroundColor = nil
|
||||
|
||||
if let tableViewController = forMenu.visibleViewController as? UITableViewController {
|
||||
tableViewController.tableView.backgroundView = nil
|
||||
tableViewController.tableView.separatorEffect = nil
|
||||
tableViewController.tableView.reloadData()
|
||||
} else if let viewController = forMenu.visibleViewController {
|
||||
if let blurView = viewController.view.subviews[0] as? UIVisualEffectView {
|
||||
blurView.removeFromSuperview()
|
||||
}
|
||||
} else if let blurView = view.subviews[0] as? UIVisualEffectView {
|
||||
blurView.removeFromSuperview()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,7 +234,6 @@ public class SideMenuManager {
|
||||
- Returns: The array of screen edge gestures added to `toView`.
|
||||
*/
|
||||
public class func menuAddScreenEdgePanGesturesToPresent(toView toView: UIView, forMenu:UIRectEdge? = nil) -> [UIScreenEdgePanGestureRecognizer] {
|
||||
|
||||
var array = [UIScreenEdgePanGestureRecognizer]()
|
||||
|
||||
if forMenu != .Right {
|
||||
|
||||
@@ -204,7 +204,7 @@ internal class SideMenuTransition: UIPercentDrivenInteractiveTransition, UIViewC
|
||||
originalSuperview?.addSubview(mainViewController.view)
|
||||
}
|
||||
|
||||
internal class func presentMenuStart(forSize size: CGSize = UIScreen.mainScreen().bounds.size) {
|
||||
internal class func presentMenuStart(forSize size: CGSize = SideMenuManager.appScreenRect.size) {
|
||||
guard let menuView = SideMenuTransition.presentDirection == .Left ? SideMenuManager.menuLeftNavigationController?.view : SideMenuManager.menuRightNavigationController?.view else {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@ import UIKit
|
||||
|
||||
public class UISideMenuNavigationController: UINavigationController {
|
||||
|
||||
internal var originalMenuBackgroundColor: UIColor?
|
||||
|
||||
public override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
|
||||
@@ -21,7 +23,7 @@ public class UISideMenuNavigationController: UINavigationController {
|
||||
/// Whether the menu appears on the right or left side of the screen. Right is the default.
|
||||
@IBInspectable public var leftSide:Bool = false {
|
||||
didSet {
|
||||
if isViewLoaded() { // suppress warnings
|
||||
if isViewLoaded() && oldValue != leftSide { // suppress warnings
|
||||
didSetSide()
|
||||
}
|
||||
}
|
||||
@@ -148,7 +150,7 @@ public class UISideMenuNavigationController: UINavigationController {
|
||||
CATransaction.commit()
|
||||
} else {
|
||||
menuViewController.presentViewController(viewController, animated: animated, completion: nil)
|
||||
print("Warning: attempted to push a ViewController from a ViewController that doesn't have a NavigationController. It will be presented it instead.")
|
||||
print("SideMenu Warning: cannot push a ViewController from a ViewController without a NavigationController. It will be presented it instead.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,15 +3,20 @@
|
||||
[](http://cocoapods.org/pods/SideMenu)
|
||||
[](http://cocoapods.org/pods/SideMenu)
|
||||
|
||||
### If you like SideMenu, give it a ★ at the top right of this page.
|
||||
## Shameless Requests First
|
||||
**1. If you like SideMenu, give it a ★ at the top right of its [GitHub](https://github.com/jonkykong/SideMenu) page.**
|
||||
|
||||
**2. I need an invite to Dribbble to share SideMenu. Invite me: https://dribbble.com/jonkykong**
|
||||
|
||||
## Overview
|
||||
|
||||
SideMenu is a simple and versatile side menu control written in Swift.
|
||||
- [x] **It can be implemented in storyboard without a single line of [code](#code-less-storyboard-implementation).**
|
||||
- [x] Four standard animation styles to choose from (even parallax if you want to get weird).
|
||||
- [x] Highly customizable without needing to write tons of custom code.
|
||||
- [x] Supports continuous swiping between side menus on boths sides in a single gesture.
|
||||
- [x] Global menu configuration. Set-up once and be done for all screens.
|
||||
- [x] Menus can be presented and dismissed the same as any other View Controller since this control uses custom transitions.
|
||||
* **It can be implemented in storyboard without a single line of [code](#code-less-storyboard-implementation).**
|
||||
* Four standard animation styles to choose from (even parallax if you want to get weird).
|
||||
* Highly customizable without needing to write tons of custom code.
|
||||
* Supports continuous swiping between side menus on boths sides in a single gesture.
|
||||
* Global menu configuration. Set-up once and be done for all screens.
|
||||
* Menus can be presented and dismissed the same as any other View Controller since this control uses custom transitions.
|
||||
|
||||
Check out the example project or this [interactive demo](https://appetize.io/app/64a9v3e6b8c6f53zvn5pnny80m) to see it in action!
|
||||
|
||||
@@ -21,7 +26,7 @@ Check out the example project or this [interactive demo](https://appetize.io/app
|
||||

|
||||
|
||||
## Requirements
|
||||
- [x] iOS 8 or higher
|
||||
* iOS 8 or higher
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -118,6 +123,13 @@ menuAddPanGestureToPresent(toView toView: UIView) -> UIPanGestureRecognizer
|
||||
## Known Issues
|
||||
Don't try to change the status bar appearance when presenting a menu. When used with quick gestures/animations, it causes the presentation animation to not complete properly and locks the UI. See [radar 21961293](http://www.openradar.me/21961293) for more information.
|
||||
|
||||
## About Me
|
||||
My name is Jon Kent and I'm a freelance iOS designer, developer, and mobile strategist. I love coffee and play the drums. **Hire me!**
|
||||
|
||||
🌎 Web: [http://jonkent.me](http://jonkent.me)
|
||||
|
||||
✉️ Email: [contact@jonkent.me](mailto:contact@jonkent.me)
|
||||
|
||||
## License
|
||||
|
||||
SideMenu is available under the MIT license. See the LICENSE file for more info.
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
|
||||
Pod::Spec.new do |s|
|
||||
s.name = "SideMenu"
|
||||
s.version = "1.1.5"
|
||||
s.version = "1.1.7"
|
||||
s.summary = "Simple side menu control for iOS in Swift inspired by Facebook. Right and Left sides. No coding required."
|
||||
|
||||
# This description is used to generate tags and improve search results.
|
||||
|
||||
Reference in New Issue
Block a user