Compare commits
46 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ad462962fd | |||
| 6ed444f433 | |||
| a65e26cb47 | |||
| 94610771b4 | |||
| 5599796e9d | |||
| 33449c84a0 | |||
| 458b246013 | |||
| a58a170979 | |||
| e4c43569de | |||
| 966e1c9976 | |||
| 1241215e53 | |||
| 09070849d8 | |||
| 8705078fa5 | |||
| 48a39b4573 | |||
| 3611a6f5b8 | |||
| 701d482714 | |||
| 9574c37479 | |||
| 52faf9a7e1 | |||
| 05a3659255 | |||
| ef0c5fceed | |||
| eab7e274e8 | |||
| f9ec208e36 | |||
| 6b9607fc9a | |||
| 8ad4b3a4d9 | |||
| b0357d3f54 | |||
| 7a30c5441e | |||
| 13e3d504f1 | |||
| 02578a894a | |||
| 2e54a9d21a | |||
| d31f4419e1 | |||
| 7bf1668184 | |||
| e12faa68c9 | |||
| ecebaca9b9 | |||
| aeb660b02f | |||
| e6eb28385c | |||
| f9f8fd7817 | |||
| dda720eee7 | |||
| 8bb2505b6f | |||
| 2878eea03f | |||
| 7512cb9373 | |||
| 189586d8e8 | |||
| f4d78af501 | |||
| af2ef21f88 | |||
| 25b87e4780 | |||
| c966675305 | |||
| b0dfba206c |
@@ -4,7 +4,7 @@ Thank you for your interest in SideMenu!
|
||||
|
||||
I have received a surprising amount of questions about SideMenu since putting it up here. A few people in the community have identified some problems and helped contribute to SideMenu to make it better for everyone and I'm truly grateful for the support! Keep them coming!
|
||||
|
||||
I have also received a number of questions about people having issues implementing SideMenu, mostly from beginners learning how to code. As much as I would love to help all of you, I simply do **not** have the time to teach you. I am only supporting bugfixes or reviewing pull requests.
|
||||
I have also received a number of questions about people having issues implementing SideMenu, mostly from beginners learning how to code. As much as I would love to help all of you, **I do not have time to teach you**. I am only supporting bugfixes or reviewing pull requests.
|
||||
|
||||
I spent a lot of time putting together a detailed [README](https://github.com/jonkykong/SideMenu/blob/master/README.md), adding comments about usage in code, and provided a [demo project](https://github.com/jonkykong/SideMenu/tree/master/Example). These will give you all the information you need to work through any problem, **saving _you_ the time it takes for me to personally respond.**
|
||||
|
||||
@@ -17,7 +17,7 @@ I spent a lot of time putting together a detailed [README](https://github.com/jo
|
||||
### If your question is about SideMenu not working the way it's described in the [README](https://github.com/jonkykong/SideMenu/blob/master/README.md)...
|
||||
- This *may* be a bug. You must be able to reproduce the bug in the [demo project](https://github.com/jonkykong/SideMenu/tree/master/Example) which has a minimal amount of code. This helps ensure you don't have a bug in your code unrelated to SideMenu. If the bug is reproducable, open an issue and I will respond to it when I find time.
|
||||
|
||||
**Again**, please do **not** email me or open any issues if you want to know how to use SideMenu or are having trouble getting it to do behave a specific way not described in the [README](https://github.com/jonkykong/SideMenu/blob/master/README.md). I am not **tech support**. I am not a **teacher**. If you open an issue while failing to follow these guidelines or use the provided templates your **request for help will be ignored**.
|
||||
**Again**, please do **not** email me or open any issues if you want to know how to use SideMenu or are having trouble getting it to behave a specific way not described in the [README](https://github.com/jonkykong/SideMenu/blob/master/README.md). I am not **tech support**. I am not a **teacher**. If you open an issue while failing to follow these guidelines or use the provided templates your **request for help will be ignored**.
|
||||
|
||||
### Thanks again for your support and for being respectful of my time.
|
||||
I apologize if this seems harsh, but there have been too many developers that have willfully ignored all of this and continued to contact me.
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<!--- Provide a general summary of your changes in the Title above -->
|
||||
<!--- IF YOU DELETE OR IGNORE THIS TEMPLATE WHEN OPENING A NEW ISSUE, YOUR ISSUE WILL BE IGNORED -->
|
||||
<!--- IF YOU DELETE OR IGNORE THIS TEMPLATE YOUR ISSUE WILL BE IGNORED AND CLOSED -->
|
||||
## New Issue Checklist
|
||||
<!--- Please complete all of the checks below before submitting a new issue (complete a check by marking it [x] with no spaces) -->
|
||||
I have read the [guidelines for contributing](https://github.com/jonkykong/SideMenu/blob/master/.github/CONTRIBUTING.md) and I understand:
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11542" systemVersion="16B2555" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="yAA-s6-Bam">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13196" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="yAA-s6-Bam">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11524"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13173"/>
|
||||
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
@@ -15,7 +15,7 @@
|
||||
<objects>
|
||||
<navigationController id="yAA-s6-Bam" sceneMemberID="viewController">
|
||||
<navigationBar key="navigationBar" contentMode="scaleToFill" barStyle="black" id="Bue-4e-bCJ">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
||||
<rect key="frame" x="0.0" y="20" width="375" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<gestureRecognizers/>
|
||||
<color key="tintColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
@@ -42,7 +42,7 @@
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="LFJ-SB-Zp9">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="635"/>
|
||||
<rect key="frame" x="0.0" y="64" width="375" height="571"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="DMn-tw-NTB">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="469"/>
|
||||
@@ -205,9 +205,9 @@
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="LFJ-SB-Zp9" firstAttribute="top" secondItem="0gg-po-Ih1" secondAttribute="topMargin" id="0T7-Dc-CaB"/>
|
||||
<constraint firstItem="LFJ-SB-Zp9" firstAttribute="leading" secondItem="0gg-po-Ih1" secondAttribute="leading" id="OsA-4z-Y7t"/>
|
||||
<constraint firstItem="ma4-O6-wOT" firstAttribute="top" secondItem="LFJ-SB-Zp9" secondAttribute="bottom" constant="8" id="UUi-lo-0RA"/>
|
||||
<constraint firstItem="LFJ-SB-Zp9" firstAttribute="top" secondItem="Rm7-bv-OCN" secondAttribute="bottom" id="W6M-QX-I2w"/>
|
||||
<constraint firstItem="ma4-O6-wOT" firstAttribute="centerX" secondItem="0gg-po-Ih1" secondAttribute="centerX" id="aia-PT-OH3"/>
|
||||
<constraint firstItem="LW0-9z-RHu" firstAttribute="top" secondItem="ma4-O6-wOT" secondAttribute="bottom" constant="8" id="d5Q-Sj-0Xz"/>
|
||||
<constraint firstItem="LFJ-SB-Zp9" firstAttribute="top" secondItem="Rm7-bv-OCN" secondAttribute="bottom" id="ssi-ps-a2k"/>
|
||||
@@ -252,7 +252,6 @@
|
||||
<navigationController storyboardIdentifier="LeftMenuNavigationController" navigationBarHidden="YES" id="DuX-EW-0mP" customClass="UISideMenuNavigationController" customModule="SideMenu" sceneMemberID="viewController">
|
||||
<navigationItem key="navigationItem" id="ipz-Lx-Wgf"/>
|
||||
<navigationBar key="navigationBar" contentMode="scaleToFill" id="35F-wh-r6h">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</navigationBar>
|
||||
<userDefinedRuntimeAttributes>
|
||||
@@ -387,7 +386,6 @@
|
||||
<objects>
|
||||
<navigationController storyboardIdentifier="RightMenuNavigationController" navigationBarHidden="YES" id="z7k-fk-pfc" customClass="UISideMenuNavigationController" customModule="SideMenu" sceneMemberID="viewController">
|
||||
<navigationBar key="navigationBar" contentMode="scaleToFill" id="qOd-yQ-2i8">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</navigationBar>
|
||||
<connections>
|
||||
@@ -589,7 +587,7 @@
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="a17-pq-WAQ">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<rect key="frame" x="0.0" y="20" width="375" height="647"/>
|
||||
<state key="normal" title="Dismiss">
|
||||
<color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</state>
|
||||
|
||||
@@ -14,6 +14,8 @@ class SideMenuTableView: UITableViewController {
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
|
||||
print("SideMenu Appearing!")
|
||||
|
||||
// this will be non-nil if a blur effect is applied
|
||||
guard tableView.backgroundView == nil else {
|
||||
return
|
||||
@@ -24,8 +26,6 @@ class SideMenuTableView: UITableViewController {
|
||||
imageView.contentMode = .scaleAspectFit
|
||||
imageView.backgroundColor = UIColor.black.withAlphaComponent(0.2)
|
||||
tableView.backgroundView = imageView
|
||||
|
||||
print("SideMenu Appearing!")
|
||||
}
|
||||
|
||||
override func viewDidAppear(_ animated: Bool) {
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
open class SideMenuManager : NSObject {
|
||||
|
||||
@objc public enum MenuPushStyle : Int {
|
||||
public enum MenuPushStyle : Int {
|
||||
case defaultBehavior,
|
||||
popWhenPossible,
|
||||
replace,
|
||||
@@ -27,7 +27,7 @@ open class SideMenuManager : NSObject {
|
||||
subMenu
|
||||
}
|
||||
|
||||
@objc public enum MenuPresentMode : Int {
|
||||
public enum MenuPresentMode : Int {
|
||||
case menuSlideIn,
|
||||
viewSlideOut,
|
||||
viewSlideInOut,
|
||||
@@ -66,8 +66,12 @@ open class SideMenuManager : NSObject {
|
||||
|
||||
/// Prevents the same view controller (or a view controller of the same class) from being pushed more than once. Defaults to true.
|
||||
open static var menuAllowPushOfSameClassTwice = true
|
||||
|
||||
/// Width of the menu when presented on screen, showing the existing view controller in the remaining space. Default is 75% of the screen width.
|
||||
|
||||
/**
|
||||
Width of the menu when presented on screen, showing the existing view controller in the remaining space. Default is 75% of the screen width.
|
||||
|
||||
Note that each menu's width can be overridden using the `menuWidth` property on any `UISideMenuNavigationController` instance.
|
||||
*/
|
||||
open 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.
|
||||
@@ -76,8 +80,8 @@ open class SideMenuManager : NSObject {
|
||||
/// Duration of the animation when the menu is dismissed without gestures. Default is 0.35 seconds.
|
||||
open static var menuAnimationDismissDuration: Double = 0.35
|
||||
|
||||
/// Duration of the remaining animation when the menu is partially dismissed with gestures. Default is 0.2 seconds.
|
||||
open static var menuAnimationCompleteGestureDuration: Double = 0.20
|
||||
/// Duration of the remaining animation when the menu is partially dismissed with gestures. Default is 0.35 seconds.
|
||||
open static var menuAnimationCompleteGestureDuration: Double = 0.35
|
||||
|
||||
/// Amount to fade the existing view controller when the menu is presented. Default is 0 for no fade. Set to 1 to fade completely.
|
||||
open static var menuAnimationFadeStrength: CGFloat = 0
|
||||
@@ -97,12 +101,6 @@ open class SideMenuManager : NSObject {
|
||||
/// The radius of the shadow around the menu view controller or existing view controller depending on the `menuPresentMode`. Default is 5.
|
||||
open static var menuShadowRadius: CGFloat = 5
|
||||
|
||||
/// The left menu swipe to dismiss gesture.
|
||||
open static weak var menuLeftSwipeToDismissGesture: UIPanGestureRecognizer?
|
||||
|
||||
/// The right menu swipe to dismiss gesture.
|
||||
open static weak var menuRightSwipeToDismissGesture: UIPanGestureRecognizer?
|
||||
|
||||
/// Enable or disable interaction with the presenting view controller while the menu is displayed. Enabling may make it difficult to dismiss the menu or cause exceptions if the user tries to present and already presented menu. Default is false.
|
||||
open static var menuPresentingViewControllerUserInteractionEnabled: Bool = false
|
||||
|
||||
@@ -121,6 +119,14 @@ open class SideMenuManager : NSObject {
|
||||
/// The animation initial spring velocity when a menu is displayed. Ignored when displayed with a gesture.
|
||||
open static var menuAnimationInitialSpringVelocity: CGFloat = 1
|
||||
|
||||
/**
|
||||
Automatically dismisses the menu when another view is pushed from it.
|
||||
|
||||
Note: to prevent the menu from dismissing when presenting, set modalPresentationStyle = .overFullScreen
|
||||
of the view controller being presented in storyboard or during its initalization.
|
||||
*/
|
||||
open static var menuDismissOnPush = true
|
||||
|
||||
/// -Warning: Deprecated. Use `menuPushStyle = .subMenu` instead.
|
||||
@available(*, deprecated, renamed: "menuPushStyle", message: "Use `menuPushStyle = .subMenu` instead.")
|
||||
open static var menuAllowSubmenus: Bool {
|
||||
@@ -221,6 +227,30 @@ open class SideMenuManager : NSObject {
|
||||
}
|
||||
}
|
||||
|
||||
/// The left menu swipe to dismiss gesture.
|
||||
open static weak var menuLeftSwipeToDismissGesture: UIPanGestureRecognizer? {
|
||||
didSet {
|
||||
oldValue?.view?.removeGestureRecognizer(oldValue!)
|
||||
setupGesture(gesture: menuLeftSwipeToDismissGesture)
|
||||
}
|
||||
}
|
||||
|
||||
/// The right menu swipe to dismiss gesture.
|
||||
open static weak var menuRightSwipeToDismissGesture: UIPanGestureRecognizer? {
|
||||
didSet {
|
||||
oldValue?.view?.removeGestureRecognizer(oldValue!)
|
||||
setupGesture(gesture: menuRightSwipeToDismissGesture)
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate class func setupGesture(gesture: UIPanGestureRecognizer?) {
|
||||
guard let gesture = gesture else {
|
||||
return
|
||||
}
|
||||
|
||||
gesture.addTarget(SideMenuTransition.self, action:#selector(SideMenuTransition.handleHideMenuPan(_:)))
|
||||
}
|
||||
|
||||
fileprivate class func setupNavigationController(_ forMenu: UISideMenuNavigationController?, leftSide: Bool) {
|
||||
guard let forMenu = forMenu else {
|
||||
return
|
||||
@@ -228,7 +258,6 @@ open class SideMenuManager : NSObject {
|
||||
|
||||
if menuEnableSwipeGestures {
|
||||
let exitPanGesture = UIPanGestureRecognizer()
|
||||
exitPanGesture.addTarget(SideMenuTransition.self, action:#selector(SideMenuTransition.handleHideMenuPan(_:)))
|
||||
forMenu.view.addGestureRecognizer(exitPanGesture)
|
||||
if leftSide {
|
||||
menuLeftSwipeToDismissGesture = exitPanGesture
|
||||
|
||||
@@ -14,8 +14,22 @@ open class SideMenuTransition: UIPercentDrivenInteractiveTransition {
|
||||
fileprivate var interactive = false
|
||||
fileprivate static weak var originalSuperview: UIView?
|
||||
fileprivate static weak var activeGesture: UIGestureRecognizer?
|
||||
fileprivate static var switchMenus = false
|
||||
|
||||
fileprivate static var switchMenus = false {
|
||||
didSet {
|
||||
if switchMenus {
|
||||
singleton.cancel()
|
||||
}
|
||||
}
|
||||
}
|
||||
fileprivate static var menuWidth: CGFloat {
|
||||
get {
|
||||
let overriddenWidth = viewControllerForMenu?.menuWidth ?? 0
|
||||
if overriddenWidth > CGFloat.ulpOfOne {
|
||||
return overriddenWidth
|
||||
}
|
||||
return SideMenuManager.menuWidth
|
||||
}
|
||||
}
|
||||
internal static let singleton = SideMenuTransition()
|
||||
internal static var presentDirection: UIRectEdge = .left
|
||||
internal static weak var tapView: UIView? {
|
||||
@@ -39,11 +53,7 @@ open class SideMenuTransition: UIPercentDrivenInteractiveTransition {
|
||||
return
|
||||
}
|
||||
|
||||
if let menuShrinkBackgroundColor = SideMenuManager.menuAnimationBackgroundColor {
|
||||
statusBarView.backgroundColor = menuShrinkBackgroundColor
|
||||
} else {
|
||||
statusBarView.backgroundColor = UIColor.black
|
||||
}
|
||||
statusBarView.backgroundColor = SideMenuManager.menuAnimationBackgroundColor ?? UIColor.black
|
||||
statusBarView.isUserInteractionEnabled = false
|
||||
}
|
||||
}
|
||||
@@ -89,23 +99,25 @@ open class SideMenuTransition: UIPercentDrivenInteractiveTransition {
|
||||
return viewController
|
||||
}
|
||||
|
||||
internal class func handlePresentMenuLeftScreenEdge(_ edge: UIScreenEdgePanGestureRecognizer) {
|
||||
@objc internal class func handlePresentMenuLeftScreenEdge(_ edge: UIScreenEdgePanGestureRecognizer) {
|
||||
SideMenuTransition.presentDirection = .left
|
||||
handlePresentMenuPan(edge)
|
||||
}
|
||||
|
||||
internal class func handlePresentMenuRightScreenEdge(_ edge: UIScreenEdgePanGestureRecognizer) {
|
||||
@objc internal class func handlePresentMenuRightScreenEdge(_ edge: UIScreenEdgePanGestureRecognizer) {
|
||||
SideMenuTransition.presentDirection = .right
|
||||
handlePresentMenuPan(edge)
|
||||
}
|
||||
|
||||
internal class func handlePresentMenuPan(_ pan: UIPanGestureRecognizer) {
|
||||
@objc internal class func handlePresentMenuPan(_ pan: UIPanGestureRecognizer) {
|
||||
if activeGesture == nil {
|
||||
activeGesture = pan
|
||||
} else if pan != activeGesture {
|
||||
pan.isEnabled = false
|
||||
pan.isEnabled = true
|
||||
return
|
||||
} else if pan.state != .began && pan.state != .changed {
|
||||
activeGesture = nil
|
||||
}
|
||||
|
||||
// how much distance have we panned in reference to the parent view?
|
||||
@@ -137,7 +149,7 @@ open class SideMenuTransition: UIPercentDrivenInteractiveTransition {
|
||||
}
|
||||
|
||||
let direction: CGFloat = SideMenuTransition.presentDirection == .left ? 1 : -1
|
||||
let distance = translation.x / SideMenuManager.menuWidth
|
||||
let distance = translation.x / menuWidth
|
||||
// now lets deal with different states that the gesture recognizer sends
|
||||
switch (pan.state) {
|
||||
case .began, .changed:
|
||||
@@ -146,11 +158,9 @@ open class SideMenuTransition: UIPercentDrivenInteractiveTransition {
|
||||
} else if distance > 0 && SideMenuTransition.presentDirection == .right && SideMenuManager.menuLeftNavigationController != nil {
|
||||
SideMenuTransition.presentDirection = .left
|
||||
switchMenus = true
|
||||
singleton.cancel()
|
||||
} else if distance < 0 && SideMenuTransition.presentDirection == .left && SideMenuManager.menuRightNavigationController != nil {
|
||||
SideMenuTransition.presentDirection = .right
|
||||
switchMenus = true
|
||||
singleton.cancel()
|
||||
} else {
|
||||
singleton.update(min(distance * direction, 1))
|
||||
}
|
||||
@@ -165,15 +175,13 @@ open class SideMenuTransition: UIPercentDrivenInteractiveTransition {
|
||||
singleton.update(0.9999)
|
||||
}
|
||||
singleton.finish()
|
||||
activeGesture = nil
|
||||
} else {
|
||||
singleton.cancel()
|
||||
activeGesture = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class func handleHideMenuPan(_ pan: UIPanGestureRecognizer) {
|
||||
@objc internal class func handleHideMenuPan(_ pan: UIPanGestureRecognizer) {
|
||||
if activeGesture == nil {
|
||||
activeGesture = pan
|
||||
} else if pan != activeGesture {
|
||||
@@ -184,7 +192,7 @@ open class SideMenuTransition: UIPercentDrivenInteractiveTransition {
|
||||
|
||||
let translation = pan.translation(in: pan.view!)
|
||||
let direction:CGFloat = SideMenuTransition.presentDirection == .left ? -1 : 1
|
||||
let distance = translation.x / SideMenuManager.menuWidth * direction
|
||||
let distance = translation.x / menuWidth * direction
|
||||
|
||||
switch (pan.state) {
|
||||
|
||||
@@ -210,7 +218,7 @@ open class SideMenuTransition: UIPercentDrivenInteractiveTransition {
|
||||
}
|
||||
}
|
||||
|
||||
internal class func handleHideMenuTap(_ tap: UITapGestureRecognizer) {
|
||||
@objc internal class func handleHideMenuTap(_ tap: UITapGestureRecognizer) {
|
||||
presentingViewControllerForMenu?.dismiss(animated: true, completion: nil)
|
||||
}
|
||||
|
||||
@@ -225,7 +233,7 @@ open class SideMenuTransition: UIPercentDrivenInteractiveTransition {
|
||||
mainViewController.view.frame.origin.y = 0
|
||||
menuView.transform = .identity
|
||||
menuView.frame.origin.y = 0
|
||||
menuView.frame.size.width = SideMenuManager.menuWidth
|
||||
menuView.frame.size.width = menuWidth
|
||||
menuView.frame.size.height = mainViewController.view.frame.height // in case status bar height changed
|
||||
var statusBarFrame = UIApplication.shared.statusBarFrame
|
||||
let statusBarOffset = SideMenuManager.appScreenRect.size.height - mainViewController.view.frame.maxY
|
||||
@@ -241,7 +249,7 @@ open class SideMenuTransition: UIPercentDrivenInteractiveTransition {
|
||||
|
||||
case .viewSlideOut:
|
||||
menuView.alpha = 1 - SideMenuManager.menuAnimationFadeStrength
|
||||
menuView.frame.origin.x = SideMenuTransition.presentDirection == .left ? 0 : mainViewController.view.frame.width - SideMenuManager.menuWidth
|
||||
menuView.frame.origin.x = SideMenuTransition.presentDirection == .left ? 0 : mainViewController.view.frame.width - menuWidth
|
||||
mainViewController.view.frame.origin.x = 0
|
||||
menuView.transform = CGAffineTransform(scaleX: SideMenuManager.menuAnimationTransformScaleFactor, y: SideMenuManager.menuAnimationTransformScaleFactor)
|
||||
|
||||
@@ -256,7 +264,7 @@ open class SideMenuTransition: UIPercentDrivenInteractiveTransition {
|
||||
|
||||
case .menuDissolveIn:
|
||||
menuView.alpha = 0
|
||||
menuView.frame.origin.x = SideMenuTransition.presentDirection == .left ? 0 : mainViewController.view.frame.width - SideMenuManager.menuWidth
|
||||
menuView.frame.origin.x = SideMenuTransition.presentDirection == .left ? 0 : mainViewController.view.frame.width - menuWidth
|
||||
mainViewController.view.frame.origin.x = 0
|
||||
}
|
||||
}
|
||||
@@ -290,9 +298,9 @@ open class SideMenuTransition: UIPercentDrivenInteractiveTransition {
|
||||
|
||||
menuView.alpha = 1
|
||||
menuView.transform = .identity
|
||||
menuView.frame.size.width = SideMenuManager.menuWidth
|
||||
menuView.frame.size.width = menuWidth
|
||||
let size = SideMenuManager.appScreenRect.size
|
||||
menuView.frame.origin.x = SideMenuTransition.presentDirection == .left ? 0 : size.width - SideMenuManager.menuWidth
|
||||
menuView.frame.origin.x = SideMenuTransition.presentDirection == .left ? 0 : size.width - menuWidth
|
||||
mainViewController.view.transform = .identity
|
||||
mainViewController.view.frame.size.width = size.width
|
||||
let statusBarOffset = size.height - menuView.bounds.height
|
||||
@@ -304,6 +312,8 @@ open class SideMenuTransition: UIPercentDrivenInteractiveTransition {
|
||||
if statusBarOffset >= CGFloat.ulpOfOne {
|
||||
statusBarFrame.size.height = statusBarOffset
|
||||
}
|
||||
SideMenuTransition.tapView?.transform = .identity
|
||||
SideMenuTransition.tapView?.bounds = mainViewController.view.bounds
|
||||
SideMenuTransition.statusBarView?.frame = statusBarFrame
|
||||
SideMenuTransition.statusBarView?.alpha = 1
|
||||
|
||||
@@ -329,6 +339,9 @@ open class SideMenuTransition: UIPercentDrivenInteractiveTransition {
|
||||
|
||||
if SideMenuManager.menuPresentMode != .viewSlideOut {
|
||||
mainViewController.view.transform = CGAffineTransform(scaleX: SideMenuManager.menuAnimationTransformScaleFactor, y: SideMenuManager.menuAnimationTransformScaleFactor)
|
||||
if SideMenuManager.menuAnimationTransformScaleFactor > 1 {
|
||||
SideMenuTransition.tapView?.transform = mainViewController.view.transform
|
||||
}
|
||||
mainViewController.view.alpha = 1 - SideMenuManager.menuAnimationFadeStrength
|
||||
}
|
||||
}
|
||||
@@ -360,7 +373,7 @@ open class SideMenuTransition: UIPercentDrivenInteractiveTransition {
|
||||
}
|
||||
}
|
||||
|
||||
internal func handleNotification() {
|
||||
@objc internal func handleNotification(notification: NSNotification) {
|
||||
guard let mainViewController = SideMenuTransition.presentingViewControllerForMenu,
|
||||
let menuViewController = SideMenuTransition.viewControllerForMenu,
|
||||
menuViewController.presentedViewController == nil && menuViewController.presentingViewController != nil else {
|
||||
@@ -370,6 +383,14 @@ open class SideMenuTransition: UIPercentDrivenInteractiveTransition {
|
||||
if let originalSuperview = SideMenuTransition.originalSuperview {
|
||||
originalSuperview.addSubview(mainViewController.view)
|
||||
}
|
||||
|
||||
if notification.name == NSNotification.Name.UIApplicationDidEnterBackground {
|
||||
SideMenuTransition.hideMenuStart()
|
||||
SideMenuTransition.hideMenuComplete()
|
||||
menuViewController.dismiss(animated: false, completion: nil)
|
||||
return
|
||||
}
|
||||
|
||||
UIView.animate(withDuration: SideMenuManager.menuAnimationDismissDuration,
|
||||
delay: 0,
|
||||
usingSpringWithDamping: SideMenuManager.menuAnimationUsingSpringWithDamping,
|
||||
@@ -478,6 +499,9 @@ extension SideMenuTransition: UIViewControllerAnimatedTransitioning {
|
||||
container.insertSubview(tapView, aboveSubview: topView)
|
||||
tapView.bounds = container.bounds
|
||||
tapView.center = topView.center
|
||||
if SideMenuManager.menuAnimationTransformScaleFactor > 1 {
|
||||
tapView.transform = topView.transform
|
||||
}
|
||||
SideMenuTransition.tapView = tapView
|
||||
}
|
||||
if let statusBarView = SideMenuTransition.statusBarView {
|
||||
@@ -496,7 +520,7 @@ extension SideMenuTransition: UIViewControllerAnimatedTransitioning {
|
||||
let duration = transitionDuration(using: transitionContext)
|
||||
if interactive {
|
||||
UIView.animate(withDuration: duration,
|
||||
delay: 0,
|
||||
delay: duration, // HACK: If zero, the animation briefly flashes in iOS 11. UIViewPropertyAnimators (iOS 10+) may resolve this.
|
||||
options: .curveLinear,
|
||||
animations: {
|
||||
animate()
|
||||
@@ -525,6 +549,13 @@ extension SideMenuTransition: UIViewControllerAnimatedTransitioning {
|
||||
return presenting ? SideMenuManager.menuAnimationPresentDuration : SideMenuManager.menuAnimationDismissDuration
|
||||
}
|
||||
|
||||
open override func update(_ percentComplete: CGFloat) {
|
||||
guard !SideMenuTransition.switchMenus else {
|
||||
return
|
||||
}
|
||||
|
||||
super.update(percentComplete)
|
||||
}
|
||||
}
|
||||
|
||||
extension SideMenuTransition: UIViewControllerTransitioningDelegate {
|
||||
|
||||
@@ -9,6 +9,9 @@ import UIKit
|
||||
|
||||
open class UISideMenuNavigationController: UINavigationController {
|
||||
|
||||
/// Width of the menu when presented on screen, showing the existing view controller in the remaining space. Default is zero. When zero, `SideMenuManager.menuWidth` is used.
|
||||
@IBInspectable open var menuWidth: CGFloat = 0
|
||||
|
||||
internal var originalMenuBackgroundColor: UIColor?
|
||||
|
||||
open override func awakeFromNib() {
|
||||
@@ -66,14 +69,46 @@ open class UISideMenuNavigationController: UINavigationController {
|
||||
}
|
||||
}
|
||||
|
||||
override open func viewWillDisappear(_ animated: Bool) {
|
||||
super.viewWillDisappear(animated)
|
||||
|
||||
// when presenting a view controller from the menu, the menu view gets moved into another transition view above our transition container
|
||||
// which can break the visual layout we had before. So, we move the menu view back to its original transition view to preserve it.
|
||||
if !isBeingDismissed {
|
||||
if let mainView = presentingViewController?.view {
|
||||
switch SideMenuManager.menuPresentMode {
|
||||
case .viewSlideOut, .viewSlideInOut:
|
||||
mainView.superview?.insertSubview(view, belowSubview: mainView)
|
||||
case .menuSlideIn, .menuDissolveIn:
|
||||
if let tapView = SideMenuTransition.tapView {
|
||||
mainView.superview?.insertSubview(view, aboveSubview: tapView)
|
||||
} else {
|
||||
mainView.superview?.insertSubview(view, aboveSubview: mainView)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if SideMenuManager.menuDismissOnPush {
|
||||
// We're presenting a view controller from the menu, so we need to hide the menu so it isn't showing when the presented view is dismissed.
|
||||
UIView.animate(withDuration: SideMenuManager.menuAnimationDismissDuration,
|
||||
delay: 0,
|
||||
usingSpringWithDamping: SideMenuManager.menuAnimationUsingSpringWithDamping,
|
||||
initialSpringVelocity: SideMenuManager.menuAnimationInitialSpringVelocity,
|
||||
options: SideMenuManager.menuAnimationOptions,
|
||||
animations: {
|
||||
SideMenuTransition.hideMenuStart()
|
||||
}) { (finished) -> Void in
|
||||
self.view.isHidden = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override open func viewDidDisappear(_ animated: Bool) {
|
||||
super.viewDidDisappear(animated)
|
||||
|
||||
// We're presenting a view controller from the menu, so we need to hide the menu so it isn't showing when the presented view is dismissed.
|
||||
if !isBeingDismissed {
|
||||
view.isHidden = true
|
||||
SideMenuTransition.hideMenuStart()
|
||||
}
|
||||
// Hack: force selection to get cleared on UITableViewControllers when reappearing using custom transitions
|
||||
visibleViewController?.viewWillAppear(false)
|
||||
}
|
||||
|
||||
override open func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
|
||||
@@ -92,20 +127,6 @@ open class UISideMenuNavigationController: UINavigationController {
|
||||
}
|
||||
}
|
||||
|
||||
override open func prepare(for segue: UIStoryboardSegue, sender: Any?) {
|
||||
if let presentingViewController = presentingViewController {
|
||||
presentingViewController.prepare(for: segue, sender: sender)
|
||||
}
|
||||
}
|
||||
|
||||
override open func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
|
||||
if let presentingViewController = presentingViewController {
|
||||
return presentingViewController.shouldPerformSegue(withIdentifier: identifier, sender: sender)
|
||||
}
|
||||
|
||||
return super.shouldPerformSegue(withIdentifier: identifier, sender: sender)
|
||||
}
|
||||
|
||||
override open func pushViewController(_ viewController: UIViewController, animated: Bool) {
|
||||
guard viewControllers.count > 0 && SideMenuManager.menuPushStyle != .subMenu else {
|
||||
// NOTE: pushViewController is called by init(rootViewController: UIViewController)
|
||||
@@ -114,9 +135,11 @@ open class UISideMenuNavigationController: UINavigationController {
|
||||
return
|
||||
}
|
||||
|
||||
let splitViewController = presentingViewController as? UISplitViewController
|
||||
let tabBarController = presentingViewController as? UITabBarController
|
||||
guard let navigationController = (tabBarController?.selectedViewController ?? presentingViewController) as? UINavigationController else {
|
||||
print("SideMenu Warning: attempt to push a View Controller from \(String(describing: presentingViewController.self)) where its navigationController == nil. It must be embedded in a Navigation Controller for this to work.")
|
||||
let potentialNavigationController = (splitViewController?.viewControllers.first ?? tabBarController?.selectedViewController) ?? presentingViewController
|
||||
guard let navigationController = potentialNavigationController as? UINavigationController else {
|
||||
print("SideMenu Warning: attempt to push a View Controller from \(String(describing: potentialNavigationController.self)) where its navigationController == nil. It must be embedded in a Navigation Controller for this to work.")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -125,7 +148,6 @@ open class UISideMenuNavigationController: UINavigationController {
|
||||
CATransaction.begin()
|
||||
CATransaction.setCompletionBlock( { () -> Void in
|
||||
self.dismiss(animated: true, completion: nil)
|
||||
self.visibleViewController?.viewWillAppear(false) // Hack: force selection to get cleared on UITableViewControllers when reappearing using custom transitions
|
||||
})
|
||||
|
||||
let areAnimationsEnabled = UIView.areAnimationsEnabled
|
||||
|
||||
@@ -14,6 +14,11 @@ open class UITableViewVibrantCell: UITableViewCell {
|
||||
fileprivate var vibrancySelectedBackgroundView:UIVisualEffectView = UIVisualEffectView()
|
||||
fileprivate var defaultSelectedBackgroundView:UIView?
|
||||
|
||||
// For registering with UITableView without subclassing otherwise dequeuing instance of the cell causes an exception
|
||||
public override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
|
||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||
}
|
||||
|
||||
required public init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
|
||||
|
||||
Generated
+28
-3
@@ -328,7 +328,7 @@
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0730;
|
||||
LastUpgradeCheck = 0700;
|
||||
LastUpgradeCheck = 0900;
|
||||
};
|
||||
buildConfigurationList = 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
@@ -405,20 +405,30 @@
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGNING_REQUIRED = NO;
|
||||
COPY_PHASE_STRIP = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"POD_CONFIGURATION_DEBUG=1",
|
||||
@@ -466,7 +476,7 @@
|
||||
SDKROOT = iphoneos;
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 3.0;
|
||||
SWIFT_VERSION = 4.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
@@ -482,19 +492,29 @@
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGNING_REQUIRED = NO;
|
||||
COPY_PHASE_STRIP = YES;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"POD_CONFIGURATION_RELEASE=1",
|
||||
"$(inherited)",
|
||||
@@ -508,6 +528,7 @@
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
PROVISIONING_PROFILE_SPECIFIER = NO_SIGNING/;
|
||||
STRIP_INSTALLED_PRODUCT = NO;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||
SYMROOT = "${SRCROOT}/../build";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
@@ -517,6 +538,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 3324698B7EF536D06111969551D7A984 /* Pods-Example.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
|
||||
"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
|
||||
@@ -553,6 +575,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = E84078875951590B4A5503E807E1791E /* Pods-Example.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
|
||||
"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
|
||||
@@ -588,6 +611,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7CAC7C8AA53EBC987714BAC240E7DE89 /* Pods-Example-ExampleTests.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
|
||||
"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
|
||||
@@ -624,6 +648,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 36CF7D6DA1B99FEA132A604D0BF8FB58 /* Pods-Example-ExampleTests.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
|
||||
"CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
|
||||
@@ -680,7 +705,7 @@
|
||||
PRODUCT_NAME = SideMenu;
|
||||
SDKROOT = iphoneos;
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_VERSION = 3.0;
|
||||
SWIFT_VERSION = 4.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
VERSION_INFO_PREFIX = "";
|
||||
|
||||
@@ -5,20 +5,24 @@
|
||||
[](http://cocoapods.org/pods/SideMenu)
|
||||
|
||||
### If you like SideMenu, give it a ★ at the top right of its [GitHub](https://github.com/jonkykong/SideMenu) page.
|
||||
#### Using SideMenu in your app? [Send](mailto:contact@jonkent.me?subject=SideMenu in action!) me a link to your app in the app store!
|
||||
#### Using SideMenu in your app? [Send](mailto:yo@massappeal.co?subject=SideMenu%20in%20action!) me a link to your app in the app store!
|
||||
|
||||
> I'm Jon Kent and I freelance iOS design, development, and mobile strategies. I love coffee and play the drums. [**Hire me**](mailto:contact@jonkent.me?subject=Let's build something amazing.) to help you make cool stuff. I also have a [website](http://jonkent.me). *Note: If you're having a problem with SideMenu, please open an [issue](https://github.com/jonkykong/SideMenu/issues/new) and do not email me.*
|
||||
> Hi, I'm Jon Kent and I am an iOS designer, developer, and mobile strategist. I love coffee and play the drums.
|
||||
> * [**Hire me**](mailto:yo@massappeal.co?subject=Let's%20build%20something%20amazing) to help you make cool stuff. *Note: If you're having a problem with SideMenu, please open an [issue](https://github.com/jonkykong/SideMenu/issues/new) and do not email me.*
|
||||
> * Check out my [website](http://massappeal.co) to see some of my other projects.
|
||||
> * Building and maintaining this free library takes time. Help keep me awake and buy me a coffee ☕️ via [PayPal](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=contact%40jonkent%2eme&lc=US¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted).
|
||||
|
||||
## Overview
|
||||
|
||||
SideMenu is a simple and versatile side menu control written in Swift.
|
||||
* **It can be implemented in storyboard without a single line of [code](#code-less-storyboard-implementation).**
|
||||
* Four standard animation styles to choose from (there's even a parallax effect 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](https://developer.apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/CustomizingtheTransitionAnimations.html).
|
||||
* Animations use your view controllers, not snapshots.
|
||||
- [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 (there's even a parallax effect 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](https://developer.apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/CustomizingtheTransitionAnimations.html).
|
||||
- [x] Animations use your view controllers, not snapshots.
|
||||
- [x] Properly handles screen rotation and in-call status bar height changes.
|
||||
|
||||
Check out the example project to see it in action!
|
||||
### Preview Samples
|
||||
@@ -27,7 +31,7 @@ Check out the example project to see it in action!
|
||||
|  |  |  |  |
|
||||
|
||||
## Requirements
|
||||
* iOS 8 or higher
|
||||
- [x] iOS 8 or higher
|
||||
|
||||
## Installation
|
||||
### CocoaPods
|
||||
@@ -208,6 +212,14 @@ open static var menuAnimationUsingSpringWithDamping: CGFloat = 1
|
||||
/// The animation initial spring velocity when a menu is displayed. Ignored when displayed with a gesture.
|
||||
open static var menuAnimationInitialSpringVelocity: CGFloat = 1
|
||||
|
||||
/**
|
||||
Automatically dismisses the menu when another view is pushed from it.
|
||||
|
||||
Note: to prevent the menu from dismissing when presenting, set modalPresentationStyle = .overFullScreen
|
||||
of the view controller being presented in storyboard or during its initalization.
|
||||
*/
|
||||
open static var menuDismissOnPush = true
|
||||
|
||||
/**
|
||||
The blur effect style of the menu if the menu's root view controller is a UITableViewController or UICollectionViewController.
|
||||
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
|
||||
Pod::Spec.new do |s|
|
||||
s.name = "SideMenu"
|
||||
s.version = "2.3.0"
|
||||
s.version = "3.0.0"
|
||||
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.
|
||||
|
||||
@@ -279,21 +279,23 @@
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0800;
|
||||
LastUpgradeCheck = 0820;
|
||||
LastUpgradeCheck = 0900;
|
||||
ORGANIZATIONNAME = jonkykong;
|
||||
TargetAttributes = {
|
||||
7B48A0D21DCB2487002990A1 = {
|
||||
CreatedOnToolsVersion = 8.0;
|
||||
LastSwiftMigration = 0900;
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
7B48A0E51DCB2487002990A1 = {
|
||||
CreatedOnToolsVersion = 8.0;
|
||||
LastSwiftMigration = 0900;
|
||||
ProvisioningStyle = Automatic;
|
||||
TestTargetID = 7B48A0D21DCB2487002990A1;
|
||||
};
|
||||
7B9DC9031DC6E8C1000D4007 = {
|
||||
CreatedOnToolsVersion = 8.0;
|
||||
LastSwiftMigration = 0820;
|
||||
LastSwiftMigration = 0900;
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
};
|
||||
@@ -493,7 +495,7 @@
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.jonkykong.Example;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 3.0;
|
||||
SWIFT_VERSION = 4.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@@ -507,7 +509,7 @@
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.jonkykong.Example;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 3.0;
|
||||
SWIFT_VERSION = 4.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
@@ -521,7 +523,7 @@
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.jonkykong.ExampleTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 3.0;
|
||||
SWIFT_VERSION = 4.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Example.app/Example";
|
||||
};
|
||||
name = Debug;
|
||||
@@ -536,7 +538,7 @@
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.jonkykong.ExampleTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 3.0;
|
||||
SWIFT_VERSION = 4.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Example.app/Example";
|
||||
};
|
||||
name = Release;
|
||||
@@ -550,7 +552,9 @@
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
@@ -558,7 +562,11 @@
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVES = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
@@ -604,7 +612,9 @@
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
@@ -612,7 +622,11 @@
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVES = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
@@ -660,7 +674,7 @@
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 3.0;
|
||||
SWIFT_VERSION = 4.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@@ -681,7 +695,7 @@
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.jonkykong.SideMenu;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SWIFT_VERSION = 3.0;
|
||||
SWIFT_VERSION = 4.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0820"
|
||||
LastUpgradeVersion = "0900"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
@@ -26,6 +26,7 @@
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
@@ -36,6 +37,7 @@
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
language = ""
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
|
||||
Reference in New Issue
Block a user