Compare commits

...

56 Commits

Author SHA1 Message Date
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
jonkykong fe52a16565 Updated README.md for pod. 2016-01-21 21:28:13 -08:00
jonkykong 7541ac0ef7 Fix for rare crash when app is backgrounded. 2016-01-21 21:11:46 -08:00
jonkykong 448faae85c Updated README.md for GitHub. 2016-01-15 11:49:50 -08:00
jonkykong 3b2e3454cf Updated README.md specifically for pods. 2016-01-15 11:46:27 -08:00
Jon Kent 4926721a42 Update README.md 2016-01-15 11:36:01 -08:00
jonkykong d51a826581 Updated example project to support iPad. 2016-01-15 11:27:46 -08:00
Jon Kent 2e5680bdea Update README.md 2016-01-15 11:21:17 -08:00
Jon Kent d37a30348d Update README.md 2016-01-15 11:16:44 -08:00
Jon Kent 3d53679a94 Update README.md 2016-01-14 20:37:13 -08:00
jonkykong 82f99a2cba Refactoring class structure and fix for viewWillAppear and viewDidAppear methods being called twice due to viewsControllers being added/removed from transition contexts. 2016-01-14 20:25:32 -08:00
Jon Kent 1a1123967d Update README.md 2016-01-14 20:22:26 -08:00
Jon Kent f945155814 Update README.md 2016-01-14 20:18:23 -08:00
23 changed files with 935 additions and 641 deletions
+2 -2
View File
@@ -1,5 +1,5 @@
PODS:
- SideMenu (0.1.4)
- SideMenu (1.0.3)
DEPENDENCIES:
- SideMenu (from `../`)
@@ -9,6 +9,6 @@ EXTERNAL SOURCES:
:path: ../
SPEC CHECKSUMS:
SideMenu: 09bc4ab16e392aea64caf052074efd63ef726b6a
SideMenu: 166ea23f143a8df84d0cf2170057793e26f0ba9e
COCOAPODS: 0.39.0
+3 -3
View File
@@ -1,7 +1,7 @@
{
"name": "SideMenu",
"version": "0.1.4",
"summary": "SideMenu is a simple and versatile side menu control.",
"version": "1.0.3",
"summary": "Simple side menu control in Swift inspired by Facebook. Right and Left sides. No coding required.",
"description": "SideMenu is a simple and versatile side menu control. It's highly customizable, but can also be implemented in storyboard without a single line of code. The are three standard animation styles to choose from along with several other options for further customization if desired. Just type SideMenuManager.menu... and code completion will show you everything you can customize.",
"homepage": "https://github.com/jonkykong/SideMenu",
"screenshots": "https://raw.githubusercontent.com/jonkykong/SideMenu/master/etc/Preview.gif",
@@ -11,7 +11,7 @@
},
"source": {
"git": "https://github.com/jonkykong/SideMenu.git",
"tag": "0.1.4"
"tag": "1.0.3"
},
"platforms": {
"ios": "8.0"
+2 -2
View File
@@ -1,5 +1,5 @@
PODS:
- SideMenu (0.1.4)
- SideMenu (1.0.3)
DEPENDENCIES:
- SideMenu (from `../`)
@@ -9,6 +9,6 @@ EXTERNAL SOURCES:
:path: ../
SPEC CHECKSUMS:
SideMenu: 09bc4ab16e392aea64caf052074efd63ef726b6a
SideMenu: 166ea23f143a8df84d0cf2170057793e26f0ba9e
COCOAPODS: 0.39.0
+30 -18
View File
@@ -7,13 +7,16 @@
objects = {
/* Begin PBXBuildFile section */
136BF9383BF2527B070BA5717DBA9D7F /* SideMenuManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBA288F42456ACA5ACB2CF80A5ADB09A /* SideMenuManager.swift */; };
3876451029D26E27CF659DA08BDBA909 /* UISideMenuNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE16A7DD7BD7A0F908B6D5D9660270A9 /* UISideMenuNavigationController.swift */; };
38E7197A7FA54FE6EA9474F7C71E9F16 /* SideMenu.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 80BEBB037771664BE7EDD19D9FA27CF9 /* SideMenu.bundle */; };
654B24B050E549972B44628F3D457134 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3E4E89230EF59BC255123B67864ACF77 /* Foundation.framework */; };
65CAFD32BFFE0B95AC0AD095EE320645 /* SideMenu-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 065251241095423AD65BFAC01FD1EFC6 /* SideMenu-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; };
6B68286B3E7B0CB2FE5C392902281CE1 /* SideMenu-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B967E268029BFFB818450080E0070B3 /* SideMenu-dummy.m */; };
8AA9CBD72AFC76A9039A8CF9CE6AC1B1 /* Pods-SideMenu_Tests-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 66BE2CB4DECBCC7820640717CC54B8B6 /* Pods-SideMenu_Tests-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; };
8AFB3DFF4F1A5C3F872B5980F29340A0 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3E4E89230EF59BC255123B67864ACF77 /* Foundation.framework */; };
92A9FE9F77CE2BA2AB924DB02E446C76 /* SideMenuManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B5455C690C42784185F70B2287AEA03 /* SideMenuManager.swift */; };
BBA8C724C31EBC571ED008721DC191C7 /* SideMenu-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B967E268029BFFB818450080E0070B3 /* SideMenu-dummy.m */; };
92E1730BB52E7F211ABDEA6120B3CBC0 /* UITableViewVibrantCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2F27B28C13E47CE793DCD786ABE0EBA0 /* UITableViewVibrantCell.swift */; };
B7BAC40F47999790437216BD070E4B0B /* SideMenuTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = B89C2BD310402418B97E451D4C32129D /* SideMenuTransition.swift */; };
D15E623D3EA1175C6ECE8E7F96F03F1B /* Pods-SideMenu_Example-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = F3BE17EC6C115709ADE0336BED36620B /* Pods-SideMenu_Example-dummy.m */; };
E8F227DB44F0E28D22866613E7466FE8 /* Pods-SideMenu_Example-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 6442E0432AE7807F49351AA4A2662BA0 /* Pods-SideMenu_Example-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; };
E93EFE2668CC8435D5DE5C232FA073A2 /* Pods-SideMenu_Tests-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 8894543047CFB1B0AD661193D079E3AF /* Pods-SideMenu_Tests-dummy.m */; };
@@ -49,12 +52,12 @@
02386539B907565FEF643C0A13DFD87A /* Pods-SideMenu_Example-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-SideMenu_Example-acknowledgements.plist"; sourceTree = "<group>"; };
065251241095423AD65BFAC01FD1EFC6 /* SideMenu-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SideMenu-umbrella.h"; sourceTree = "<group>"; };
080DBC3EDE1B586D2C363264990812F4 /* Pods_SideMenu_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SideMenu_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
0B5455C690C42784185F70B2287AEA03 /* SideMenuManager.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SideMenuManager.swift; sourceTree = "<group>"; };
167CC8746E153424CD7BBFBEB1FCC761 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
18CAD0A610A9A596A337B81EA6C75E82 /* SideMenu.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SideMenu.xcconfig; sourceTree = "<group>"; };
1B967E268029BFFB818450080E0070B3 /* SideMenu-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "SideMenu-dummy.m"; sourceTree = "<group>"; };
27F802E03D96716FDA4B8EB2F79D3442 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
283B837F6AEE40BE625A3B7BF3D629C4 /* Pods-SideMenu_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-SideMenu_Tests.debug.xcconfig"; sourceTree = "<group>"; };
2F27B28C13E47CE793DCD786ABE0EBA0 /* UITableViewVibrantCell.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = UITableViewVibrantCell.swift; sourceTree = "<group>"; };
365023FDA9AABF541F5F2BB4897DBC3D /* SideMenu-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SideMenu-prefix.pch"; sourceTree = "<group>"; };
3E4E89230EF59BC255123B67864ACF77 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; };
43082750426B0601530DDE0E513C028D /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@@ -71,9 +74,12 @@
9BD9EE073A93C4FF5537C83246116880 /* Pods_SideMenu_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SideMenu_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; };
9EF8186F4C9E56B047D9FD1A6E197E35 /* Pods-SideMenu_Tests-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-SideMenu_Tests-resources.sh"; sourceTree = "<group>"; };
A108300E5F9E66CC5B80C6D158F1A2B4 /* Pods-SideMenu_Tests-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-SideMenu_Tests-frameworks.sh"; sourceTree = "<group>"; };
B89C2BD310402418B97E451D4C32129D /* SideMenuTransition.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SideMenuTransition.swift; sourceTree = "<group>"; };
BA6428E9F66FD5A23C0A2E06ED26CD2F /* Podfile */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; };
CCFF9BC0A5E0AEB1B572E08B7BEB5179 /* Pods-SideMenu_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-SideMenu_Example.debug.xcconfig"; sourceTree = "<group>"; };
CE16A7DD7BD7A0F908B6D5D9660270A9 /* UISideMenuNavigationController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = UISideMenuNavigationController.swift; sourceTree = "<group>"; };
DB5D86340A731D1EBAB66BA453409E3B /* Pods-SideMenu_Tests-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-SideMenu_Tests-acknowledgements.plist"; sourceTree = "<group>"; };
DBA288F42456ACA5ACB2CF80A5ADB09A /* SideMenuManager.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SideMenuManager.swift; sourceTree = "<group>"; };
DDF7D1E1EB67D0EE22B89DBA15B34455 /* Pods-SideMenu_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-SideMenu_Tests.release.xcconfig"; sourceTree = "<group>"; };
DE75E648D267654445B52C8280543EFD /* Pods-SideMenu_Tests-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-SideMenu_Tests-acknowledgements.markdown"; sourceTree = "<group>"; };
F3BE17EC6C115709ADE0336BED36620B /* Pods-SideMenu_Example-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-SideMenu_Example-dummy.m"; sourceTree = "<group>"; };
@@ -126,17 +132,20 @@
34BEDB4240BF71B8086595F752B69042 /* SideMenu */ = {
isa = PBXGroup;
children = (
CB203E0872A2E52C8E99D04334ED5A9D /* Pod */,
A332AD7F12D36E82A15A055F8C320B9B /* Pod */,
E193E81FDAC4759729D7C787A23DAA84 /* Support Files */,
);
name = SideMenu;
path = ../..;
sourceTree = "<group>";
};
42F4169C1135EF13A1D0421D270BD2F4 /* Classes */ = {
46BA4BFCFF15B4CAA79C17449E551388 /* Classes */ = {
isa = PBXGroup;
children = (
0B5455C690C42784185F70B2287AEA03 /* SideMenuManager.swift */,
DBA288F42456ACA5ACB2CF80A5ADB09A /* SideMenuManager.swift */,
B89C2BD310402418B97E451D4C32129D /* SideMenuTransition.swift */,
CE16A7DD7BD7A0F908B6D5D9660270A9 /* UISideMenuNavigationController.swift */,
2F27B28C13E47CE793DCD786ABE0EBA0 /* UITableViewVibrantCell.swift */,
);
path = Classes;
sourceTree = "<group>";
@@ -190,6 +199,14 @@
name = Products;
sourceTree = "<group>";
};
A332AD7F12D36E82A15A055F8C320B9B /* Pod */ = {
isa = PBXGroup;
children = (
46BA4BFCFF15B4CAA79C17449E551388 /* Classes */,
);
path = Pod;
sourceTree = "<group>";
};
A94B9130D4AB3D2F2C9607150B2ADFB6 /* Pods-SideMenu_Example */ = {
isa = PBXGroup;
children = (
@@ -224,14 +241,6 @@
name = iOS;
sourceTree = "<group>";
};
CB203E0872A2E52C8E99D04334ED5A9D /* Pod */ = {
isa = PBXGroup;
children = (
42F4169C1135EF13A1D0421D270BD2F4 /* Classes */,
);
path = Pod;
sourceTree = "<group>";
};
E193E81FDAC4759729D7C787A23DAA84 /* Support Files */ = {
isa = PBXGroup;
children = (
@@ -298,7 +307,7 @@
isa = PBXNativeTarget;
buildConfigurationList = 9057029D293AD6EDC6335C1F302EE42B /* Build configuration list for PBXNativeTarget "SideMenu" */;
buildPhases = (
CA771114E7DB1C9C7E995AE8242C4F19 /* Sources */,
CE5E64CE3BE1AEA0E67C995DC80DB5F0 /* Sources */,
CD3D74524BB0D7B632CB6C81160DEEE1 /* Frameworks */,
FAC25EAFE8B8901BDEDD21DAC9DD45ED /* Resources */,
39BFA88BB58C8DFDF21395C7A6FD7D25 /* Headers */,
@@ -419,12 +428,15 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
CA771114E7DB1C9C7E995AE8242C4F19 /* Sources */ = {
CE5E64CE3BE1AEA0E67C995DC80DB5F0 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
BBA8C724C31EBC571ED008721DC191C7 /* SideMenu-dummy.m in Sources */,
92A9FE9F77CE2BA2AB924DB02E446C76 /* SideMenuManager.swift in Sources */,
6B68286B3E7B0CB2FE5C392902281CE1 /* SideMenu-dummy.m in Sources */,
136BF9383BF2527B070BA5717DBA9D7F /* SideMenuManager.swift in Sources */,
B7BAC40F47999790437216BD070E4B0B /* SideMenuTransition.swift in Sources */,
3876451029D26E27CF659DA08BDBA909 /* UISideMenuNavigationController.swift in Sources */,
92E1730BB52E7F211ABDEA6120B3CBC0 /* UITableViewVibrantCell.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
+1 -1
View File
@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>0.1.4</string>
<string>1.0.3</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
@@ -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 */,
@@ -492,6 +496,7 @@
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
@@ -506,6 +511,7 @@
MODULE_NAME = ExampleApp;
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
@@ -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/>
+22 -21
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"/>
@@ -219,7 +220,7 @@
<barButtonItem key="backBarButtonItem" title=" " id="FVG-mn-9HX"/>
<barButtonItem key="leftBarButtonItem" title="Left Menu" id="hjJ-My-xDQ">
<connections>
<segue destination="DuX-EW-0mP" kind="presentation" id="yoa-B2-xG5"/>
<segue destination="DuX-EW-0mP" kind="presentation" identifier="Test" id="yoa-B2-xG5"/>
</connections>
</barButtonItem>
<barButtonItem key="rightBarButtonItem" title="Right Menu" id="ckn-oO-hhX">
@@ -263,10 +264,10 @@
</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"/>
@@ -395,10 +396,10 @@
</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"/>
+3 -3
View File
@@ -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
}
}
+109 -564
View File
@@ -6,193 +6,116 @@
//
/* Example usage:
SideMenuManager.menuLeftNavigationController = storyboard!.instantiateViewControllerWithIdentifier("UILeftMenuNavigationController") as? UILeftMenuNavigationController
SideMenuManager.menuRightNavigationController = storyboard!.instantiateViewControllerWithIdentifier("UIRightMenuNavigationController") as? UIRightMenuNavigationController
SideMenuManager.menuAddPanToPresentGesture(toView: self.navigationController!.navigationBar)
// 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)
SideMenuManager.menuAddScreenEdgePanGesturesToPresent(toView: self.navigationController!.view)
*/
public class UISideMenuNavigationController: UINavigationController {
@IBInspectable public var leftSide:Bool = false {
didSet {
if isViewLoaded() { // suppress warnings
didSetSide()
}
}
}
override public func viewDidLoad() {
super.viewDidLoad()
didSetSide()
}
private func didSetSide() {
if leftSide {
SideMenuManager.menuLeftNavigationController = self
} else {
SideMenuManager.menuRightNavigationController = self
}
}
override public func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
// we had presented a view before, so lets dismiss ourselves as already acted upon
if view.hidden {
SideMenuManager.hideMenuComplete()
dismissViewControllerAnimated(false, completion: { () -> Void in
self.view.hidden = false
})
}
}
override public 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:
mainView.superview?.insertSubview(view, belowSubview: mainView)
case .MenuSlideIn, .MenuDissolveIn:
mainView.superview?.insertSubview(view, aboveSubview: SideMenuManager.tapView)
}
}
}
}
override public 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 g when the presented view is dismissed.
if !isBeingDismissed() {
view.hidden = true
SideMenuManager.hideMenuStart()
}
}
override public func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
// don't bother resizing if the view isn't visible
if view.hidden {
return
}
SideMenuManager.statusBarView?.hidden = true
coordinator.animateAlongsideTransition({ (context) -> Void in
SideMenuManager.presentMenuStart(forSize: size)
}) { (context) -> Void in
SideMenuManager.statusBarView?.hidden = false
}
}
override public func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let menuViewController: UINavigationController = SideMenuManager.presentDirection == .Left ? SideMenuManager.menuLeftNavigationController : SideMenuManager.menuRightNavigationController,
presentingViewController = menuViewController.presentingViewController as? UINavigationController {
presentingViewController.prepareForSegue(segue, sender: sender)
}
}
override public func shouldPerformSegueWithIdentifier(identifier: String, sender: AnyObject?) -> Bool {
if let menuViewController: UINavigationController = SideMenuManager.presentDirection == .Left ? SideMenuManager.menuLeftNavigationController : SideMenuManager.menuRightNavigationController,
presentingViewController = menuViewController.presentingViewController as? UINavigationController {
return presentingViewController.shouldPerformSegueWithIdentifier(identifier, sender: sender)
}
return super.shouldPerformSegueWithIdentifier(identifier, sender: sender)
}
override public func pushViewController(viewController: UIViewController, animated: Bool) {
if let menuViewController: UINavigationController = SideMenuManager.presentDirection == .Left ? SideMenuManager.menuLeftNavigationController : SideMenuManager.menuRightNavigationController {
if let presentingViewController = menuViewController.presentingViewController as? UINavigationController {
// to avoid overlapping dismiss & pop/push calls, create a transaction block where the menu
// is dismissed after showing the appropriate screen
CATransaction.begin()
CATransaction.setCompletionBlock( { () -> Void in
self.dismissViewControllerAnimated(true, completion: nil)
self.visibleViewController?.viewWillAppear(false) // Hack: force selection to get cleared on UITableViewControllers when reappearing using custom transitions
})
UIView.animateWithDuration(SideMenuManager.menuAnimationDismissDuration, animations: { () -> Void in
SideMenuManager.hideMenuStart()
})
if SideMenuManager.menuAllowPopIfPossible {
for subViewController in presentingViewController.viewControllers {
if subViewController.dynamicType == viewController.dynamicType {
presentingViewController.popToViewController(subViewController, animated: animated)
CATransaction.commit()
return
}
}
}
if !SideMenuManager.menuAllowPushOfSameClassTwice {
if presentingViewController.viewControllers.last?.dynamicType == viewController.dynamicType {
CATransaction.commit()
return
}
}
presentingViewController.pushViewController(viewController, animated: animated)
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.")
}
}
}
}
public class SideMenuManager: UIPercentDrivenInteractiveTransition, UIViewControllerAnimatedTransitioning, UIViewControllerTransitioningDelegate {
public class SideMenuManager {
public enum MenuPresentMode {
case MenuSlideIn
case ViewSlideOut
case ViewSlideInOut
case MenuDissolveIn
}
private static var presenting = false
private static var interactive = false
private static var presentDirection: UIRectEdge = .Left;
private static weak var tapView: UIView!
private static weak var statusBarView: UIView?
private static let singleton = SideMenuManager()
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()
}
}
// prevent instantiation
private override init() {}
/// The left menu.
public static var menuLeftNavigationController: UISideMenuNavigationController? {
willSet {
if menuLeftNavigationController != nil {
@@ -205,15 +128,20 @@ public class SideMenuManager: UIPercentDrivenInteractiveTransition, UIViewContro
didSet {
if let menuLeftNavigationController = menuLeftNavigationController {
let exitPanGesture = UIPanGestureRecognizer()
exitPanGesture.addTarget(self, action:"handleHideMenuPan:")
exitPanGesture.addTarget(SideMenuTransition.self, action:#selector(SideMenuTransition.handleHideMenuPan(_:)))
menuLeftNavigationController.view.addGestureRecognizer(exitPanGesture)
menuLeftNavigationController.transitioningDelegate = singleton
menuLeftNavigationController.transitioningDelegate = SideMenuTransition.singleton
menuLeftNavigationController.modalPresentationStyle = .OverFullScreen
if !menuLeftNavigationController.leftSide {
menuLeftNavigationController.leftSide = true
}
menuLeftSwipeToDismissGesture = exitPanGesture
updateMenuBlurIfNecessary()
}
}
}
/// The right menu.
public static var menuRightNavigationController: UISideMenuNavigationController? {
willSet {
if menuRightNavigationController != nil {
@@ -226,9 +154,13 @@ public class SideMenuManager: UIPercentDrivenInteractiveTransition, UIViewContro
didSet {
if let menuRightNavigationController = menuRightNavigationController {
let exitPanGesture = UIPanGestureRecognizer()
exitPanGesture.addTarget(self, action:"handleHideMenuPan:")
exitPanGesture.addTarget(SideMenuTransition.self, action:#selector(SideMenuTransition.handleHideMenuPan(_:)))
menuRightNavigationController.view.addGestureRecognizer(exitPanGesture)
menuRightNavigationController.transitioningDelegate = singleton
menuRightNavigationController.transitioningDelegate = SideMenuTransition.singleton
menuRightNavigationController.modalPresentationStyle = .OverFullScreen
if menuRightNavigationController.leftSide {
menuRightNavigationController.leftSide = false
}
menuRightSwipeToDismissGesture = exitPanGesture
updateMenuBlurIfNecessary()
}
@@ -295,19 +227,21 @@ public class SideMenuManager: UIPercentDrivenInteractiveTransition, UIViewContro
}
}
private static var viewControllerForPresentedMenu: UIViewController? {
get {
return menuLeftNavigationController?.presentingViewController != nil ? menuLeftNavigationController?.presentingViewController : menuRightNavigationController?.presentingViewController
}
}
/**
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(self, action:"handlePresentMenuPan:")
leftScreenEdgeGestureRecognizer.addTarget(SideMenuTransition.self, action:#selector(SideMenuTransition.handlePresentMenuLeftScreenEdge(_:)))
leftScreenEdgeGestureRecognizer.edges = .Left
leftScreenEdgeGestureRecognizer.cancelsTouchesInView = true
toView.addGestureRecognizer(leftScreenEdgeGestureRecognizer)
@@ -316,7 +250,7 @@ public class SideMenuManager: UIPercentDrivenInteractiveTransition, UIViewContro
if forMenu != .Left {
let rightScreenEdgeGestureRecognizer = UIScreenEdgePanGestureRecognizer()
rightScreenEdgeGestureRecognizer.addTarget(self, action:"handlePresentMenuPan:")
rightScreenEdgeGestureRecognizer.addTarget(SideMenuTransition.self, action:#selector(SideMenuTransition.handlePresentMenuRightScreenEdge(_:)))
rightScreenEdgeGestureRecognizer.edges = .Right
rightScreenEdgeGestureRecognizer.cancelsTouchesInView = true
toView.addGestureRecognizer(rightScreenEdgeGestureRecognizer)
@@ -326,407 +260,18 @@ public class SideMenuManager: UIPercentDrivenInteractiveTransition, UIViewContro
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(self, action:"handlePresentMenuPan:")
panGestureRecognizer.addTarget(SideMenuTransition.self, action:#selector(SideMenuTransition.handlePresentMenuPan(_:)))
toView.addGestureRecognizer(panGestureRecognizer)
return panGestureRecognizer
}
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 !interactive {
if translation.x == 0 {
return // not sure which way the user is swiping yet, so do nothing
}
if let edge = pan as? UIScreenEdgePanGestureRecognizer {
presentDirection = edge.edges == .Left ? .Left : .Right
} else {
presentDirection = translation.x > 0 ? .Left : .Right
}
if let menuViewController: UINavigationController = presentDirection == .Left ? menuLeftNavigationController : menuRightNavigationController {
interactive = true
if let visibleViewController = visibleViewController() {
visibleViewController.presentViewController(menuViewController, animated: true, completion: nil)
}
}
}
let direction:CGFloat = presentDirection == .Left ? 1 : -1
let distance = translation.x / 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 && presentDirection == .Right && menuLeftNavigationController != nil {
presentDirection = .Left
singleton.cancelInteractiveTransition()
viewControllerForPresentedMenu?.presentViewController(menuLeftNavigationController!, animated: true, completion: nil)
} else if distance < 0 && presentDirection == .Left && menuRightNavigationController != nil {
presentDirection = .Right
singleton.cancelInteractiveTransition()
viewControllerForPresentedMenu?.presentViewController(menuRightNavigationController!, animated: true, completion: nil)
} else {
singleton.updateInteractiveTransition(min(distance * direction, 1))
}
default:
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()
}
}
}
}
class func handleHideMenuPan(pan: UIPanGestureRecognizer) {
let translation = pan.translationInView(pan.view!)
let direction:CGFloat = presentDirection == .Left ? -1 : 1
let distance = translation.x / menuWidth * direction
switch (pan.state) {
case .Began:
interactive = true
viewControllerForPresentedMenu?.dismissViewControllerAnimated(true, completion: nil)
case .Changed:
singleton.updateInteractiveTransition(max(min(distance, 1), 0))
default:
interactive = false
let velocity = pan.velocityInView(pan.view!).x * direction
if velocity >= 100 || velocity >= -50 && distance >= 0.5 {
singleton.finishInteractiveTransition()
}
else {
singleton.cancelInteractiveTransition()
}
}
}
class func handleHideMenuTap(tap: UITapGestureRecognizer) {
viewControllerForPresentedMenu?.dismissViewControllerAnimated(true, completion: nil)
}
private class func visibleViewController() -> UIViewController? {
return getVisibleViewControllerFrom(UIApplication.sharedApplication().keyWindow?.rootViewController)
}
private class func getVisibleViewControllerFrom(viewController: UIViewController?) -> UIViewController? {
if let navigationController = viewController as? UINavigationController {
return getVisibleViewControllerFrom(navigationController.visibleViewController)
} else if let tabBarController = viewController as? UITabBarController {
return getVisibleViewControllerFrom(tabBarController.selectedViewController)
} else if let presentedViewController = viewController?.presentedViewController {
return getVisibleViewControllerFrom(presentedViewController)
}
return viewController
}
private class func hideMenuStart() {
let mainViewController = viewControllerForPresentedMenu!
let menuView = presentDirection == .Left ? menuLeftNavigationController!.view : menuRightNavigationController!.view
menuView.transform = CGAffineTransformIdentity
mainViewController.view.transform = CGAffineTransformIdentity
mainViewController.view.alpha = 1
tapView.frame = CGRectMake(0, 0, mainViewController.view.frame.width, mainViewController.view.frame.height)
menuView.frame.origin.y = 0
menuView.frame.size.width = menuWidth
menuView.frame.size.height = mainViewController.view.frame.height
statusBarView?.frame = UIApplication.sharedApplication().statusBarFrame
statusBarView?.alpha = 0
switch menuPresentMode {
case .ViewSlideOut:
menuView.alpha = 1 - menuAnimationFadeStrength
menuView.frame.origin.x = presentDirection == .Left ? 0 : mainViewController.view.frame.width - menuWidth
mainViewController.view.frame.origin.x = 0
menuView.transform = CGAffineTransformMakeScale(menuAnimationShrinkStrength, menuAnimationShrinkStrength)
case .MenuSlideIn:
menuView.alpha = 1
menuView.frame.origin.x = presentDirection == .Left ? -menuView.frame.width : mainViewController.view.frame.width
case .MenuDissolveIn:
menuView.alpha = 0
menuView.frame.origin.x = presentDirection == .Left ? 0 : mainViewController.view.frame.width - menuWidth
mainViewController.view.frame.origin.x = 0
}
}
private class func hideMenuComplete() {
let mainViewController = viewControllerForPresentedMenu!
let menuView = presentDirection == .Left ? menuLeftNavigationController!.view : menuRightNavigationController!.view
tapView.removeFromSuperview()
statusBarView?.removeFromSuperview()
mainViewController.view.motionEffects.removeAll()
mainViewController.view.layer.shadowOpacity = 0
menuView.layer.shadowOpacity = 0
NSNotificationCenter.defaultCenter().removeObserver(singleton)
if let topNavigationController = mainViewController as? UINavigationController {
topNavigationController.interactivePopGestureRecognizer!.enabled = true
}
}
private class func presentMenuStart(forSize size: CGSize = UIScreen.mainScreen().bounds.size) {
let mainViewController = viewControllerForPresentedMenu!
if let menuView = presentDirection == .Left ? menuLeftNavigationController?.view : menuRightNavigationController?.view {
menuView.transform = CGAffineTransformIdentity
mainViewController.view.transform = CGAffineTransformIdentity
menuView.frame.size.width = menuWidth
menuView.frame.size.height = size.height
menuView.frame.origin.x = presentDirection == .Left ? 0 : size.width - menuWidth
statusBarView?.frame = UIApplication.sharedApplication().statusBarFrame
statusBarView?.alpha = 1
switch menuPresentMode {
case .ViewSlideOut:
menuView.alpha = 1
let direction:CGFloat = presentDirection == .Left ? 1 : -1
mainViewController.view.frame.origin.x = direction * (menuView.frame.width)
mainViewController.view.layer.shadowColor = menuShadowColor.CGColor
mainViewController.view.layer.shadowRadius = menuShadowRadius
mainViewController.view.layer.shadowOpacity = menuShadowOpacity
mainViewController.view.layer.shadowOffset = CGSizeMake(0, 0)
case .MenuSlideIn, .MenuDissolveIn:
menuView.alpha = 1
menuView.layer.shadowColor = menuShadowColor.CGColor
menuView.layer.shadowRadius = menuShadowRadius
menuView.layer.shadowOpacity = menuShadowOpacity
menuView.layer.shadowOffset = CGSizeMake(0, 0)
mainViewController.view.frame = CGRectMake(0, 0, size.width, size.height)
mainViewController.view.transform = CGAffineTransformMakeScale(menuAnimationShrinkStrength, menuAnimationShrinkStrength)
mainViewController.view.alpha = 1 - menuAnimationFadeStrength
}
}
}
private class func presentMenuComplete() {
let mainViewController = viewControllerForPresentedMenu!
switch menuPresentMode {
case .MenuSlideIn, .MenuDissolveIn:
if menuParallaxStrength != 0 {
let horizontal = UIInterpolatingMotionEffect(keyPath: "center.x", type: .TiltAlongHorizontalAxis)
horizontal.minimumRelativeValue = -menuParallaxStrength
horizontal.maximumRelativeValue = menuParallaxStrength
let vertical = UIInterpolatingMotionEffect(keyPath: "center.y", type: .TiltAlongVerticalAxis)
vertical.minimumRelativeValue = -menuParallaxStrength
vertical.maximumRelativeValue = menuParallaxStrength
let group = UIMotionEffectGroup()
group.motionEffects = [horizontal, vertical]
mainViewController.view.addMotionEffect(group)
}
case .ViewSlideOut: break;
}
if let topNavigationController = mainViewController as? UINavigationController {
topNavigationController.interactivePopGestureRecognizer!.enabled = false
}
}
// MARK: UIViewControllerAnimatedTransitioning protocol methods
// animate a change from one viewcontroller to another
public func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
let statusBarStyle = SideMenuManager.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 {
container.backgroundColor = menuBackgroundColor
}
// create a tuple of our screens
let screens : (from:UIViewController, to:UIViewController) = (transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)!, transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)!)
// assign references to our menu view controller and the 'bottom' view controller from the tuple
// remember that our menuViewController will alternate between the from and to view controller depending if we're presenting or dismissing
let menuViewController = (!SideMenuManager.presenting ? screens.from : screens.to)
let topViewController = !SideMenuManager.presenting ? screens.to : screens.from
let menuView = menuViewController.view
let topView = topViewController.view
// prepare menu items to slide in
if SideMenuManager.presenting {
let tapView = UIView()
tapView.autoresizingMask = [.FlexibleHeight, .FlexibleWidth]
let exitPanGesture = UIPanGestureRecognizer()
exitPanGesture.addTarget(SideMenuManager.self, action:"handleHideMenuPan:")
let exitTapGesture = UITapGestureRecognizer()
exitTapGesture.addTarget(SideMenuManager.self, action: "handleHideMenuTap:")
tapView.addGestureRecognizer(exitPanGesture)
tapView.addGestureRecognizer(exitTapGesture)
// add the both views to our view controller
switch SideMenuManager.menuPresentMode {
case .ViewSlideOut:
container.addSubview(menuView)
container.addSubview(topView)
topView.addSubview(tapView)
case .MenuSlideIn, .MenuDissolveIn:
container.addSubview(topView)
container.addSubview(tapView)
container.addSubview(menuView)
}
if SideMenuManager.menuFadeStatusBar {
let blackBar = UIView()
if let menuShrinkBackgroundColor = SideMenuManager.menuAnimationBackgroundColor {
blackBar.backgroundColor = menuShrinkBackgroundColor
} else {
blackBar.backgroundColor = UIColor.blackColor()
}
blackBar.userInteractionEnabled = false
container.addSubview(blackBar)
SideMenuManager.statusBarView = blackBar
}
SideMenuManager.tapView = tapView
SideMenuManager.hideMenuStart() // offstage for interactive
NSNotificationCenter.defaultCenter().addObserver(SideMenuManager.singleton, selector:"applicationDidEnterBackgroundNotification", name: UIApplicationDidEnterBackgroundNotification, object: nil)
}
// perform the animation!
let duration = transitionDuration(transitionContext)
let options: UIViewAnimationOptions = SideMenuManager.interactive ? .CurveLinear : .CurveEaseInOut
UIView.animateWithDuration(duration, delay: 0, options: options, animations: { () -> Void in
if SideMenuManager.presenting {
SideMenuManager.presentMenuStart() // onstage items: slide in
}
else {
SideMenuManager.hideMenuStart()
}
}) { (finished) -> Void in
if SideMenuManager.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() {
if SideMenuManager.presenting {
SideMenuManager.hideMenuComplete()
}
transitionContext.completeTransition(false)
} else {
if SideMenuManager.presenting {
SideMenuManager.presentMenuComplete()
transitionContext.completeTransition(true)
switch SideMenuManager.menuPresentMode {
case .ViewSlideOut:
container.addSubview(topView)
case .MenuSlideIn, .MenuDissolveIn:
container.insertSubview(topView, atIndex: 0)
}
if let statusBarView = SideMenuManager.statusBarView {
container.bringSubviewToFront(statusBarView)
}
} else {
SideMenuManager.hideMenuComplete()
transitionContext.completeTransition(true)
menuView.removeFromSuperview()
}
}
}
}
// return how many seconds the transiton animation will take
public func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
return SideMenuManager.presenting ? SideMenuManager.menuAnimationPresentDuration : SideMenuManager.menuAnimationDismissDuration
}
// MARK: UIViewControllerTransitioningDelegate protocol methods
// return the animataor when presenting a viewcontroller
// rememeber that an animator (or animation controller) is any object that aheres to the UIViewControllerAnimatedTransitioning protocol
public func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
SideMenuManager.presenting = true
SideMenuManager.presentDirection = presented == SideMenuManager.menuLeftNavigationController ? .Left : .Right
return self
}
// return the animator used when dismissing from a viewcontroller
public func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
SideMenuManager.presenting = false
return self
}
public func interactionControllerForPresentation(animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
// if our interactive flag is true, return the transition manager object
// otherwise return nil
return SideMenuManager.interactive ? SideMenuManager.singleton : nil
}
public func interactionControllerForDismissal(animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
return SideMenuManager.interactive ? SideMenuManager.singleton : nil
}
func applicationDidEnterBackgroundNotification() {
if let menuViewController: UINavigationController = SideMenuManager.presentDirection == .Left ? SideMenuManager.menuLeftNavigationController : SideMenuManager.menuRightNavigationController {
SideMenuManager.hideMenuStart()
SideMenuManager.hideMenuComplete()
menuViewController.dismissViewControllerAnimated(false, completion: nil)
}
}
}
public class UITableViewVibrantCell: UITableViewCell {
private var vibrancyView:UIVisualEffectView = UIVisualEffectView()
private var vibrancySelectedBackgroundView:UIVisualEffectView = UIVisualEffectView()
private var defaultSelectedBackgroundView:UIView?
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
vibrancyView.frame = bounds
vibrancyView.autoresizingMask = [.FlexibleHeight, .FlexibleWidth]
for view in subviews {
vibrancyView.contentView.addSubview(view)
}
addSubview(vibrancyView)
let blurSelectionEffect = UIBlurEffect(style: .Light)
vibrancySelectedBackgroundView.effect = blurSelectionEffect
defaultSelectedBackgroundView = selectedBackgroundView
}
override public func layoutSubviews() {
super.layoutSubviews()
if !UIAccessibilityIsReduceTransparencyEnabled() && SideMenuManager.menuBlurEffectStyle != nil {
let blurEffect = UIBlurEffect(style: SideMenuManager.menuBlurEffectStyle!)
vibrancyView.effect = UIVibrancyEffect(forBlurEffect: blurEffect)
if selectedBackgroundView != nil && selectedBackgroundView != vibrancySelectedBackgroundView {
vibrancySelectedBackgroundView.contentView.addSubview(selectedBackgroundView!)
selectedBackgroundView = vibrancySelectedBackgroundView
}
} else {
vibrancyView.effect = nil
selectedBackgroundView = defaultSelectedBackgroundView
}
}
}
+435
View File
@@ -0,0 +1,435 @@
//
// SideMenuTransition.swift
// Pods
//
// Created by Jon Kent on 1/14/16.
//
//
import UIKit
internal class SideMenuTransition: UIPercentDrivenInteractiveTransition, UIViewControllerAnimatedTransitioning, UIViewControllerTransitioningDelegate {
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;
internal static weak var tapView: UIView!
internal static weak var statusBarView: UIView?
// prevent instantiation
private override init() {}
private class var viewControllerForPresentedMenu: UIViewController? {
get {
return SideMenuManager.menuLeftNavigationController?.presentingViewController != nil ? SideMenuManager.menuLeftNavigationController?.presentingViewController : SideMenuManager.menuRightNavigationController?.presentingViewController
}
}
private class var visibleViewController: UIViewController? {
get {
return getVisibleViewControllerFromViewController(UIApplication.sharedApplication().keyWindow?.rootViewController)
}
}
private class func getVisibleViewControllerFromViewController(viewController: UIViewController?) -> UIViewController? {
if let navigationController = viewController as? UINavigationController {
return getVisibleViewControllerFromViewController(navigationController.visibleViewController)
} else if let tabBarController = viewController as? UITabBarController {
return getVisibleViewControllerFromViewController(tabBarController.selectedViewController)
} else if let presentedViewController = viewController?.presentedViewController {
return getVisibleViewControllerFromViewController(presentedViewController)
}
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?
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
}
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()
}
}
}
class func handleHideMenuPan(pan: UIPanGestureRecognizer) {
let translation = pan.translationInView(pan.view!)
let direction:CGFloat = SideMenuTransition.presentDirection == .Left ? -1 : 1
let distance = translation.x / SideMenuManager.menuWidth * direction
switch (pan.state) {
case .Began:
singleton.interactive = true
viewControllerForPresentedMenu?.dismissViewControllerAnimated(true, completion: nil)
case .Changed:
singleton.updateInteractiveTransition(max(min(distance, 1), 0))
default:
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 {
singleton.cancelInteractiveTransition()
}
}
}
class func handleHideMenuTap(tap: UITapGestureRecognizer) {
viewControllerForPresentedMenu?.dismissViewControllerAnimated(true, completion: nil)
}
internal class func hideMenuStart() {
NSNotificationCenter.defaultCenter().removeObserver(SideMenuTransition.singleton)
let mainViewController = SideMenuTransition.viewControllerForPresentedMenu!
let menuView = SideMenuTransition.presentDirection == .Left ? SideMenuManager.menuLeftNavigationController!.view : SideMenuManager.menuRightNavigationController!.view
menuView.transform = CGAffineTransformIdentity
mainViewController.view.transform = CGAffineTransformIdentity
mainViewController.view.alpha = 1
SideMenuTransition.tapView.frame = CGRectMake(0, 0, mainViewController.view.frame.width, mainViewController.view.frame.height)
menuView.frame.origin.y = 0
menuView.frame.size.width = SideMenuManager.menuWidth
menuView.frame.size.height = mainViewController.view.frame.height
SideMenuTransition.statusBarView?.frame = UIApplication.sharedApplication().statusBarFrame
SideMenuTransition.statusBarView?.alpha = 0
switch SideMenuManager.menuPresentMode {
case .ViewSlideOut:
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.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
menuView.frame.origin.x = SideMenuTransition.presentDirection == .Left ? -menuView.frame.width : mainViewController.view.frame.width
case .MenuDissolveIn:
menuView.alpha = 0
menuView.frame.origin.x = SideMenuTransition.presentDirection == .Left ? 0 : mainViewController.view.frame.width - SideMenuManager.menuWidth
mainViewController.view.frame.origin.x = 0
}
}
internal class func hideMenuComplete() {
let mainViewController = SideMenuTransition.viewControllerForPresentedMenu!
let menuView = SideMenuTransition.presentDirection == .Left ? SideMenuManager.menuLeftNavigationController!.view : SideMenuManager.menuRightNavigationController!.view
SideMenuTransition.tapView.removeFromSuperview()
SideMenuTransition.statusBarView?.removeFromSuperview()
mainViewController.view.motionEffects.removeAll()
mainViewController.view.layer.shadowOpacity = 0
menuView.layer.shadowOpacity = 0
if let topNavigationController = mainViewController as? UINavigationController {
topNavigationController.interactivePopGestureRecognizer!.enabled = true
}
originalSuperview?.addSubview(mainViewController.view)
}
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!
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 {
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:#selector(SideMenuTransition.applicationDidEnterBackgroundNotification), name: UIApplicationDidEnterBackgroundNotification, object: nil)
let mainViewController = SideMenuTransition.viewControllerForPresentedMenu!
switch SideMenuManager.menuPresentMode {
case .MenuSlideIn, .MenuDissolveIn, .ViewSlideInOut:
if SideMenuManager.menuParallaxStrength != 0 {
let horizontal = UIInterpolatingMotionEffect(keyPath: "center.x", type: .TiltAlongHorizontalAxis)
horizontal.minimumRelativeValue = -SideMenuManager.menuParallaxStrength
horizontal.maximumRelativeValue = SideMenuManager.menuParallaxStrength
let vertical = UIInterpolatingMotionEffect(keyPath: "center.y", type: .TiltAlongVerticalAxis)
vertical.minimumRelativeValue = -SideMenuManager.menuParallaxStrength
vertical.maximumRelativeValue = SideMenuManager.menuParallaxStrength
let group = UIMotionEffectGroup()
group.motionEffects = [horizontal, vertical]
mainViewController.view.addMotionEffect(group)
}
case .ViewSlideOut: break;
}
if let topNavigationController = mainViewController as? UINavigationController {
topNavigationController.interactivePopGestureRecognizer!.enabled = false
}
}
// MARK: UIViewControllerAnimatedTransitioning protocol methods
// animate a change from one viewcontroller to another
internal func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
// 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 {
container.backgroundColor = menuBackgroundColor
}
// create a tuple of our screens
let screens : (from:UIViewController, to:UIViewController) = (transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)!, transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)!)
// assign references to our menu view controller and the 'bottom' view controller from the tuple
// remember that our menuViewController will alternate between the from and to view controller depending if we're presenting or dismissing
let menuViewController = (!presenting ? screens.from : screens.to)
let topViewController = !presenting ? screens.to : screens.from
let menuView = menuViewController.view
let topView = topViewController.view
// prepare menu items to slide in
if presenting {
let tapView = UIView()
tapView.autoresizingMask = [.FlexibleHeight, .FlexibleWidth]
let exitPanGesture = UIPanGestureRecognizer()
exitPanGesture.addTarget(SideMenuTransition.self, action:#selector(SideMenuTransition.handleHideMenuPan(_:)))
let exitTapGesture = UITapGestureRecognizer()
exitTapGesture.addTarget(SideMenuTransition.self, action: #selector(SideMenuTransition.handleHideMenuTap(_:)))
tapView.addGestureRecognizer(exitPanGesture)
tapView.addGestureRecognizer(exitTapGesture)
SideMenuTransition.tapView = tapView
SideMenuTransition.originalSuperview = topView.superview
// add the both views to our view controller
switch SideMenuManager.menuPresentMode {
case .ViewSlideOut:
container.addSubview(menuView)
container.addSubview(topView)
topView.addSubview(tapView)
case .MenuSlideIn, .MenuDissolveIn, .ViewSlideInOut:
container.addSubview(topView)
container.addSubview(tapView)
container.addSubview(menuView)
}
if SideMenuManager.menuFadeStatusBar {
let blackBar = UIView()
if let menuShrinkBackgroundColor = SideMenuManager.menuAnimationBackgroundColor {
blackBar.backgroundColor = menuShrinkBackgroundColor
} else {
blackBar.backgroundColor = UIColor.blackColor()
}
blackBar.userInteractionEnabled = false
container.addSubview(blackBar)
SideMenuTransition.statusBarView = blackBar
}
SideMenuTransition.hideMenuStart() // offstage for interactive
}
// perform the animation!
let duration = transitionDuration(transitionContext)
let options: UIViewAnimationOptions = interactive ? .CurveLinear : .CurveEaseInOut
UIView.animateWithDuration(duration, delay: 0, options: options, animations: { () -> Void in
if self.presenting {
SideMenuTransition.presentMenuStart() // onstage items: slide in
}
else {
SideMenuTransition.hideMenuStart()
}
}) { (finished) -> Void in
// 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)
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()
}
}
// return how many seconds the transiton animation will take
internal func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
return presenting ? SideMenuManager.menuAnimationPresentDuration : SideMenuManager.menuAnimationDismissDuration
}
// MARK: UIViewControllerTransitioningDelegate protocol methods
// 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
SideMenuTransition.presentDirection = presented == SideMenuManager.menuLeftNavigationController ? .Left : .Right
return self
}
// return the animator used when dismissing from a viewcontroller
internal func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
presenting = false
return self
}
internal func interactionControllerForPresentation(animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
// if our interactive flag is true, return the transition manager object
// otherwise return nil
return interactive ? SideMenuTransition.singleton : nil
}
internal func interactionControllerForDismissal(animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
return interactive ? SideMenuTransition.singleton : nil
}
internal func applicationDidEnterBackgroundNotification() {
if let menuViewController: UINavigationController = SideMenuTransition.presentDirection == .Left ? SideMenuManager.menuLeftNavigationController : SideMenuManager.menuRightNavigationController {
SideMenuTransition.hideMenuStart()
SideMenuTransition.hideMenuComplete()
menuViewController.dismissViewControllerAnimated(false, completion: nil)
}
}
}
@@ -0,0 +1,157 @@
//
// UISideMenuNavigationController.swift
//
// Created by Jon Kent on 1/14/16.
// Copyright © 2016 Jon Kent. All rights reserved.
//
import UIKit
public class UISideMenuNavigationController: UINavigationController {
public override func awakeFromNib() {
super.awakeFromNib()
// if this isn't set here, segues cause viewWillAppear and viewDidAppear to be called twice
// likely because the transition completes and the presentingViewController is added back
// into view for the default transition style.
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
didSetSide()
}
}
}
override public func viewDidLoad() {
super.viewDidLoad()
didSetSide()
}
private func didSetSide() {
if leftSide {
SideMenuManager.menuLeftNavigationController = self
} else {
SideMenuManager.menuRightNavigationController = self
}
}
override public func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
// we had presented a view before, so lets dismiss ourselves as already acted upon
if view.hidden {
SideMenuTransition.hideMenuComplete()
dismissViewControllerAnimated(false, completion: { () -> Void in
self.view.hidden = false
})
}
}
override public 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:
mainView.superview?.insertSubview(view, aboveSubview: SideMenuTransition.tapView)
}
}
}
}
override public 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 g when the presented view is dismissed.
if !isBeingDismissed() {
view.hidden = true
SideMenuTransition.hideMenuStart()
}
}
override public func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
// don't bother resizing if the view isn't visible
if view.hidden {
return
}
SideMenuTransition.statusBarView?.hidden = true
coordinator.animateAlongsideTransition({ (context) -> Void in
SideMenuTransition.presentMenuStart(forSize: size)
}) { (context) -> Void in
SideMenuTransition.statusBarView?.hidden = false
}
}
override public func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let menuViewController: UINavigationController = SideMenuTransition.presentDirection == .Left ? SideMenuManager.menuLeftNavigationController : SideMenuManager.menuRightNavigationController,
presentingViewController = menuViewController.presentingViewController as? UINavigationController {
presentingViewController.prepareForSegue(segue, sender: sender)
}
}
override public func shouldPerformSegueWithIdentifier(identifier: String, sender: AnyObject?) -> Bool {
if let menuViewController: UINavigationController = SideMenuTransition.presentDirection == .Left ? SideMenuManager.menuLeftNavigationController : SideMenuManager.menuRightNavigationController,
presentingViewController = menuViewController.presentingViewController as? UINavigationController {
return presentingViewController.shouldPerformSegueWithIdentifier(identifier, sender: sender)
}
return super.shouldPerformSegueWithIdentifier(identifier, sender: sender)
}
override public func pushViewController(viewController: UIViewController, animated: Bool) {
if let menuViewController: UINavigationController = SideMenuTransition.presentDirection == .Left ? SideMenuManager.menuLeftNavigationController : SideMenuManager.menuRightNavigationController {
if let presentingViewController = menuViewController.presentingViewController as? UINavigationController {
// to avoid overlapping dismiss & pop/push calls, create a transaction block where the menu
// is dismissed after showing the appropriate screen
CATransaction.begin()
CATransaction.setCompletionBlock( { () -> Void in
self.dismissViewControllerAnimated(true, completion: nil)
self.visibleViewController?.viewWillAppear(false) // Hack: force selection to get cleared on UITableViewControllers when reappearing using custom transitions
})
UIView.animateWithDuration(SideMenuManager.menuAnimationDismissDuration, animations: { () -> Void in
SideMenuTransition.hideMenuStart()
})
if SideMenuManager.menuAllowPopIfPossible {
for subViewController in presentingViewController.viewControllers {
if subViewController.dynamicType == viewController.dynamicType {
presentingViewController.popToViewController(subViewController, animated: animated)
CATransaction.commit()
return
}
}
}
if !SideMenuManager.menuAllowPushOfSameClassTwice {
if presentingViewController.viewControllers.last?.dynamicType == viewController.dynamicType {
CATransaction.commit()
return
}
}
presentingViewController.pushViewController(viewController, animated: animated)
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.")
}
}
}
}
+51
View File
@@ -0,0 +1,51 @@
//
// UITableViewVibrantCell.swift
// Pods
//
// Created by Jon Kent on 1/14/16.
//
//
import UIKit
public class UITableViewVibrantCell: UITableViewCell {
private var vibrancyView:UIVisualEffectView = UIVisualEffectView()
private var vibrancySelectedBackgroundView:UIVisualEffectView = UIVisualEffectView()
private var defaultSelectedBackgroundView:UIView?
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
vibrancyView.frame = bounds
vibrancyView.autoresizingMask = [.FlexibleHeight, .FlexibleWidth]
for view in subviews {
vibrancyView.contentView.addSubview(view)
}
addSubview(vibrancyView)
let blurSelectionEffect = UIBlurEffect(style: .Light)
vibrancySelectedBackgroundView.effect = blurSelectionEffect
defaultSelectedBackgroundView = selectedBackgroundView
}
override public func layoutSubviews() {
super.layoutSubviews()
// shouldn't be needed but backgroundColor is set to white on iPad:
backgroundColor = UIColor.clearColor()
if !UIAccessibilityIsReduceTransparencyEnabled() && SideMenuManager.menuBlurEffectStyle != nil {
let blurEffect = UIBlurEffect(style: SideMenuManager.menuBlurEffectStyle!)
vibrancyView.effect = UIVibrancyEffect(forBlurEffect: blurEffect)
if selectedBackgroundView != nil && selectedBackgroundView != vibrancySelectedBackgroundView {
vibrancySelectedBackgroundView.contentView.addSubview(selectedBackgroundView!)
selectedBackgroundView = vibrancySelectedBackgroundView
}
} else {
vibrancyView.effect = nil
selectedBackgroundView = defaultSelectedBackgroundView
}
}
}
+60 -24
View File
@@ -3,36 +3,59 @@
[![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)
## 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.
* There are three standard animation styles to choose from.
* It's highly customizable without needing to write tons of custom code.
* It supports continuous swiping between each side menu in a single gesture.
* Since it uses custom transitions it can be presented and dismissed the same as any other View Controller. This means **it can be implemented in storyboard without a single line of code**.
* **It can be implemented in storyboard without a single line of [code](#code-less-storyboard-implementation).**
* Four standard animation styles to choose from (even parallax if you want to get weird).
* Highly customizable without needing to write tons of custom code.
* Supports continuous swiping between side menus on boths sides in a single gesture.
* Global menu configuration. Set-up once and be done for all screens.
* Menus can be presented and dismissed the same as any other View Controller since this control uses custom transitions.
Check out the example project to see it in action.
Check out the example project or this [interactive demo](https://appetize.io/app/64a9v3e6b8c6f53zvn5pnny80m) to see it in action!
PS: It makes me happy when you ★ this repo.
[Demo via Appetizer](https://appetize.io/app/682u2wn33p1mgpzrtwyrxxz1w4)
![](etc/Preview.gif)
![](etc/SlideOut.gif)
![](etc/SlideIn.gif)
![](etc/Dissolve.gif)
![](etc/InOut.gif)
## Requirements
* Xcode 7 or higher
* iOS 8 or higher
* ARC
## Installation
SideMenu is available through [CocoaPods](http://cocoapods.org). To install
it, simply add the following line to your Podfile:
### CocoaPods
[CocoaPods](http://cocoapods.org) is a dependency manager for Cocoa projects. You can install it with the following command:
```bash
$ gem install cocoapods
```
To integrate SideMenu into your Xcode project using CocoaPods, specify it in your `Podfile`:
```ruby
pod "SideMenu"
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
use_frameworks!
pod 'SideMenu'
```
Then, run the following command:
```bash
$ pod install
```
## Usage
### Storyboard Implementation
### Code-less Storyboard Implementation
1. Create a Navigation Controller for a side menu. Set the custom class of the Navigation Controller to be `UISideMenuNavigationController` in the **Identity Inspector**. Create a Root View Controller for the Navigation Controller (shown as a UITableViewController below). Set up any Triggered Segues you want in that View Controller.
![](etc/Screenshot1.png)
@@ -44,16 +67,22 @@ pod "SideMenu"
That's it. *Note: you can only enable gestures in code.*
### Code Implementation
First:
```swift
import SideMenu
```
In your View Controller's `viewDidLoad` event, do something like this:
``` swift
// Define the menus
let leftMenuNavigationController = UIMenuNavigationController()
leftMenuNavigationController.leftSide = true
// UIMenuNavigationController is a subclass of UINavigationController, so do any additional configuration of it here like setting it's viewControllers.
SideMenuManager.menuLeftNavigationController = leftMenuNavigationController
let rightMenuNavigationController = UIMenuNavigationController()
// UIMenuNavigationController is a subclass of UINavigationController, so do any additional configuration of it here like setting it's viewControllers.
SideMenuManager.menuRightNavigationController = rightMenuNavigationController
let menuLeftNavigationController = UISideMenuNavigationController()
menuLeftNavigationController.leftSide = true
// UISideMenuNavigationController is a subclass of UINavigationController, so do any additional configuration of it here like setting its viewControllers.
SideMenuManager.menuLeftNavigationController = menuLeftNavigationController
let menuRightNavigationController = UISideMenuNavigationController()
// UISideMenuNavigationController is a subclass of UINavigationController, so do any additional configuration of it here like setting its viewControllers.
SideMenuManager.menuRightNavigationController = menuRightNavigationController
// 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!
@@ -75,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()
@@ -94,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 = "0.1.5"
s.summary = "Simple side menu control in Swift inspired by Facebook. Right and Left sides. No coding required."
s.version = "1.1.6"
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