Compare commits

..

49 Commits

Author SHA1 Message Date
jonkykong 1e6f192e28 Removed unneeded declaration. 2016-05-14 01:42:19 -07:00
jonkykong 771047f506 Updated pod spec and README for cocoa pods. 2016-05-14 01:37:08 -07:00
jonkykong c8ede5cd76 - Refactoring to simplify SideMenuManager logic.
- Fix for crashes by preventing side menus from being modified while actively presented.
2016-05-14 01:33:17 -07:00
jonkykong 335130ff7a Reversing README for github. 2016-05-02 16:57:04 -07:00
jonkykong 18fdc7f00e Merge tag '1.1.6'
* tag '1.1.6':
  Updates to README and podspec.
2016-05-02 16:56:42 -07:00
jonkykong e70f37f7b4 Updates to README and podspec. 2016-05-02 16:46:23 -07:00
jonkykong 21e873cc68 Logic and scope tweak. 2016-05-02 16:41:03 -07:00
Igor Savynskyi d81eb6277d variable marker corrections 2016-05-02 21:06:30 +03:00
Igor Savynskyi 2f6a1b8e6c code impruvements in solving issue with side menu wrong size 2016-05-02 15:23:42 +03:00
Ihor Savynskyi 7d766813fd fixing issue with view sizes for specific multitasking case
when running app with side menu on iPad device in Split View mode - it
takes wrong size for main view controller and side menu table view
controller (it is caused by taking sizes from UIScreen not from
UIApplication)
2016-04-27 16:40:34 +03:00
Jon Kent 78fad19e6f Update README.md 2016-04-23 22:55:54 -07:00
Jon Kent e91b9be969 Update README.md 2016-04-23 22:51:12 -07:00
Jon Kent 02252bc035 Update README.md 2016-04-22 15:00:39 -07:00
Jon Kent 4a658269a6 Merge pull request #15 from jonkykong/1.1.5
Reverse README for github.
2016-04-12 10:48:20 -07:00
jonkykong b5342a1c7c Merge tag '1.1.5'
* tag '1.1.5':
  Updated README and pod spec for cocoa pods.
  Added documentation comments for public methods.
  Animation support for parallax.
2016-04-12 10:46:10 -07:00
jonkykong bd2dc72a37 Reverse README for github. 2016-04-12 10:45:58 -07:00
jonkykong 58a1e19737 Updated README and pod spec for cocoa pods. 2016-04-12 10:43:00 -07:00
jonkykong 046c09765f Added documentation comments for public methods. 2016-04-12 10:39:17 -07:00
jonkykong dbeb741505 Animation support for parallax. 2016-04-12 10:37:43 -07:00
Jon Kent 2663b967d7 Update README.md 2016-04-08 14:17:40 -07:00
jonkykong 7a601b78b7 Reverse pod spec for github. 2016-04-08 01:13:50 -07:00
jonkykong 356f7c16e2 Merge tag '1.1.4'
* tag '1.1.4':
  One more logic tweak for animation smoothness.
2016-04-08 01:13:04 -07:00
jonkykong e512ae54be One more logic tweak for animation smoothness. 2016-04-08 01:07:07 -07:00
jonkykong 2029af7894 Updated pod spec version and README for cocoa pods. 2016-04-08 00:50:29 -07:00
jonkykong 0be7f0bc31 Bug workaround for iOS8 animations weirdly resetting. 2016-04-08 00:49:01 -07:00
Jon Kent d4732fbae5 Merge pull request #11 from jonkykong/1.1.2
Changed README back for github.
2016-04-07 18:02:20 -07:00
jonkykong 07f6dff8e8 Changed README back for github. 2016-04-07 17:58:23 -07:00
jonkykong a195757c1d Merge tag '1.1.2'
* tag '1.1.2':
  Removed unnecessary let.
2016-04-07 17:41:46 -07:00
jonkykong 68648ef3f1 Removed unnecessary let. 2016-04-07 17:40:30 -07:00
jonkykong fec44d0cc2 Updated README for cocoa pods. 2016-04-07 17:37:48 -07:00
jonkykong 4da251f6ea Upped pod spec. 2016-04-07 17:37:11 -07:00
jonkykong ddbc431d45 - Fix for edge gestures not firing on iOS 8.
- Improved logic around switching menus from rapid pans that can cause race condition crashes.
2016-04-07 17:37:02 -07:00
jonkykong 405a3ea56d Revert README back for github. 2016-04-06 00:07:29 -07:00
jonkykong 031e3bcfba Updated pod spec. 2016-04-06 00:02:57 -07:00
jonkykong c08c9a92ec Merge branch '1.1'
* 1.1:
  Updated README for cocoapods.org.
2016-04-06 00:01:19 -07:00
jonkykong f980f558b4 Updated README for cocoapods.org. 2016-04-06 00:00:37 -07:00
jonkykong b183c95efd Merge tag '1.1'
* tag '1.1':
  Correcting asset names and upping version as more appropriate for larger pod updates.
2016-04-05 23:50:01 -07:00
jonkykong 110eca43d3 Correcting asset names and upping version as more appropriate for larger pod updates. 2016-04-05 23:48:46 -07:00
jonkykong 8598050032 Renaming assets. 2016-04-05 23:45:23 -07:00
jonkykong 08e482c412 Updated podspec. 2016-04-05 23:36:06 -07:00
Jon Kent 8b833b9044 Update README.md 2016-04-05 23:08:47 -07:00
jonkykong b1f51cdcca Reduced asset sizes. 2016-04-05 23:05:44 -07:00
jonkykong 6a33fea711 Proper replacement of new property name and use of compiler warnings for rename. 2016-04-05 22:49:50 -07:00
jonkykong 2e5b209a0c Updated assets. 2016-04-05 22:17:48 -07:00
jonkykong 5463a48207 - Silencing warnings.
- Move to supported #selector method instead of strings.
- Updated example project to demonstrate new transition.
- Deprecated menuAnimationShrinkStrength in favor of better name menuAnimationTransformScaleFactor.
2016-04-05 20:35:20 -07:00
Yuval Tal ab5d7a17d6 Rename transition 2016-03-16 00:33:42 -04:00
Yuval Tal 339468f95d oops 2016-03-14 18:31:53 -04:00
Yuval Tal 933b9e93f3 Add new transition: ViewSlideOutUnder 2016-03-14 18:26:09 -04:00
jonkykong ab420fa769 Updated README.md for Github. 2016-01-21 21:30:41 -08:00
17 changed files with 428 additions and 228 deletions
@@ -14,6 +14,7 @@
84788C781C2B9F1E00C4DAF4 /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84788C741C2B9F1E00C4DAF4 /* MainViewController.swift */; };
84788C7B1C2B9FAB00C4DAF4 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84788C7A1C2B9FAB00C4DAF4 /* AppDelegate.swift */; };
84788C7D1C2BCDEB00C4DAF4 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 84788C7C1C2BCDEB00C4DAF4 /* Main.storyboard */; };
847D41DA1CB498BE0079C28F /* SideMenuTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847D41D91CB498BE0079C28F /* SideMenuTableView.swift */; };
A91D298EBD84AC675595CCA0 /* Pods_SideMenu_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B02FB2E5A68EB8A0DF6615E0 /* Pods_SideMenu_Example.framework */; };
AFA077A8EC0A5A74F8D6FF18 /* Pods_SideMenu_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8960F7A82F3CB64025C48B38 /* Pods_SideMenu_Tests.framework */; };
/* End PBXBuildFile section */
@@ -45,6 +46,7 @@
84788C741C2B9F1E00C4DAF4 /* MainViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainViewController.swift; sourceTree = "<group>"; };
84788C7A1C2B9FAB00C4DAF4 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
84788C7C1C2BCDEB00C4DAF4 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = "<group>"; };
847D41D91CB498BE0079C28F /* SideMenuTableView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SideMenuTableView.swift; sourceTree = "<group>"; };
8960F7A82F3CB64025C48B38 /* Pods_SideMenu_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SideMenu_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
A20C1DB98DEF29F3CE8D592A /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = "<group>"; };
B02FB2E5A68EB8A0DF6615E0 /* Pods_SideMenu_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SideMenu_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -109,6 +111,7 @@
84788C741C2B9F1E00C4DAF4 /* MainViewController.swift */,
84430B121C31F6D100858AA8 /* PresentedViewController.swift */,
84788C7C1C2BCDEB00C4DAF4 /* Main.storyboard */,
847D41D91CB498BE0079C28F /* SideMenuTableView.swift */,
607FACDE1AFB9204008FA782 /* LaunchScreen.xib */,
607FACD31AFB9204008FA782 /* Supporting Files */,
);
@@ -362,6 +365,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
847D41DA1CB498BE0079C28F /* SideMenuTableView.swift in Sources */,
84788C7B1C2B9FAB00C4DAF4 /* AppDelegate.swift in Sources */,
84430B131C31F6D100858AA8 /* PresentedViewController.swift in Sources */,
84788C781C2B9F1E00C4DAF4 /* MainViewController.swift in Sources */,
@@ -0,0 +1,21 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "saturn.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 573 KiB

+1
View File
@@ -37,6 +37,7 @@
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
+23 -22
View File
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="9531" systemVersion="15C50" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="yAA-s6-Bam">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10116" systemVersion="15E65" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="yAA-s6-Bam">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9529"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
</dependencies>
<scenes>
@@ -63,17 +63,6 @@
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" translatesAutoresizingMaskIntoConstraints="NO" id="KV2-tN-Aff">
<rect key="frame" x="20" y="37" width="280" height="29"/>
<segments>
<segment title="Slide In"/>
<segment title="Slide Out"/>
<segment title="Dissolve"/>
</segments>
<connections>
<action selector="changeSegment:" destination="QHN-nZ-kbB" eventType="valueChanged" id="xYG-CU-6tx"/>
</connections>
</segmentedControl>
<slider opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" minValue="0.0" maxValue="1" translatesAutoresizingMaskIntoConstraints="NO" id="Osf-2d-Znm">
<rect key="frame" x="18" y="234" width="284" height="31"/>
<color key="thumbTintColor" red="0.25098040700000002" green="0.0" blue="0.50196081400000003" alpha="1" colorSpace="calibratedRGB"/>
@@ -93,7 +82,7 @@
<action selector="changeSegment:" destination="QHN-nZ-kbB" eventType="valueChanged" id="5cv-dF-wWs"/>
</connections>
</segmentedControl>
<slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="0.001" minValue="0.001" maxValue="1" translatesAutoresizingMaskIntoConstraints="NO" id="Xp9-C5-Td1">
<slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="0.001" minValue="0.001" maxValue="2" translatesAutoresizingMaskIntoConstraints="NO" id="Xp9-C5-Td1">
<rect key="frame" x="18" y="368" width="284" height="31"/>
<color key="thumbTintColor" red="0.25098040700000002" green="0.0" blue="0.50196081400000003" alpha="1" colorSpace="calibratedRGB"/>
<connections>
@@ -113,8 +102,8 @@
<action selector="changeSlider:" destination="QHN-nZ-kbB" eventType="valueChanged" id="CFn-3w-HeP"/>
</connections>
</slider>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Menu Shrink Strength" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Tsg-30-YHs">
<rect key="frame" x="20" y="339" width="167" height="20.5"/>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Menu Transform Scale Factor" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Tsg-30-YHs">
<rect key="frame" x="20" y="339" width="225" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
@@ -144,6 +133,18 @@
<action selector="changeSwitch:" destination="QHN-nZ-kbB" eventType="valueChanged" id="yUy-FA-gYY"/>
</connections>
</switch>
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" translatesAutoresizingMaskIntoConstraints="NO" id="KV2-tN-Aff">
<rect key="frame" x="20" y="37" width="280" height="29"/>
<segments>
<segment title="Slide In"/>
<segment title="Slide Out"/>
<segment title="In + Out"/>
<segment title="Dissolve"/>
</segments>
<connections>
<action selector="changeSegment:" destination="QHN-nZ-kbB" eventType="valueChanged" id="xYG-CU-6tx"/>
</connections>
</segmentedControl>
</subviews>
<constraints>
<constraint firstItem="KV2-tN-Aff" firstAttribute="leading" secondItem="DMn-tw-NTB" secondAttribute="leading" constant="20" id="0Xw-7D-HJS"/>
@@ -263,14 +264,14 @@
</objects>
<point key="canvasLocation" x="961.875" y="8.4507042253521121"/>
</scene>
<!--Table View Controller-->
<!--Side Menu Table View-->
<scene sceneID="L2w-o7-jEN">
<objects>
<tableViewController id="V6g-oO-Tbm" sceneMemberID="viewController">
<tableViewController id="V6g-oO-Tbm" customClass="SideMenuTableView" customModule="SideMenu_Example" customModuleProvider="target" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" scrollEnabled="NO" dataMode="static" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="28" sectionFooterHeight="28" id="Dqh-bs-m2M">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="0.0" alpha="0.25134698280000001" colorSpace="calibratedWhite"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<color key="tintColor" red="0.0" green="0.47843137250000001" blue="1" alpha="1" colorSpace="calibratedRGB"/>
<inset key="separatorInset" minX="15" minY="0.0" maxX="8" maxY="0.0"/>
<view key="tableFooterView" contentMode="scaleToFill" id="vVB-ag-TnU">
@@ -395,14 +396,14 @@
</objects>
<point key="canvasLocation" x="961.875" y="698.23943661971828"/>
</scene>
<!--Table View Controller-->
<!--Side Menu Table View-->
<scene sceneID="l9t-dY-QwR">
<objects>
<tableViewController id="Ol4-YR-KUL" sceneMemberID="viewController">
<tableViewController id="Ol4-YR-KUL" customClass="SideMenuTableView" customModule="SideMenu_Example" customModuleProvider="target" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" scrollEnabled="NO" dataMode="static" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="28" sectionFooterHeight="28" id="49z-eA-JB7">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="0.0" alpha="0.25134698275862066" colorSpace="calibratedWhite"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<inset key="separatorInset" minX="0.0" minY="0.0" maxX="15" maxY="0.0"/>
<view key="tableFooterView" contentMode="scaleToFill" id="UXT-t2-k90">
<rect key="frame" x="0.0" y="132" width="320" height="0.0"/>
+4 -4
View File
@@ -28,7 +28,7 @@ class MainViewController: UIViewController {
// Define the menus
SideMenuManager.menuLeftNavigationController = storyboard!.instantiateViewControllerWithIdentifier("LeftMenuNavigationController") as? UISideMenuNavigationController
SideMenuManager.menuRightNavigationController = storyboard!.instantiateViewControllerWithIdentifier("RightMenuNavigationController") as? UISideMenuNavigationController
// Enable gestures. The left and/or right menus must be set up above for these to work.
// Note that these continue to work on the Navigation Controller independent of the View Controller it displays!
SideMenuManager.menuAddPanGestureToPresent(toView: self.navigationController!.navigationBar)
@@ -51,7 +51,7 @@ class MainViewController: UIViewController {
darknessSlider.value = Float(SideMenuManager.menuAnimationFadeStrength)
shadowOpacitySlider.value = Float(SideMenuManager.menuShadowOpacity)
shrinkFactorSlider.value = Float(SideMenuManager.menuAnimationShrinkStrength)
shrinkFactorSlider.value = Float(SideMenuManager.menuAnimationTransformScaleFactor)
screenWidthSlider.value = Float(SideMenuManager.menuWidth / view.frame.width)
blackOutStatusBar.on = SideMenuManager.menuFadeStatusBar
}
@@ -59,7 +59,7 @@ class MainViewController: UIViewController {
@IBAction private func changeSegment(segmentControl: UISegmentedControl) {
switch segmentControl {
case presentModeSegmentedControl:
let modes:[SideMenuManager.MenuPresentMode] = [.MenuSlideIn, .ViewSlideOut, .MenuDissolveIn]
let modes:[SideMenuManager.MenuPresentMode] = [.MenuSlideIn, .ViewSlideOut, .ViewSlideInOut, .MenuDissolveIn]
SideMenuManager.menuPresentMode = modes[segmentControl.selectedSegmentIndex]
case blurSegmentControl:
if segmentControl.selectedSegmentIndex == 0 {
@@ -79,7 +79,7 @@ class MainViewController: UIViewController {
case shadowOpacitySlider:
SideMenuManager.menuShadowOpacity = slider.value
case shrinkFactorSlider:
SideMenuManager.menuAnimationShrinkStrength = CGFloat(slider.value)
SideMenuManager.menuAnimationTransformScaleFactor = CGFloat(slider.value)
case screenWidthSlider:
SideMenuManager.menuWidth = view.frame.width * CGFloat(slider.value)
default: break;
+29
View File
@@ -0,0 +1,29 @@
//
// SideMenuTableView.swift
// SideMenu
//
// Created by Jon Kent on 4/5/16.
// Copyright © 2016 CocoaPods. All rights reserved.
//
import Foundation
import SideMenu
class SideMenuTableView: UITableViewController {
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
// this will be non-nil if a blur effect is applied
guard tableView.backgroundView == nil else {
return
}
// Set up a cool background image for demo purposes
let imageView = UIImageView(image: UIImage(named: "saturn"))
imageView.contentMode = .ScaleAspectFit
imageView.backgroundColor = UIColor.blackColor().colorWithAlphaComponent(0.2)
tableView.backgroundView = imageView
}
}
+161 -77
View File
@@ -21,147 +21,224 @@ public class SideMenuManager {
public enum MenuPresentMode {
case MenuSlideIn
case ViewSlideOut
case ViewSlideInOut
case MenuDissolveIn
}
private static var originalLeftMenuBackgroundColor: UIColor?
private static var originalRightMenuBackgroundColor: UIColor?
public static var menuPresentMode:MenuPresentMode = .ViewSlideOut
// 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.
There are four modes in MenuPresentMode:
- MenuSlideIn: Menu slides in over of the existing view.
- ViewSlideOut: The existing view slides out to reveal the menu.
- ViewSlideInOut: The existing view slides out while the menu slides in.
- MenuDissolveIn: The menu dissolves in over the existing view controller.
*/
public static var menuPresentMode: MenuPresentMode = .ViewSlideOut
/// Prevents the same view controller (or a view controller of the same class) from being pushed more than once. Defaults to true.
public static var menuAllowPushOfSameClassTwice = true
/// Pops to any view controller already in the navigation stack instead of the view controller being pushed if they share the same class. Defaults to false.
public static var menuAllowPopIfPossible = false
public static var menuWidth: CGFloat = max(round(min(UIScreen.mainScreen().bounds.width, UIScreen.mainScreen().bounds.height) * 0.75), 240)
/// 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((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
/// Duration of the animation when the menu is dismissed without gestures. Default is 0.35 seconds.
public static var menuAnimationDismissDuration = 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.
public static var menuAnimationFadeStrength: CGFloat = 0
public static var menuAnimationShrinkStrength: CGFloat = 1
/// The amount to scale the existing view controller or the menu view controller depending on the `menuPresentMode`. Default is 1 for no scaling. Less than 1 will shrink, greater than 1 will grow.
public static var menuAnimationTransformScaleFactor: CGFloat = 1
/// The background color behind menu animations. Depending on the animation settings this may not be visible. If `menuFadeStatusBar` is true, this color is used to fade it. Default is black.
public static var menuAnimationBackgroundColor: UIColor?
/// The shadow opacity around the menu view controller or existing view controller depending on the `menuPresentMode`. Default is 0.5 for 50% opacity.
public static var menuShadowOpacity: Float = 0.5
/// The shadow color around the menu view controller or existing view controller depending on the `menuPresentMode`. Default is black.
public static var menuShadowColor = UIColor.blackColor()
/// The radius of the shadow around the menu view controller or existing view controller depending on the `menuPresentMode`. Default is 5.
public static var menuShadowRadius: CGFloat = 5
/// The left menu swipe to dismiss gesture.
public static weak var menuLeftSwipeToDismissGesture: UIPanGestureRecognizer?
/// The right menu swipe to dismiss gesture.
public static weak var menuRightSwipeToDismissGesture: UIPanGestureRecognizer?
/// The strength of the parallax effect on the existing view controller. Does not apply to `menuPresentMode` when set to `ViewSlideOut`. Default is 0.
public static var menuParallaxStrength: Int = 0
/// Draws the `menuAnimationBackgroundColor` behind the status bar. Default is true.
public static var menuFadeStatusBar = true
// Note: if you want cells in a UITableViewController menu to look good, make them a subclass of UITableViewVibrantCell!
/// - Warning: Deprecated. Use `menuAnimationTransformScaleFactor` instead.
@available(*, deprecated, renamed="menuAnimationTransformScaleFactor")
public static var menuAnimationShrinkStrength: CGFloat {
get {
return menuAnimationTransformScaleFactor
}
set {
menuAnimationTransformScaleFactor = newValue
}
}
// prevent instantiation
private init() {}
/**
The blur effect style of the menu if the menu's root view controller is a UITableViewController or UICollectionViewController.
- Note: If you want cells in a UITableViewController menu to show vibrancy, make them a subclass of UITableViewVibrantCell.
*/
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:"handleHideMenuPan:")
menuLeftNavigationController.view.addGestureRecognizer(exitPanGesture)
menuLeftNavigationController.transitioningDelegate = SideMenuTransition.singleton
menuLeftNavigationController.modalPresentationStyle = .OverFullScreen
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:"handleHideMenuPan:")
menuRightNavigationController.view.addGestureRecognizer(exitPanGesture)
menuRightNavigationController.transitioningDelegate = SideMenuTransition.singleton
menuRightNavigationController.modalPresentationStyle = .OverFullScreen
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()
}
}
/**
Adds screen edge gestures to a view to present a menu.
- Parameter toView: The view to add gestures to.
- Parameter forMenu: The menu (left or right) you want to add a gesture for. If unspecified, gestures will be added for both sides.
- 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 {
let leftScreenEdgeGestureRecognizer = UIScreenEdgePanGestureRecognizer()
leftScreenEdgeGestureRecognizer.addTarget(SideMenuTransition.self, action:"handlePresentMenuPan:")
leftScreenEdgeGestureRecognizer.addTarget(SideMenuTransition.self, action:#selector(SideMenuTransition.handlePresentMenuLeftScreenEdge(_:)))
leftScreenEdgeGestureRecognizer.edges = .Left
leftScreenEdgeGestureRecognizer.cancelsTouchesInView = true
toView.addGestureRecognizer(leftScreenEdgeGestureRecognizer)
@@ -170,7 +247,7 @@ public class SideMenuManager {
if forMenu != .Left {
let rightScreenEdgeGestureRecognizer = UIScreenEdgePanGestureRecognizer()
rightScreenEdgeGestureRecognizer.addTarget(SideMenuTransition.self, action:"handlePresentMenuPan:")
rightScreenEdgeGestureRecognizer.addTarget(SideMenuTransition.self, action:#selector(SideMenuTransition.handlePresentMenuRightScreenEdge(_:)))
rightScreenEdgeGestureRecognizer.edges = .Right
rightScreenEdgeGestureRecognizer.cancelsTouchesInView = true
toView.addGestureRecognizer(rightScreenEdgeGestureRecognizer)
@@ -180,9 +257,16 @@ public class SideMenuManager {
return array
}
/**
Adds a pan edge gesture to a view to present menus.
- Parameter toView: The view to add a pan gesture to.
- Returns: The pan gesture added to `toView`.
*/
public class func menuAddPanGestureToPresent(toView toView: UIView) -> UIPanGestureRecognizer {
let panGestureRecognizer = UIPanGestureRecognizer()
panGestureRecognizer.addTarget(SideMenuTransition.self, action:"handlePresentMenuPan:")
panGestureRecognizer.addTarget(SideMenuTransition.self, action:#selector(SideMenuTransition.handlePresentMenuPan(_:)))
toView.addGestureRecognizer(panGestureRecognizer)
return panGestureRecognizer
+153 -112
View File
@@ -13,6 +13,7 @@ internal class SideMenuTransition: UIPercentDrivenInteractiveTransition, UIViewC
private var presenting = false
private var interactive = false
private static weak var originalSuperview: UIView?
private static var switchMenus = false
internal static let singleton = SideMenuTransition()
internal static var presentDirection: UIRectEdge = .Left;
@@ -46,62 +47,75 @@ internal class SideMenuTransition: UIPercentDrivenInteractiveTransition, UIViewC
return viewController
}
class func handlePresentMenuLeftScreenEdge(edge: UIScreenEdgePanGestureRecognizer) {
SideMenuTransition.presentDirection = .Left
handlePresentMenuPan(edge)
}
class func handlePresentMenuRightScreenEdge(edge: UIScreenEdgePanGestureRecognizer) {
SideMenuTransition.presentDirection = .Right
handlePresentMenuPan(edge)
}
class func handlePresentMenuPan(pan: UIPanGestureRecognizer) {
// how much distance have we panned in reference to the parent view?
if let view = viewControllerForPresentedMenu != nil ? viewControllerForPresentedMenu?.view : pan.view {
let transform = view.transform
view.transform = CGAffineTransformIdentity
let translation = pan.translationInView(pan.view!)
view.transform = transform
// do some math to translate this to a percentage based value
if !singleton.interactive {
if translation.x == 0 {
return // not sure which way the user is swiping yet, so do nothing
}
if let edge = pan as? UIScreenEdgePanGestureRecognizer {
SideMenuTransition.presentDirection = edge.edges == .Left ? .Left : .Right
} else {
SideMenuTransition.presentDirection = translation.x > 0 ? .Left : .Right
}
if let menuViewController: UINavigationController = SideMenuTransition.presentDirection == .Left ? SideMenuManager.menuLeftNavigationController : SideMenuManager.menuRightNavigationController {
singleton.interactive = true
if let visibleViewController = visibleViewController {
visibleViewController.presentViewController(menuViewController, animated: true, completion: nil)
}
}
guard let view = viewControllerForPresentedMenu != nil ? viewControllerForPresentedMenu?.view : pan.view else {
return
}
let transform = view.transform
view.transform = CGAffineTransformIdentity
let translation = pan.translationInView(pan.view!)
view.transform = transform
// do some math to translate this to a percentage based value
if !singleton.interactive {
if translation.x == 0 {
return // not sure which way the user is swiping yet, so do nothing
}
let direction:CGFloat = SideMenuTransition.presentDirection == .Left ? 1 : -1
let distance = translation.x / SideMenuManager.menuWidth
// now lets deal with different states that the gesture recognizer sends
switch (pan.state) {
case .Began, .Changed:
if pan is UIScreenEdgePanGestureRecognizer {
singleton.updateInteractiveTransition(min(distance * direction, 1))
} else if distance > 0 && SideMenuTransition.presentDirection == .Right && SideMenuManager.menuLeftNavigationController != nil {
SideMenuTransition.presentDirection = .Left
singleton.cancelInteractiveTransition()
viewControllerForPresentedMenu?.presentViewController(SideMenuManager.menuLeftNavigationController!, animated: true, completion: nil)
} else if distance < 0 && SideMenuTransition.presentDirection == .Left && SideMenuManager.menuRightNavigationController != nil {
SideMenuTransition.presentDirection = .Right
singleton.cancelInteractiveTransition()
viewControllerForPresentedMenu?.presentViewController(SideMenuManager.menuRightNavigationController!, animated: true, completion: nil)
} else {
singleton.updateInteractiveTransition(min(distance * direction, 1))
}
default:
singleton.interactive = false
view.transform = CGAffineTransformIdentity
let velocity = pan.velocityInView(pan.view!).x * direction
view.transform = transform
if velocity >= 100 || velocity >= -50 && abs(distance) >= 0.5 {
singleton.finishInteractiveTransition()
} else {
singleton.cancelInteractiveTransition()
if !(pan is UIScreenEdgePanGestureRecognizer) {
SideMenuTransition.presentDirection = translation.x > 0 ? .Left : .Right
}
if let menuViewController = SideMenuTransition.presentDirection == .Left ? SideMenuManager.menuLeftNavigationController : SideMenuManager.menuRightNavigationController,
visibleViewController = visibleViewController {
singleton.interactive = true
visibleViewController.presentViewController(menuViewController, animated: true, completion: nil)
}
}
let direction: CGFloat = SideMenuTransition.presentDirection == .Left ? 1 : -1
let distance = translation.x / SideMenuManager.menuWidth
// now lets deal with different states that the gesture recognizer sends
switch (pan.state) {
case .Began, .Changed:
if pan is UIScreenEdgePanGestureRecognizer {
singleton.updateInteractiveTransition(min(distance * direction, 1))
} else if distance > 0 && SideMenuTransition.presentDirection == .Right && SideMenuManager.menuLeftNavigationController != nil {
SideMenuTransition.presentDirection = .Left
switchMenus = true
singleton.cancelInteractiveTransition()
} else if distance < 0 && SideMenuTransition.presentDirection == .Left && SideMenuManager.menuRightNavigationController != nil {
SideMenuTransition.presentDirection = .Right
switchMenus = true
singleton.cancelInteractiveTransition()
} else {
singleton.updateInteractiveTransition(min(distance * direction, 1))
}
default:
singleton.interactive = false
view.transform = CGAffineTransformIdentity
let velocity = pan.velocityInView(pan.view!).x * direction
view.transform = transform
if velocity >= 100 || velocity >= -50 && abs(distance) >= 0.5 {
// bug workaround: animation briefly resets after call to finishInteractiveTransition() but before animateTransition completion is called.
if NSProcessInfo().operatingSystemVersion.majorVersion == 8 && singleton.percentComplete > 1 - CGFloat(FLT_EPSILON) {
singleton.updateInteractiveTransition(0.9999)
}
singleton.finishInteractiveTransition()
} else {
singleton.cancelInteractiveTransition()
}
}
}
@@ -122,9 +136,12 @@ internal class SideMenuTransition: UIPercentDrivenInteractiveTransition, UIViewC
singleton.interactive = false
let velocity = pan.velocityInView(pan.view!).x * direction
if velocity >= 100 || velocity >= -50 && distance >= 0.5 {
// bug workaround: animation briefly resets after call to finishInteractiveTransition() but before animateTransition completion is called.
if NSProcessInfo().operatingSystemVersion.majorVersion == 8 && singleton.percentComplete > 1 - CGFloat(FLT_EPSILON) {
singleton.updateInteractiveTransition(0.9999)
}
singleton.finishInteractiveTransition()
}
else {
} else {
singleton.cancelInteractiveTransition()
}
}
@@ -155,7 +172,12 @@ internal class SideMenuTransition: UIPercentDrivenInteractiveTransition, UIViewC
menuView.alpha = 1 - SideMenuManager.menuAnimationFadeStrength
menuView.frame.origin.x = SideMenuTransition.presentDirection == .Left ? 0 : mainViewController.view.frame.width - SideMenuManager.menuWidth
mainViewController.view.frame.origin.x = 0
menuView.transform = CGAffineTransformMakeScale(SideMenuManager.menuAnimationShrinkStrength, SideMenuManager.menuAnimationShrinkStrength)
menuView.transform = CGAffineTransformMakeScale(SideMenuManager.menuAnimationTransformScaleFactor, SideMenuManager.menuAnimationTransformScaleFactor)
case .ViewSlideInOut:
menuView.alpha = 1
menuView.frame.origin.x = SideMenuTransition.presentDirection == .Left ? -menuView.frame.width : mainViewController.view.frame.width
mainViewController.view.frame.origin.x = 0
case .MenuSlideIn:
menuView.alpha = 1
@@ -182,47 +204,60 @@ 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
}
let mainViewController = SideMenuTransition.viewControllerForPresentedMenu!
if let menuView = SideMenuTransition.presentDirection == .Left ? SideMenuManager.menuLeftNavigationController?.view : SideMenuManager.menuRightNavigationController?.view {
menuView.transform = CGAffineTransformIdentity
mainViewController.view.transform = CGAffineTransformIdentity
menuView.frame.size.width = SideMenuManager.menuWidth
menuView.frame.size.height = size.height
menuView.frame.origin.x = SideMenuTransition.presentDirection == .Left ? 0 : size.width - SideMenuManager.menuWidth
SideMenuTransition.statusBarView?.frame = UIApplication.sharedApplication().statusBarFrame
SideMenuTransition.statusBarView?.alpha = 1
menuView.transform = CGAffineTransformIdentity
mainViewController.view.transform = CGAffineTransformIdentity
menuView.frame.size.width = SideMenuManager.menuWidth
menuView.frame.size.height = size.height
menuView.frame.origin.x = SideMenuTransition.presentDirection == .Left ? 0 : size.width - SideMenuManager.menuWidth
SideMenuTransition.statusBarView?.frame = UIApplication.sharedApplication().statusBarFrame
SideMenuTransition.statusBarView?.alpha = 1
switch SideMenuManager.menuPresentMode {
switch SideMenuManager.menuPresentMode {
case .ViewSlideOut:
menuView.alpha = 1
let direction:CGFloat = SideMenuTransition.presentDirection == .Left ? 1 : -1
mainViewController.view.frame.origin.x = direction * (menuView.frame.width)
mainViewController.view.layer.shadowColor = SideMenuManager.menuShadowColor.CGColor
mainViewController.view.layer.shadowRadius = SideMenuManager.menuShadowRadius
mainViewController.view.layer.shadowOpacity = SideMenuManager.menuShadowOpacity
mainViewController.view.layer.shadowOffset = CGSizeMake(0, 0)
case .MenuSlideIn, .MenuDissolveIn:
menuView.alpha = 1
menuView.layer.shadowColor = SideMenuManager.menuShadowColor.CGColor
menuView.layer.shadowRadius = SideMenuManager.menuShadowRadius
menuView.layer.shadowOpacity = SideMenuManager.menuShadowOpacity
menuView.layer.shadowOffset = CGSizeMake(0, 0)
mainViewController.view.frame = CGRectMake(0, 0, size.width, size.height)
mainViewController.view.transform = CGAffineTransformMakeScale(SideMenuManager.menuAnimationShrinkStrength, SideMenuManager.menuAnimationShrinkStrength)
mainViewController.view.alpha = 1 - SideMenuManager.menuAnimationFadeStrength
}
case .ViewSlideOut:
menuView.alpha = 1
let direction:CGFloat = SideMenuTransition.presentDirection == .Left ? 1 : -1
mainViewController.view.frame.origin.x = direction * (menuView.frame.width)
mainViewController.view.layer.shadowColor = SideMenuManager.menuShadowColor.CGColor
mainViewController.view.layer.shadowRadius = SideMenuManager.menuShadowRadius
mainViewController.view.layer.shadowOpacity = SideMenuManager.menuShadowOpacity
mainViewController.view.layer.shadowOffset = CGSizeMake(0, 0)
case .ViewSlideInOut:
menuView.alpha = 1
menuView.layer.shadowColor = SideMenuManager.menuShadowColor.CGColor
menuView.layer.shadowRadius = SideMenuManager.menuShadowRadius
menuView.layer.shadowOpacity = SideMenuManager.menuShadowOpacity
menuView.layer.shadowOffset = CGSizeMake(0, 0)
let direction:CGFloat = SideMenuTransition.presentDirection == .Left ? 1 : -1
mainViewController.view.frame.origin.x = direction * (menuView.frame.width)
mainViewController.view.transform = CGAffineTransformMakeScale(SideMenuManager.menuAnimationTransformScaleFactor, SideMenuManager.menuAnimationTransformScaleFactor)
mainViewController.view.alpha = 1 - SideMenuManager.menuAnimationFadeStrength
case .MenuSlideIn, .MenuDissolveIn:
menuView.alpha = 1
menuView.layer.shadowColor = SideMenuManager.menuShadowColor.CGColor
menuView.layer.shadowRadius = SideMenuManager.menuShadowRadius
menuView.layer.shadowOpacity = SideMenuManager.menuShadowOpacity
menuView.layer.shadowOffset = CGSizeMake(0, 0)
mainViewController.view.frame = CGRectMake(0, 0, size.width, size.height)
mainViewController.view.transform = CGAffineTransformMakeScale(SideMenuManager.menuAnimationTransformScaleFactor, SideMenuManager.menuAnimationTransformScaleFactor)
mainViewController.view.alpha = 1 - SideMenuManager.menuAnimationFadeStrength
}
}
internal class func presentMenuComplete() {
NSNotificationCenter.defaultCenter().addObserver(SideMenuTransition.singleton, selector:"applicationDidEnterBackgroundNotification", name: UIApplicationDidEnterBackgroundNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(SideMenuTransition.singleton, selector:#selector(SideMenuTransition.applicationDidEnterBackgroundNotification), name: UIApplicationDidEnterBackgroundNotification, object: nil)
let mainViewController = SideMenuTransition.viewControllerForPresentedMenu!
switch SideMenuManager.menuPresentMode {
case .MenuSlideIn, .MenuDissolveIn:
case .MenuSlideIn, .MenuDissolveIn, .ViewSlideInOut:
if SideMenuManager.menuParallaxStrength != 0 {
let horizontal = UIInterpolatingMotionEffect(keyPath: "center.x", type: .TiltAlongHorizontalAxis)
horizontal.minimumRelativeValue = -SideMenuManager.menuParallaxStrength
@@ -248,8 +283,6 @@ internal class SideMenuTransition: UIPercentDrivenInteractiveTransition, UIViewC
// animate a change from one viewcontroller to another
internal func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
let statusBarStyle = SideMenuTransition.visibleViewController?.preferredStatusBarStyle()
// get reference to our fromView, toView and the container view that we should perform the transition in
let container = transitionContext.containerView()!
if let menuBackgroundColor = SideMenuManager.menuAnimationBackgroundColor {
@@ -272,9 +305,9 @@ internal class SideMenuTransition: UIPercentDrivenInteractiveTransition, UIViewC
let tapView = UIView()
tapView.autoresizingMask = [.FlexibleHeight, .FlexibleWidth]
let exitPanGesture = UIPanGestureRecognizer()
exitPanGesture.addTarget(SideMenuTransition.self, action:"handleHideMenuPan:")
exitPanGesture.addTarget(SideMenuTransition.self, action:#selector(SideMenuTransition.handleHideMenuPan(_:)))
let exitTapGesture = UITapGestureRecognizer()
exitTapGesture.addTarget(SideMenuTransition.self, action: "handleHideMenuTap:")
exitTapGesture.addTarget(SideMenuTransition.self, action: #selector(SideMenuTransition.handleHideMenuTap(_:)))
tapView.addGestureRecognizer(exitPanGesture)
tapView.addGestureRecognizer(exitTapGesture)
SideMenuTransition.tapView = tapView
@@ -287,7 +320,7 @@ internal class SideMenuTransition: UIPercentDrivenInteractiveTransition, UIViewC
container.addSubview(menuView)
container.addSubview(topView)
topView.addSubview(tapView)
case .MenuSlideIn, .MenuDissolveIn:
case .MenuSlideIn, .MenuDissolveIn, .ViewSlideInOut:
container.addSubview(topView)
container.addSubview(tapView)
container.addSubview(menuView)
@@ -319,36 +352,44 @@ internal class SideMenuTransition: UIPercentDrivenInteractiveTransition, UIViewC
SideMenuTransition.hideMenuStart()
}
}) { (finished) -> Void in
if SideMenuTransition.visibleViewController?.preferredStatusBarStyle() != statusBarStyle {
print("Warning: do not change the status bar style while using custom transitions or you risk transitions not properly completing and locking up the UI. See http://www.openradar.me/21961293")
}
// tell our transitionContext object that we've finished animating
if transitionContext.transitionWasCancelled() {
let viewControllerForPresentedMenu = SideMenuTransition.viewControllerForPresentedMenu
if self.presenting {
SideMenuTransition.hideMenuComplete()
} else {
SideMenuTransition.presentMenuComplete()
}
transitionContext.completeTransition(false)
} else {
if self.presenting {
SideMenuTransition.presentMenuComplete()
transitionContext.completeTransition(true)
switch SideMenuManager.menuPresentMode {
case .ViewSlideOut:
container.addSubview(topView)
case .MenuSlideIn, .MenuDissolveIn:
container.insertSubview(topView, atIndex: 0)
}
if let statusBarView = SideMenuTransition.statusBarView {
container.bringSubviewToFront(statusBarView)
}
} else {
SideMenuTransition.hideMenuComplete()
transitionContext.completeTransition(true)
menuView.removeFromSuperview()
if SideMenuTransition.switchMenus {
SideMenuTransition.switchMenus = false
viewControllerForPresentedMenu?.presentViewController(SideMenuTransition.presentDirection == .Left ? SideMenuManager.menuLeftNavigationController! : SideMenuManager.menuRightNavigationController!, animated: true, completion: nil)
}
return
}
if self.presenting {
SideMenuTransition.presentMenuComplete()
transitionContext.completeTransition(true)
switch SideMenuManager.menuPresentMode {
case .ViewSlideOut:
container.addSubview(topView)
case .MenuSlideIn, .MenuDissolveIn, .ViewSlideInOut:
container.insertSubview(topView, atIndex: 0)
}
if let statusBarView = SideMenuTransition.statusBarView {
container.bringSubviewToFront(statusBarView)
}
return
}
SideMenuTransition.hideMenuComplete()
transitionContext.completeTransition(true)
menuView.removeFromSuperview()
}
}
@@ -359,7 +400,7 @@ internal class SideMenuTransition: UIPercentDrivenInteractiveTransition, UIViewC
// MARK: UIViewControllerTransitioningDelegate protocol methods
// return the animataor when presenting a viewcontroller
// return the animator when presenting a viewcontroller
// rememeber that an animator (or animation controller) is any object that aheres to the UIViewControllerAnimatedTransitioning protocol
internal func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
self.presenting = true
@@ -9,6 +9,8 @@ import UIKit
public class UISideMenuNavigationController: UINavigationController {
internal var originalMenuBackgroundColor: UIColor?
public override func awakeFromNib() {
super.awakeFromNib()
@@ -18,9 +20,10 @@ public class UISideMenuNavigationController: UINavigationController {
modalPresentationStyle = .OverFullScreen
}
/// 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()
}
}
@@ -60,7 +63,7 @@ public class UISideMenuNavigationController: UINavigationController {
if !isBeingDismissed() {
if let mainView = presentingViewController?.view {
switch SideMenuManager.menuPresentMode {
case .ViewSlideOut:
case .ViewSlideOut, .ViewSlideInOut:
mainView.superview?.insertSubview(view, belowSubview: mainView)
case .MenuSlideIn, .MenuDissolveIn:
mainView.superview?.insertSubview(view, aboveSubview: SideMenuTransition.tapView)
@@ -147,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.")
}
}
}
+23 -7
View File
@@ -3,18 +3,27 @@
[![License](https://img.shields.io/cocoapods/l/SideMenu.svg?style=flat)](http://cocoapods.org/pods/SideMenu)
[![Platform](https://img.shields.io/cocoapods/p/SideMenu.svg?style=flat)](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.
## 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.
* **It can be implemented in storyboard without a single line of code.**
* Three standard animation styles to choose from.
* **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 each side menu in a single gesture.
* 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/5y7n2bk8f6jz58h92871udem54) to see it in action!
Check out the example project or this [interactive demo](https://appetize.io/app/64a9v3e6b8c6f53zvn5pnny80m) to see it in action!
![](etc/Preview.gif)
![](etc/SlideOut.gif)
![](etc/SlideIn.gif)
![](etc/Dissolve.gif)
![](etc/InOut.gif)
## Requirements
* iOS 8 or higher
@@ -95,7 +104,7 @@ menuWidth: CGFloat = max(round(min(UIScreen.mainScreen().bounds.width, UIScreen.
menuAnimationPresentDuration = 0.35
menuAnimationDismissDuration = 0.35
menuAnimationFadeStrength: CGFloat = 0
menuAnimationShrinkStrength: CGFloat = 1
menuAnimationTransformScaleFactor: CGFloat = 1
menuAnimationBackgroundColor: UIColor? = nil
menuShadowOpacity: Float = 0.5
menuShadowColor = UIColor.blackColor()
@@ -114,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.
+3 -3
View File
@@ -8,8 +8,8 @@
Pod::Spec.new do |s|
s.name = "SideMenu"
s.version = "1.0.3"
s.summary = "Simple side menu control in Swift inspired by Facebook. Right and Left sides. No coding required."
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.
# * Think: What does it do? Why did you write it? What is the focus?
@@ -21,7 +21,7 @@ Pod::Spec.new do |s|
DESC
s.homepage = "https://github.com/jonkykong/SideMenu"
s.screenshot = "https://raw.githubusercontent.com/jonkykong/SideMenu/master/etc/Preview.gif"
s.screenshots = [ "https://raw.githubusercontent.com/jonkykong/SideMenu/master/etc/SlideOut.gif", "https://raw.githubusercontent.com/jonkykong/SideMenu/master/etc/SlideIn.gif", "https://raw.githubusercontent.com/jonkykong/SideMenu/master/etc/Dissolve.gif", "https://raw.githubusercontent.com/jonkykong/SideMenu/master/etc/InOut.gif" ]
s.license = 'MIT'
s.author = { "jonkykong" => "jonk@jonked.com" }
s.source = { :git => "https://github.com/jonkykong/SideMenu.git", :tag => s.version.to_s }
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 764 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 438 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 MiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 663 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 605 KiB