├── .gitignore ├── Example ├── Classes │ └── .gitkeep ├── Podfile ├── RMPScrollingMenuBarController.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── xcshareddata │ │ └── xcschemes │ │ └── RMPScrollingMenuBarController-Example.xcscheme ├── RMPScrollingMenuBarController.xcworkspace │ └── contents.xcworkspacedata ├── RMPScrollingMenuBarController │ ├── Classes │ │ ├── .gitkeep │ │ ├── RMPAppDelegate.h │ │ ├── RMPAppDelegate.m │ │ ├── RMPPageViewController.h │ │ ├── RMPPageViewController.m │ │ ├── RMPViewController.h │ │ └── RMPViewController.m │ ├── Images.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── LaunchImage.launchimage │ │ │ └── Contents.json │ ├── RMPScrollingMenuBarController-Info.plist │ ├── RMPScrollingMenuBarController-Prefix.pch │ ├── en.lproj │ │ └── InfoPlist.strings │ └── main.m └── Tests │ ├── Tests-Info.plist │ ├── Tests-Prefix.pch │ ├── Tests.m │ └── en.lproj │ └── InfoPlist.strings ├── Example_Swift2 ├── Podfile ├── RMPScrollingMenuBarController.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── xcshareddata │ │ └── xcschemes │ │ └── RMPScrollingMenuBarController-Example.xcscheme ├── RMPScrollingMenuBarController.xcworkspace │ └── contents.xcworkspacedata ├── RMPScrollingMenuBarController │ ├── AppDelegate.swift │ ├── Base.lproj │ │ └── LaunchScreen.xib │ ├── Images.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Info.plist │ └── PageViewController.swift └── Tests │ ├── Info.plist │ └── Tests.swift ├── LICENSE ├── Pod ├── Assets │ └── .gitkeep └── Classes │ ├── .gitkeep │ ├── RMPScrollingMenuBar.h │ ├── RMPScrollingMenuBar.m │ ├── RMPScrollingMenuBarController.h │ ├── RMPScrollingMenuBarController.m │ ├── RMPScrollingMenuBarControllerAnimator.h │ ├── RMPScrollingMenuBarControllerAnimator.m │ ├── RMPScrollingMenuBarControllerTransition.h │ ├── RMPScrollingMenuBarControllerTransition.m │ ├── RMPScrollingMenuBarItem.h │ ├── RMPScrollingMenuBarItem.m │ ├── UIViewController+RMPScrollingMenuBarControllerHelper.h │ └── UIViewController+RMPScrollingMenuBarControllerHelper.m ├── README.md ├── RMPScrollingMenuBarController.podspec └── docs └── rmpscrollingmenubarcontroller.gif /.gitignore: -------------------------------------------------------------------------------- 1 | # OS X 2 | .DS_Store 3 | 4 | # Xcode 5 | build/ 6 | *.pbxuser 7 | !default.pbxuser 8 | *.mode1v3 9 | !default.mode1v3 10 | *.mode2v3 11 | !default.mode2v3 12 | *.perspectivev3 13 | !default.perspectivev3 14 | xcuserdata 15 | *.xccheckout 16 | profile 17 | *.moved-aside 18 | DerivedData 19 | *.hmap 20 | *.ipa 21 | 22 | # Bundler 23 | .bundle 24 | 25 | # We recommend against adding the Pods directory to your .gitignore. However 26 | # you should judge for yourself, the pros and cons are mentioned at: 27 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 28 | # 29 | # Note: if you ignore the Pods directory, make sure to uncomment 30 | # `pod install` in .travis.yml 31 | # 32 | Pods/ 33 | Podfile.lock 34 | -------------------------------------------------------------------------------- /Example/Classes/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recruit-mp/RMPScrollingMenuBarController/2de637e2e86d8fe986e6dd26cd2910c78739b95d/Example/Classes/.gitkeep -------------------------------------------------------------------------------- /Example/Podfile: -------------------------------------------------------------------------------- 1 | source 'https://github.com/CocoaPods/Specs.git' 2 | use_frameworks! 3 | 4 | target 'RMPScrollingMenuBarController', :exclusive => true do 5 | pod "RMPScrollingMenuBarController", :path => "../" 6 | end 7 | 8 | target 'Tests', :exclusive => true do 9 | pod "RMPScrollingMenuBarController", :path => "../" 10 | 11 | pod 'FBSnapshotTestCase' 12 | end 13 | -------------------------------------------------------------------------------- /Example/RMPScrollingMenuBarController.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 6003F58E195388D20070C39A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58D195388D20070C39A /* Foundation.framework */; }; 11 | 6003F590195388D20070C39A /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58F195388D20070C39A /* CoreGraphics.framework */; }; 12 | 6003F592195388D20070C39A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F591195388D20070C39A /* UIKit.framework */; }; 13 | 6003F598195388D20070C39A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6003F596195388D20070C39A /* InfoPlist.strings */; }; 14 | 6003F59A195388D20070C39A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F599195388D20070C39A /* main.m */; }; 15 | 6003F5A9195388D20070C39A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6003F5A8195388D20070C39A /* Images.xcassets */; }; 16 | 6003F5B0195388D20070C39A /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F5AF195388D20070C39A /* XCTest.framework */; }; 17 | 6003F5B1195388D20070C39A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58D195388D20070C39A /* Foundation.framework */; }; 18 | 6003F5B2195388D20070C39A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F591195388D20070C39A /* UIKit.framework */; }; 19 | 6003F5BA195388D20070C39A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6003F5B8195388D20070C39A /* InfoPlist.strings */; }; 20 | 6003F5BC195388D20070C39A /* Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F5BB195388D20070C39A /* Tests.m */; }; 21 | 923619241A5A3C3F00A3754E /* RMPAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 923619211A5A3C3F00A3754E /* RMPAppDelegate.m */; }; 22 | 923619251A5A3C3F00A3754E /* RMPViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 923619231A5A3C3F00A3754E /* RMPViewController.m */; }; 23 | 923619281A5A7E9100A3754E /* RMPPageViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 923619271A5A7E9100A3754E /* RMPPageViewController.m */; }; 24 | B3F3BD4A521683177F4A6A54 /* Pods_RMPScrollingMenuBarController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F3D95260CC24310220D239D6 /* Pods_RMPScrollingMenuBarController.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; 25 | BA82FA671DAD5D210640A226 /* Pods_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C063F9BDDBBC03193D8191E5 /* Pods_Tests.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; 26 | /* End PBXBuildFile section */ 27 | 28 | /* Begin PBXContainerItemProxy section */ 29 | 6003F5B3195388D20070C39A /* PBXContainerItemProxy */ = { 30 | isa = PBXContainerItemProxy; 31 | containerPortal = 6003F582195388D10070C39A /* Project object */; 32 | proxyType = 1; 33 | remoteGlobalIDString = 6003F589195388D20070C39A; 34 | remoteInfo = RMPScrollingMenuBarController; 35 | }; 36 | /* End PBXContainerItemProxy section */ 37 | 38 | /* Begin PBXFileReference section */ 39 | 13CAEB25BC5ABB658E4BB8EE /* Pods-Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Tests/Pods-Tests.debug.xcconfig"; sourceTree = ""; }; 40 | 2DB96FC0ECB7CE0221053665 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; 41 | 5093C0AB2CAB29372D4D2287 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; }; 42 | 6003F58A195388D20070C39A /* RMPScrollingMenuBarController.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RMPScrollingMenuBarController.app; sourceTree = BUILT_PRODUCTS_DIR; }; 43 | 6003F58D195388D20070C39A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 44 | 6003F58F195388D20070C39A /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 45 | 6003F591195388D20070C39A /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 46 | 6003F595195388D20070C39A /* RMPScrollingMenuBarController-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "RMPScrollingMenuBarController-Info.plist"; sourceTree = ""; }; 47 | 6003F597195388D20070C39A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 48 | 6003F599195388D20070C39A /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 49 | 6003F59B195388D20070C39A /* RMPScrollingMenuBarController-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "RMPScrollingMenuBarController-Prefix.pch"; sourceTree = ""; }; 50 | 6003F5A8195388D20070C39A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 51 | 6003F5AE195388D20070C39A /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 52 | 6003F5AF195388D20070C39A /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 53 | 6003F5B7195388D20070C39A /* Tests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Tests-Info.plist"; sourceTree = ""; }; 54 | 6003F5B9195388D20070C39A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 55 | 6003F5BB195388D20070C39A /* Tests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Tests.m; sourceTree = ""; }; 56 | 606FC2411953D9B200FFA9A0 /* Tests-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Tests-Prefix.pch"; sourceTree = ""; }; 57 | 923619201A5A3C3F00A3754E /* RMPAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RMPAppDelegate.h; path = RMPScrollingMenuBarController/Classes/RMPAppDelegate.h; sourceTree = SOURCE_ROOT; }; 58 | 923619211A5A3C3F00A3754E /* RMPAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RMPAppDelegate.m; path = RMPScrollingMenuBarController/Classes/RMPAppDelegate.m; sourceTree = SOURCE_ROOT; }; 59 | 923619221A5A3C3F00A3754E /* RMPViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RMPViewController.h; path = RMPScrollingMenuBarController/Classes/RMPViewController.h; sourceTree = SOURCE_ROOT; }; 60 | 923619231A5A3C3F00A3754E /* RMPViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RMPViewController.m; path = RMPScrollingMenuBarController/Classes/RMPViewController.m; sourceTree = SOURCE_ROOT; }; 61 | 923619261A5A7E9100A3754E /* RMPPageViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RMPPageViewController.h; path = RMPScrollingMenuBarController/Classes/RMPPageViewController.h; sourceTree = SOURCE_ROOT; }; 62 | 923619271A5A7E9100A3754E /* RMPPageViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RMPPageViewController.m; path = RMPScrollingMenuBarController/Classes/RMPPageViewController.m; sourceTree = SOURCE_ROOT; }; 63 | BCEAD3703A99B56D3E11E103 /* Pods-RMPScrollingMenuBarController.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RMPScrollingMenuBarController.debug.xcconfig"; path = "Pods/Target Support Files/Pods-RMPScrollingMenuBarController/Pods-RMPScrollingMenuBarController.debug.xcconfig"; sourceTree = ""; }; 64 | C063F9BDDBBC03193D8191E5 /* Pods_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 65 | C6503C50F46B65F76DB81523 /* Pods-RMPScrollingMenuBarController.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RMPScrollingMenuBarController.release.xcconfig"; path = "Pods/Target Support Files/Pods-RMPScrollingMenuBarController/Pods-RMPScrollingMenuBarController.release.xcconfig"; sourceTree = ""; }; 66 | F20DC15B0CC036E8660412DF /* Pods-Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-Tests/Pods-Tests.release.xcconfig"; sourceTree = ""; }; 67 | F3D95260CC24310220D239D6 /* Pods_RMPScrollingMenuBarController.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RMPScrollingMenuBarController.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 68 | F5BA9D9C65B83CF7166A3105 /* RMPScrollingMenuBarController.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = RMPScrollingMenuBarController.podspec; path = ../RMPScrollingMenuBarController.podspec; sourceTree = ""; }; 69 | /* End PBXFileReference section */ 70 | 71 | /* Begin PBXFrameworksBuildPhase section */ 72 | 6003F587195388D20070C39A /* Frameworks */ = { 73 | isa = PBXFrameworksBuildPhase; 74 | buildActionMask = 2147483647; 75 | files = ( 76 | 6003F590195388D20070C39A /* CoreGraphics.framework in Frameworks */, 77 | 6003F592195388D20070C39A /* UIKit.framework in Frameworks */, 78 | 6003F58E195388D20070C39A /* Foundation.framework in Frameworks */, 79 | B3F3BD4A521683177F4A6A54 /* Pods_RMPScrollingMenuBarController.framework in Frameworks */, 80 | ); 81 | runOnlyForDeploymentPostprocessing = 0; 82 | }; 83 | 6003F5AB195388D20070C39A /* Frameworks */ = { 84 | isa = PBXFrameworksBuildPhase; 85 | buildActionMask = 2147483647; 86 | files = ( 87 | 6003F5B0195388D20070C39A /* XCTest.framework in Frameworks */, 88 | 6003F5B2195388D20070C39A /* UIKit.framework in Frameworks */, 89 | 6003F5B1195388D20070C39A /* Foundation.framework in Frameworks */, 90 | BA82FA671DAD5D210640A226 /* Pods_Tests.framework in Frameworks */, 91 | ); 92 | runOnlyForDeploymentPostprocessing = 0; 93 | }; 94 | /* End PBXFrameworksBuildPhase section */ 95 | 96 | /* Begin PBXGroup section */ 97 | 6003F581195388D10070C39A = { 98 | isa = PBXGroup; 99 | children = ( 100 | 60FF7A9C1954A5C5007DD14C /* Podspec Metadata */, 101 | 6003F593195388D20070C39A /* RMPScrollingMenuBarController */, 102 | 6003F5B5195388D20070C39A /* Tests */, 103 | 6003F58C195388D20070C39A /* Frameworks */, 104 | 6003F58B195388D20070C39A /* Products */, 105 | ED37F408D7D1CB8F744576F6 /* Pods */, 106 | ); 107 | sourceTree = ""; 108 | }; 109 | 6003F58B195388D20070C39A /* Products */ = { 110 | isa = PBXGroup; 111 | children = ( 112 | 6003F58A195388D20070C39A /* RMPScrollingMenuBarController.app */, 113 | 6003F5AE195388D20070C39A /* Tests.xctest */, 114 | ); 115 | name = Products; 116 | sourceTree = ""; 117 | }; 118 | 6003F58C195388D20070C39A /* Frameworks */ = { 119 | isa = PBXGroup; 120 | children = ( 121 | 6003F58D195388D20070C39A /* Foundation.framework */, 122 | 6003F58F195388D20070C39A /* CoreGraphics.framework */, 123 | 6003F591195388D20070C39A /* UIKit.framework */, 124 | 6003F5AF195388D20070C39A /* XCTest.framework */, 125 | F3D95260CC24310220D239D6 /* Pods_RMPScrollingMenuBarController.framework */, 126 | C063F9BDDBBC03193D8191E5 /* Pods_Tests.framework */, 127 | ); 128 | name = Frameworks; 129 | sourceTree = ""; 130 | }; 131 | 6003F593195388D20070C39A /* RMPScrollingMenuBarController */ = { 132 | isa = PBXGroup; 133 | children = ( 134 | 923425831A4D66B6001E56FC /* Classes */, 135 | 6003F5A8195388D20070C39A /* Images.xcassets */, 136 | 6003F594195388D20070C39A /* Supporting Files */, 137 | ); 138 | path = RMPScrollingMenuBarController; 139 | sourceTree = ""; 140 | }; 141 | 6003F594195388D20070C39A /* Supporting Files */ = { 142 | isa = PBXGroup; 143 | children = ( 144 | 6003F595195388D20070C39A /* RMPScrollingMenuBarController-Info.plist */, 145 | 6003F596195388D20070C39A /* InfoPlist.strings */, 146 | 6003F599195388D20070C39A /* main.m */, 147 | 6003F59B195388D20070C39A /* RMPScrollingMenuBarController-Prefix.pch */, 148 | ); 149 | name = "Supporting Files"; 150 | sourceTree = ""; 151 | }; 152 | 6003F5B5195388D20070C39A /* Tests */ = { 153 | isa = PBXGroup; 154 | children = ( 155 | 6003F5BB195388D20070C39A /* Tests.m */, 156 | 6003F5B6195388D20070C39A /* Supporting Files */, 157 | ); 158 | path = Tests; 159 | sourceTree = ""; 160 | }; 161 | 6003F5B6195388D20070C39A /* Supporting Files */ = { 162 | isa = PBXGroup; 163 | children = ( 164 | 6003F5B7195388D20070C39A /* Tests-Info.plist */, 165 | 6003F5B8195388D20070C39A /* InfoPlist.strings */, 166 | 606FC2411953D9B200FFA9A0 /* Tests-Prefix.pch */, 167 | ); 168 | name = "Supporting Files"; 169 | sourceTree = ""; 170 | }; 171 | 60FF7A9C1954A5C5007DD14C /* Podspec Metadata */ = { 172 | isa = PBXGroup; 173 | children = ( 174 | F5BA9D9C65B83CF7166A3105 /* RMPScrollingMenuBarController.podspec */, 175 | 2DB96FC0ECB7CE0221053665 /* README.md */, 176 | 5093C0AB2CAB29372D4D2287 /* LICENSE */, 177 | ); 178 | name = "Podspec Metadata"; 179 | sourceTree = ""; 180 | }; 181 | 923425831A4D66B6001E56FC /* Classes */ = { 182 | isa = PBXGroup; 183 | children = ( 184 | 923619201A5A3C3F00A3754E /* RMPAppDelegate.h */, 185 | 923619211A5A3C3F00A3754E /* RMPAppDelegate.m */, 186 | 923619261A5A7E9100A3754E /* RMPPageViewController.h */, 187 | 923619271A5A7E9100A3754E /* RMPPageViewController.m */, 188 | 923619221A5A3C3F00A3754E /* RMPViewController.h */, 189 | 923619231A5A3C3F00A3754E /* RMPViewController.m */, 190 | ); 191 | name = Classes; 192 | path = ../Classes; 193 | sourceTree = ""; 194 | }; 195 | ED37F408D7D1CB8F744576F6 /* Pods */ = { 196 | isa = PBXGroup; 197 | children = ( 198 | BCEAD3703A99B56D3E11E103 /* Pods-RMPScrollingMenuBarController.debug.xcconfig */, 199 | C6503C50F46B65F76DB81523 /* Pods-RMPScrollingMenuBarController.release.xcconfig */, 200 | 13CAEB25BC5ABB658E4BB8EE /* Pods-Tests.debug.xcconfig */, 201 | F20DC15B0CC036E8660412DF /* Pods-Tests.release.xcconfig */, 202 | ); 203 | name = Pods; 204 | sourceTree = ""; 205 | }; 206 | /* End PBXGroup section */ 207 | 208 | /* Begin PBXNativeTarget section */ 209 | 6003F589195388D20070C39A /* RMPScrollingMenuBarController */ = { 210 | isa = PBXNativeTarget; 211 | buildConfigurationList = 6003F5BF195388D20070C39A /* Build configuration list for PBXNativeTarget "RMPScrollingMenuBarController" */; 212 | buildPhases = ( 213 | 50C8B00C5DF5A9F8A61780E2 /* Check Pods Manifest.lock */, 214 | 6003F586195388D20070C39A /* Sources */, 215 | 6003F587195388D20070C39A /* Frameworks */, 216 | 6003F588195388D20070C39A /* Resources */, 217 | A11710F6E36168D668D05A5B /* Copy Pods Resources */, 218 | 3393B09CF4B00531561F3908 /* Embed Pods Frameworks */, 219 | ); 220 | buildRules = ( 221 | ); 222 | dependencies = ( 223 | ); 224 | name = RMPScrollingMenuBarController; 225 | productName = RMPScrollingMenuBarController; 226 | productReference = 6003F58A195388D20070C39A /* RMPScrollingMenuBarController.app */; 227 | productType = "com.apple.product-type.application"; 228 | }; 229 | 6003F5AD195388D20070C39A /* Tests */ = { 230 | isa = PBXNativeTarget; 231 | buildConfigurationList = 6003F5C2195388D20070C39A /* Build configuration list for PBXNativeTarget "Tests" */; 232 | buildPhases = ( 233 | 165D113A3FCE7B83E8B30EDD /* Check Pods Manifest.lock */, 234 | 6003F5AA195388D20070C39A /* Sources */, 235 | 6003F5AB195388D20070C39A /* Frameworks */, 236 | 6003F5AC195388D20070C39A /* Resources */, 237 | BFDF308D2CA9EEE85AA5A60D /* Copy Pods Resources */, 238 | 3BAEBFBB6BDD20B3270B033A /* Embed Pods Frameworks */, 239 | ); 240 | buildRules = ( 241 | ); 242 | dependencies = ( 243 | 6003F5B4195388D20070C39A /* PBXTargetDependency */, 244 | ); 245 | name = Tests; 246 | productName = RMPScrollingMenuBarControllerTests; 247 | productReference = 6003F5AE195388D20070C39A /* Tests.xctest */; 248 | productType = "com.apple.product-type.bundle.unit-test"; 249 | }; 250 | /* End PBXNativeTarget section */ 251 | 252 | /* Begin PBXProject section */ 253 | 6003F582195388D10070C39A /* Project object */ = { 254 | isa = PBXProject; 255 | attributes = { 256 | CLASSPREFIX = RMP; 257 | LastUpgradeCheck = 0510; 258 | ORGANIZATIONNAME = kato; 259 | TargetAttributes = { 260 | 6003F5AD195388D20070C39A = { 261 | TestTargetID = 6003F589195388D20070C39A; 262 | }; 263 | }; 264 | }; 265 | buildConfigurationList = 6003F585195388D10070C39A /* Build configuration list for PBXProject "RMPScrollingMenuBarController" */; 266 | compatibilityVersion = "Xcode 3.2"; 267 | developmentRegion = English; 268 | hasScannedForEncodings = 0; 269 | knownRegions = ( 270 | en, 271 | Base, 272 | ); 273 | mainGroup = 6003F581195388D10070C39A; 274 | productRefGroup = 6003F58B195388D20070C39A /* Products */; 275 | projectDirPath = ""; 276 | projectRoot = ""; 277 | targets = ( 278 | 6003F589195388D20070C39A /* RMPScrollingMenuBarController */, 279 | 6003F5AD195388D20070C39A /* Tests */, 280 | ); 281 | }; 282 | /* End PBXProject section */ 283 | 284 | /* Begin PBXResourcesBuildPhase section */ 285 | 6003F588195388D20070C39A /* Resources */ = { 286 | isa = PBXResourcesBuildPhase; 287 | buildActionMask = 2147483647; 288 | files = ( 289 | 6003F5A9195388D20070C39A /* Images.xcassets in Resources */, 290 | 6003F598195388D20070C39A /* InfoPlist.strings in Resources */, 291 | ); 292 | runOnlyForDeploymentPostprocessing = 0; 293 | }; 294 | 6003F5AC195388D20070C39A /* Resources */ = { 295 | isa = PBXResourcesBuildPhase; 296 | buildActionMask = 2147483647; 297 | files = ( 298 | 6003F5BA195388D20070C39A /* InfoPlist.strings in Resources */, 299 | ); 300 | runOnlyForDeploymentPostprocessing = 0; 301 | }; 302 | /* End PBXResourcesBuildPhase section */ 303 | 304 | /* Begin PBXShellScriptBuildPhase section */ 305 | 165D113A3FCE7B83E8B30EDD /* Check Pods Manifest.lock */ = { 306 | isa = PBXShellScriptBuildPhase; 307 | buildActionMask = 2147483647; 308 | files = ( 309 | ); 310 | inputPaths = ( 311 | ); 312 | name = "Check Pods Manifest.lock"; 313 | outputPaths = ( 314 | ); 315 | runOnlyForDeploymentPostprocessing = 0; 316 | shellPath = /bin/sh; 317 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; 318 | showEnvVarsInLog = 0; 319 | }; 320 | 3393B09CF4B00531561F3908 /* Embed Pods Frameworks */ = { 321 | isa = PBXShellScriptBuildPhase; 322 | buildActionMask = 2147483647; 323 | files = ( 324 | ); 325 | inputPaths = ( 326 | ); 327 | name = "Embed Pods Frameworks"; 328 | outputPaths = ( 329 | ); 330 | runOnlyForDeploymentPostprocessing = 0; 331 | shellPath = /bin/sh; 332 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-RMPScrollingMenuBarController/Pods-RMPScrollingMenuBarController-frameworks.sh\"\n"; 333 | showEnvVarsInLog = 0; 334 | }; 335 | 3BAEBFBB6BDD20B3270B033A /* Embed Pods Frameworks */ = { 336 | isa = PBXShellScriptBuildPhase; 337 | buildActionMask = 2147483647; 338 | files = ( 339 | ); 340 | inputPaths = ( 341 | ); 342 | name = "Embed Pods Frameworks"; 343 | outputPaths = ( 344 | ); 345 | runOnlyForDeploymentPostprocessing = 0; 346 | shellPath = /bin/sh; 347 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Tests/Pods-Tests-frameworks.sh\"\n"; 348 | showEnvVarsInLog = 0; 349 | }; 350 | 50C8B00C5DF5A9F8A61780E2 /* Check Pods Manifest.lock */ = { 351 | isa = PBXShellScriptBuildPhase; 352 | buildActionMask = 2147483647; 353 | files = ( 354 | ); 355 | inputPaths = ( 356 | ); 357 | name = "Check Pods Manifest.lock"; 358 | outputPaths = ( 359 | ); 360 | runOnlyForDeploymentPostprocessing = 0; 361 | shellPath = /bin/sh; 362 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; 363 | showEnvVarsInLog = 0; 364 | }; 365 | A11710F6E36168D668D05A5B /* Copy Pods Resources */ = { 366 | isa = PBXShellScriptBuildPhase; 367 | buildActionMask = 2147483647; 368 | files = ( 369 | ); 370 | inputPaths = ( 371 | ); 372 | name = "Copy Pods Resources"; 373 | outputPaths = ( 374 | ); 375 | runOnlyForDeploymentPostprocessing = 0; 376 | shellPath = /bin/sh; 377 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-RMPScrollingMenuBarController/Pods-RMPScrollingMenuBarController-resources.sh\"\n"; 378 | showEnvVarsInLog = 0; 379 | }; 380 | BFDF308D2CA9EEE85AA5A60D /* Copy Pods Resources */ = { 381 | isa = PBXShellScriptBuildPhase; 382 | buildActionMask = 2147483647; 383 | files = ( 384 | ); 385 | inputPaths = ( 386 | ); 387 | name = "Copy Pods Resources"; 388 | outputPaths = ( 389 | ); 390 | runOnlyForDeploymentPostprocessing = 0; 391 | shellPath = /bin/sh; 392 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Tests/Pods-Tests-resources.sh\"\n"; 393 | showEnvVarsInLog = 0; 394 | }; 395 | /* End PBXShellScriptBuildPhase section */ 396 | 397 | /* Begin PBXSourcesBuildPhase section */ 398 | 6003F586195388D20070C39A /* Sources */ = { 399 | isa = PBXSourcesBuildPhase; 400 | buildActionMask = 2147483647; 401 | files = ( 402 | 923619251A5A3C3F00A3754E /* RMPViewController.m in Sources */, 403 | 923619241A5A3C3F00A3754E /* RMPAppDelegate.m in Sources */, 404 | 6003F59A195388D20070C39A /* main.m in Sources */, 405 | 923619281A5A7E9100A3754E /* RMPPageViewController.m in Sources */, 406 | ); 407 | runOnlyForDeploymentPostprocessing = 0; 408 | }; 409 | 6003F5AA195388D20070C39A /* Sources */ = { 410 | isa = PBXSourcesBuildPhase; 411 | buildActionMask = 2147483647; 412 | files = ( 413 | 6003F5BC195388D20070C39A /* Tests.m in Sources */, 414 | ); 415 | runOnlyForDeploymentPostprocessing = 0; 416 | }; 417 | /* End PBXSourcesBuildPhase section */ 418 | 419 | /* Begin PBXTargetDependency section */ 420 | 6003F5B4195388D20070C39A /* PBXTargetDependency */ = { 421 | isa = PBXTargetDependency; 422 | target = 6003F589195388D20070C39A /* RMPScrollingMenuBarController */; 423 | targetProxy = 6003F5B3195388D20070C39A /* PBXContainerItemProxy */; 424 | }; 425 | /* End PBXTargetDependency section */ 426 | 427 | /* Begin PBXVariantGroup section */ 428 | 6003F596195388D20070C39A /* InfoPlist.strings */ = { 429 | isa = PBXVariantGroup; 430 | children = ( 431 | 6003F597195388D20070C39A /* en */, 432 | ); 433 | name = InfoPlist.strings; 434 | sourceTree = ""; 435 | }; 436 | 6003F5B8195388D20070C39A /* InfoPlist.strings */ = { 437 | isa = PBXVariantGroup; 438 | children = ( 439 | 6003F5B9195388D20070C39A /* en */, 440 | ); 441 | name = InfoPlist.strings; 442 | sourceTree = ""; 443 | }; 444 | /* End PBXVariantGroup section */ 445 | 446 | /* Begin XCBuildConfiguration section */ 447 | 6003F5BD195388D20070C39A /* Debug */ = { 448 | isa = XCBuildConfiguration; 449 | buildSettings = { 450 | ALWAYS_SEARCH_USER_PATHS = NO; 451 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 452 | CLANG_CXX_LIBRARY = "libc++"; 453 | CLANG_ENABLE_MODULES = YES; 454 | CLANG_ENABLE_OBJC_ARC = YES; 455 | CLANG_WARN_BOOL_CONVERSION = YES; 456 | CLANG_WARN_CONSTANT_CONVERSION = YES; 457 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 458 | CLANG_WARN_EMPTY_BODY = YES; 459 | CLANG_WARN_ENUM_CONVERSION = YES; 460 | CLANG_WARN_INT_CONVERSION = YES; 461 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 462 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 463 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 464 | COPY_PHASE_STRIP = NO; 465 | GCC_C_LANGUAGE_STANDARD = gnu99; 466 | GCC_DYNAMIC_NO_PIC = NO; 467 | GCC_OPTIMIZATION_LEVEL = 0; 468 | GCC_PREPROCESSOR_DEFINITIONS = ( 469 | "DEBUG=1", 470 | "$(inherited)", 471 | ); 472 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 473 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 474 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 475 | GCC_WARN_UNDECLARED_SELECTOR = YES; 476 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 477 | GCC_WARN_UNUSED_FUNCTION = YES; 478 | GCC_WARN_UNUSED_VARIABLE = YES; 479 | IPHONEOS_DEPLOYMENT_TARGET = 7.1; 480 | ONLY_ACTIVE_ARCH = YES; 481 | SDKROOT = iphoneos; 482 | TARGETED_DEVICE_FAMILY = "1,2"; 483 | }; 484 | name = Debug; 485 | }; 486 | 6003F5BE195388D20070C39A /* Release */ = { 487 | isa = XCBuildConfiguration; 488 | buildSettings = { 489 | ALWAYS_SEARCH_USER_PATHS = NO; 490 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 491 | CLANG_CXX_LIBRARY = "libc++"; 492 | CLANG_ENABLE_MODULES = YES; 493 | CLANG_ENABLE_OBJC_ARC = YES; 494 | CLANG_WARN_BOOL_CONVERSION = YES; 495 | CLANG_WARN_CONSTANT_CONVERSION = YES; 496 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 497 | CLANG_WARN_EMPTY_BODY = YES; 498 | CLANG_WARN_ENUM_CONVERSION = YES; 499 | CLANG_WARN_INT_CONVERSION = YES; 500 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 501 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 502 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 503 | COPY_PHASE_STRIP = YES; 504 | ENABLE_NS_ASSERTIONS = NO; 505 | GCC_C_LANGUAGE_STANDARD = gnu99; 506 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 507 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 508 | GCC_WARN_UNDECLARED_SELECTOR = YES; 509 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 510 | GCC_WARN_UNUSED_FUNCTION = YES; 511 | GCC_WARN_UNUSED_VARIABLE = YES; 512 | IPHONEOS_DEPLOYMENT_TARGET = 7.1; 513 | SDKROOT = iphoneos; 514 | TARGETED_DEVICE_FAMILY = "1,2"; 515 | VALIDATE_PRODUCT = YES; 516 | }; 517 | name = Release; 518 | }; 519 | 6003F5C0195388D20070C39A /* Debug */ = { 520 | isa = XCBuildConfiguration; 521 | baseConfigurationReference = BCEAD3703A99B56D3E11E103 /* Pods-RMPScrollingMenuBarController.debug.xcconfig */; 522 | buildSettings = { 523 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 524 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 525 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 526 | GCC_PREFIX_HEADER = "RMPScrollingMenuBarController/RMPScrollingMenuBarController-Prefix.pch"; 527 | INFOPLIST_FILE = "RMPScrollingMenuBarController/RMPScrollingMenuBarController-Info.plist"; 528 | PRODUCT_NAME = "$(TARGET_NAME)"; 529 | WRAPPER_EXTENSION = app; 530 | }; 531 | name = Debug; 532 | }; 533 | 6003F5C1195388D20070C39A /* Release */ = { 534 | isa = XCBuildConfiguration; 535 | baseConfigurationReference = C6503C50F46B65F76DB81523 /* Pods-RMPScrollingMenuBarController.release.xcconfig */; 536 | buildSettings = { 537 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 538 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 539 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 540 | GCC_PREFIX_HEADER = "RMPScrollingMenuBarController/RMPScrollingMenuBarController-Prefix.pch"; 541 | INFOPLIST_FILE = "RMPScrollingMenuBarController/RMPScrollingMenuBarController-Info.plist"; 542 | PRODUCT_NAME = "$(TARGET_NAME)"; 543 | WRAPPER_EXTENSION = app; 544 | }; 545 | name = Release; 546 | }; 547 | 6003F5C3195388D20070C39A /* Debug */ = { 548 | isa = XCBuildConfiguration; 549 | baseConfigurationReference = 13CAEB25BC5ABB658E4BB8EE /* Pods-Tests.debug.xcconfig */; 550 | buildSettings = { 551 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/RMPScrollingMenuBarController.app/RMPScrollingMenuBarController"; 552 | FRAMEWORK_SEARCH_PATHS = ( 553 | "$(SDKROOT)/Developer/Library/Frameworks", 554 | "$(inherited)", 555 | "$(DEVELOPER_FRAMEWORKS_DIR)", 556 | ); 557 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 558 | GCC_PREFIX_HEADER = "Tests/Tests-Prefix.pch"; 559 | GCC_PREPROCESSOR_DEFINITIONS = ( 560 | "DEBUG=1", 561 | "$(inherited)", 562 | ); 563 | INFOPLIST_FILE = "Tests/Tests-Info.plist"; 564 | PRODUCT_NAME = "$(TARGET_NAME)"; 565 | TEST_HOST = "$(BUNDLE_LOADER)"; 566 | WRAPPER_EXTENSION = xctest; 567 | }; 568 | name = Debug; 569 | }; 570 | 6003F5C4195388D20070C39A /* Release */ = { 571 | isa = XCBuildConfiguration; 572 | baseConfigurationReference = F20DC15B0CC036E8660412DF /* Pods-Tests.release.xcconfig */; 573 | buildSettings = { 574 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/RMPScrollingMenuBarController.app/RMPScrollingMenuBarController"; 575 | FRAMEWORK_SEARCH_PATHS = ( 576 | "$(SDKROOT)/Developer/Library/Frameworks", 577 | "$(inherited)", 578 | "$(DEVELOPER_FRAMEWORKS_DIR)", 579 | ); 580 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 581 | GCC_PREFIX_HEADER = "Tests/Tests-Prefix.pch"; 582 | INFOPLIST_FILE = "Tests/Tests-Info.plist"; 583 | PRODUCT_NAME = "$(TARGET_NAME)"; 584 | TEST_HOST = "$(BUNDLE_LOADER)"; 585 | WRAPPER_EXTENSION = xctest; 586 | }; 587 | name = Release; 588 | }; 589 | /* End XCBuildConfiguration section */ 590 | 591 | /* Begin XCConfigurationList section */ 592 | 6003F585195388D10070C39A /* Build configuration list for PBXProject "RMPScrollingMenuBarController" */ = { 593 | isa = XCConfigurationList; 594 | buildConfigurations = ( 595 | 6003F5BD195388D20070C39A /* Debug */, 596 | 6003F5BE195388D20070C39A /* Release */, 597 | ); 598 | defaultConfigurationIsVisible = 0; 599 | defaultConfigurationName = Release; 600 | }; 601 | 6003F5BF195388D20070C39A /* Build configuration list for PBXNativeTarget "RMPScrollingMenuBarController" */ = { 602 | isa = XCConfigurationList; 603 | buildConfigurations = ( 604 | 6003F5C0195388D20070C39A /* Debug */, 605 | 6003F5C1195388D20070C39A /* Release */, 606 | ); 607 | defaultConfigurationIsVisible = 0; 608 | defaultConfigurationName = Release; 609 | }; 610 | 6003F5C2195388D20070C39A /* Build configuration list for PBXNativeTarget "Tests" */ = { 611 | isa = XCConfigurationList; 612 | buildConfigurations = ( 613 | 6003F5C3195388D20070C39A /* Debug */, 614 | 6003F5C4195388D20070C39A /* Release */, 615 | ); 616 | defaultConfigurationIsVisible = 0; 617 | defaultConfigurationName = Release; 618 | }; 619 | /* End XCConfigurationList section */ 620 | }; 621 | rootObject = 6003F582195388D10070C39A /* Project object */; 622 | } 623 | -------------------------------------------------------------------------------- /Example/RMPScrollingMenuBarController.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/RMPScrollingMenuBarController.xcodeproj/xcshareddata/xcschemes/RMPScrollingMenuBarController-Example.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 61 | 62 | 68 | 69 | 70 | 71 | 72 | 73 | 79 | 80 | 86 | 87 | 88 | 89 | 91 | 92 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /Example/RMPScrollingMenuBarController.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Example/RMPScrollingMenuBarController/Classes/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recruit-mp/RMPScrollingMenuBarController/2de637e2e86d8fe986e6dd26cd2910c78739b95d/Example/RMPScrollingMenuBarController/Classes/.gitkeep -------------------------------------------------------------------------------- /Example/RMPScrollingMenuBarController/Classes/RMPAppDelegate.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Recruit Marketing Partners Co.,Ltd. All rights reserved. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #import 22 | 23 | @interface RMPAppDelegate : UIResponder 24 | 25 | @property (strong, nonatomic) UIWindow *window; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /Example/RMPScrollingMenuBarController/Classes/RMPAppDelegate.m: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Recruit Marketing Partners Co.,Ltd. All rights reserved. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #import "RMPAppDelegate.h" 22 | #import "RMPScrollingMenuBarController.h" 23 | #import "RMPPageViewController.h" 24 | 25 | @interface RMPAppDelegate () 26 | 27 | @end 28 | 29 | @implementation RMPAppDelegate 30 | 31 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 32 | { 33 | 34 | [self setup]; 35 | 36 | return YES; 37 | } 38 | 39 | - (void)applicationWillResignActive:(UIApplication *)application 40 | { 41 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 42 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 43 | } 44 | 45 | - (void)applicationDidEnterBackground:(UIApplication *)application 46 | { 47 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 48 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 49 | } 50 | 51 | - (void)applicationWillEnterForeground:(UIApplication *)application 52 | { 53 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 54 | } 55 | 56 | - (void)applicationDidBecomeActive:(UIApplication *)application 57 | { 58 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 59 | } 60 | 61 | - (void)applicationWillTerminate:(UIApplication *)application 62 | { 63 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 64 | } 65 | 66 | #pragma mark - private methods 67 | - (void)setup 68 | { 69 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 70 | 71 | // Setup menu bar controller 72 | RMPScrollingMenuBarController* menuController = [[RMPScrollingMenuBarController alloc] init]; 73 | menuController.delegate = self; 74 | 75 | // Customize appearance of menu bar. 76 | menuController.view.backgroundColor = [UIColor whiteColor]; 77 | menuController.menuBar.indicatorColor = [UIColor blueColor]; 78 | //menuController.menuBar.style = RMPScrollingMenuBarStyleInfinitePaging; 79 | //menuController.menuBar.showsIndicator = NO; 80 | //menuController.menuBar.showsSeparatorLine = NO; 81 | 82 | // Set ViewControllers for menu bar controller 83 | NSMutableArray* viewControllers = [NSMutableArray array]; 84 | for(int i = 0; i < 10; i++){ 85 | RMPPageViewController* vc = [[RMPPageViewController alloc] init]; 86 | vc.view.backgroundColor = [UIColor colorWithWhite:0.3+0.05*i alpha:1.0]; 87 | vc.message = [NSString stringWithFormat:@"Message for No.%ld", (long)i+1]; 88 | [viewControllers addObject:vc]; 89 | } 90 | 91 | [menuController setViewControllers:viewControllers]; 92 | 93 | UINavigationController* naviController; 94 | naviController = [[UINavigationController alloc] initWithRootViewController:menuController]; 95 | self.window.rootViewController = naviController; 96 | [self.window makeKeyAndVisible]; 97 | } 98 | 99 | #pragma mark - RMPScrollingMenuBarControllerDelegate methods 100 | - (RMPScrollingMenuBarItem*)menuBarController:(RMPScrollingMenuBarController *)menuBarController 101 | menuBarItemAtIndex:(NSInteger)index 102 | { 103 | RMPScrollingMenuBarItem* item = [[RMPScrollingMenuBarItem alloc] init]; 104 | item.title = [NSString stringWithFormat:@"Title %02ld", (long)(index+1)]; 105 | 106 | // Customize appearance of menu bar item. 107 | UIButton* button = item.button; 108 | [button setTitleColor:[UIColor lightGrayColor] 109 | forState:UIControlStateNormal]; 110 | [button setTitleColor:[UIColor grayColor] 111 | forState:UIControlStateDisabled]; 112 | [button setTitleColor:[UIColor blueColor] 113 | forState:UIControlStateSelected]; 114 | return item; 115 | } 116 | 117 | - (void)menuBarController:(RMPScrollingMenuBarController *)menuBarController 118 | willSelectViewController:(UIViewController *)viewController 119 | { 120 | NSLog(@"will select %@", viewController); 121 | } 122 | 123 | - (void)menuBarController:(RMPScrollingMenuBarController *)menuBarController 124 | didSelectViewController:(UIViewController *)viewController 125 | { 126 | NSLog(@"did select %@", viewController); 127 | } 128 | 129 | - (void)menuBarController:(RMPScrollingMenuBarController *)menuBarController 130 | didCancelViewController:(UIViewController *)viewController 131 | { 132 | NSLog(@"did cancel %@", viewController); 133 | } 134 | 135 | @end 136 | -------------------------------------------------------------------------------- /Example/RMPScrollingMenuBarController/Classes/RMPPageViewController.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Recruit Marketing Partners Co.,Ltd. All rights reserved. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #import 22 | 23 | @interface RMPPageViewController : UIViewController 24 | 25 | @property (nonatomic, strong)NSString* message; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /Example/RMPScrollingMenuBarController/Classes/RMPPageViewController.m: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Recruit Marketing Partners Co.,Ltd. All rights reserved. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #import "RMPPageViewController.h" 22 | 23 | @implementation RMPPageViewController { 24 | UILabel* _messageLabel; 25 | } 26 | 27 | - (void)loadView 28 | { 29 | [super loadView]; 30 | 31 | CGRect f = self.view.bounds; 32 | f.size.height = 32; 33 | UILabel* label = [[UILabel alloc] initWithFrame:f]; 34 | _messageLabel = label; 35 | _messageLabel.numberOfLines = 0; 36 | _messageLabel.textColor = [UIColor whiteColor]; 37 | _messageLabel.textAlignment = NSTextAlignmentCenter; 38 | _messageLabel.center = CGPointMake(self.view.bounds.size.width*0.5, self.view.bounds.size.height*0.5); 39 | [self.view addSubview:_messageLabel]; 40 | 41 | if(_message){ 42 | _messageLabel.text = _message; 43 | } 44 | 45 | } 46 | 47 | - (void)setMessage:(NSString *)message 48 | { 49 | _message = message; 50 | _messageLabel.text = _message; 51 | } 52 | 53 | - (void)viewDidLayoutSubviews 54 | { 55 | _messageLabel.center = CGPointMake(self.view.bounds.size.width*0.5, self.view.bounds.size.height*0.5); 56 | } 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /Example/RMPScrollingMenuBarController/Classes/RMPViewController.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Recruit Marketing Partners Co.,Ltd. All rights reserved. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #import 22 | 23 | @interface RMPViewController : UIViewController 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /Example/RMPScrollingMenuBarController/Classes/RMPViewController.m: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Recruit Marketing Partners Co.,Ltd. All rights reserved. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #import "RMPViewController.h" 22 | 23 | @interface RMPViewController () 24 | 25 | @end 26 | 27 | @implementation RMPViewController 28 | 29 | - (void)viewDidLoad 30 | { 31 | [super viewDidLoad]; 32 | // Do any additional setup after loading the view, typically from a nib. 33 | } 34 | 35 | - (void)didReceiveMemoryWarning 36 | { 37 | [super didReceiveMemoryWarning]; 38 | // Dispose of any resources that can be recreated. 39 | } 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /Example/RMPScrollingMenuBarController/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "40x40", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "60x60", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "ipad", 20 | "size" : "29x29", 21 | "scale" : "1x" 22 | }, 23 | { 24 | "idiom" : "ipad", 25 | "size" : "29x29", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "ipad", 30 | "size" : "40x40", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "40x40", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "76x76", 41 | "scale" : "1x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "76x76", 46 | "scale" : "2x" 47 | } 48 | ], 49 | "info" : { 50 | "version" : 1, 51 | "author" : "xcode" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Example/RMPScrollingMenuBarController/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "7.0", 8 | "scale" : "2x" 9 | }, 10 | { 11 | "orientation" : "portrait", 12 | "idiom" : "iphone", 13 | "subtype" : "retina4", 14 | "extent" : "full-screen", 15 | "minimum-system-version" : "7.0", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "orientation" : "portrait", 20 | "idiom" : "ipad", 21 | "extent" : "full-screen", 22 | "minimum-system-version" : "7.0", 23 | "scale" : "1x" 24 | }, 25 | { 26 | "orientation" : "landscape", 27 | "idiom" : "ipad", 28 | "extent" : "full-screen", 29 | "minimum-system-version" : "7.0", 30 | "scale" : "1x" 31 | }, 32 | { 33 | "orientation" : "portrait", 34 | "idiom" : "ipad", 35 | "extent" : "full-screen", 36 | "minimum-system-version" : "7.0", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "orientation" : "landscape", 41 | "idiom" : "ipad", 42 | "extent" : "full-screen", 43 | "minimum-system-version" : "7.0", 44 | "scale" : "2x" 45 | } 46 | ], 47 | "info" : { 48 | "version" : 1, 49 | "author" : "xcode" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Example/RMPScrollingMenuBarController/RMPScrollingMenuBarController-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /Example/RMPScrollingMenuBarController/RMPScrollingMenuBarController-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #import 8 | 9 | #ifndef __IPHONE_5_0 10 | #warning "This project uses features only available in iOS SDK 5.0 and later." 11 | #endif 12 | 13 | #ifdef __OBJC__ 14 | #import 15 | #import 16 | #endif 17 | -------------------------------------------------------------------------------- /Example/RMPScrollingMenuBarController/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Example/RMPScrollingMenuBarController/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // RMPScrollingMenuBarController 4 | // 5 | // Created by kato on 12/26/2014. 6 | // Copyright (c) 2014 kato. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "RMPAppDelegate.h" 12 | 13 | int main(int argc, char * argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([RMPAppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Example/Tests/Tests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Example/Tests/Tests-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every test case source file. 5 | // 6 | 7 | #ifdef __OBJC__ 8 | 9 | #import 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /Example/Tests/Tests.m: -------------------------------------------------------------------------------- 1 | // 2 | // RMPScrollingMenuBarControllerTests.m 3 | // RMPScrollingMenuBarControllerTests 4 | // 5 | // Created by kato on 12/26/2014. 6 | // Copyright (c) 2014 kato. All rights reserved. 7 | // 8 | 9 | ${TEST_EXAMPLE} 10 | -------------------------------------------------------------------------------- /Example/Tests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Example_Swift2/Podfile: -------------------------------------------------------------------------------- 1 | source 'https://github.com/CocoaPods/Specs.git' 2 | use_frameworks! 3 | 4 | target 'RMPScrollingMenuBarController_Example', :exclusive => true do 5 | pod "RMPScrollingMenuBarController", :path => "../" 6 | end 7 | 8 | target 'RMPScrollingMenuBarController_Tests', :exclusive => true do 9 | pod "RMPScrollingMenuBarController", :path => "../" 10 | 11 | # Comment outed because maybe FBSnapshotTestCase isn't support Swift2. 12 | #pod 'FBSnapshotTestCase' 13 | end 14 | -------------------------------------------------------------------------------- /Example_Swift2/RMPScrollingMenuBarController.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD51AFB9204008FA782 /* AppDelegate.swift */; }; 11 | 607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDC1AFB9204008FA782 /* Images.xcassets */; }; 12 | 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */; }; 13 | 607FACEC1AFB9204008FA782 /* Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACEB1AFB9204008FA782 /* Tests.swift */; }; 14 | 8E4583BD1BC556FD00F1E691 /* PageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8E4583BC1BC556FD00F1E691 /* PageViewController.swift */; settings = {ASSET_TAGS = (); }; }; 15 | 9497AD4E7A6A71793ADEA9F5 /* Pods_RMPScrollingMenuBarController_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3C6D077B87E4A12CB4F9D5ED /* Pods_RMPScrollingMenuBarController_Tests.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; 16 | DE49E87A5E6793B0F456BF56 /* Pods_RMPScrollingMenuBarController_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D936C9D1FC0F8BB016C39A6B /* Pods_RMPScrollingMenuBarController_Example.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXContainerItemProxy section */ 20 | 607FACE61AFB9204008FA782 /* PBXContainerItemProxy */ = { 21 | isa = PBXContainerItemProxy; 22 | containerPortal = 607FACC81AFB9204008FA782 /* Project object */; 23 | proxyType = 1; 24 | remoteGlobalIDString = 607FACCF1AFB9204008FA782; 25 | remoteInfo = RMPScrollingMenuBarController; 26 | }; 27 | /* End PBXContainerItemProxy section */ 28 | 29 | /* Begin PBXFileReference section */ 30 | 07A9FD3E93752E722DD2FFE9 /* Pods-RMPScrollingMenuBarController_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RMPScrollingMenuBarController_Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-RMPScrollingMenuBarController_Tests/Pods-RMPScrollingMenuBarController_Tests.debug.xcconfig"; sourceTree = ""; }; 31 | 0AD8D4DE470C59FDE1F0A57F /* Pods-RMPScrollingMenuBarController_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RMPScrollingMenuBarController_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-RMPScrollingMenuBarController_Example/Pods-RMPScrollingMenuBarController_Example.release.xcconfig"; sourceTree = ""; }; 32 | 24E2E0F91024CEA4B53C9240 /* Pods-RMPScrollingMenuBarController_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RMPScrollingMenuBarController_Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-RMPScrollingMenuBarController_Tests/Pods-RMPScrollingMenuBarController_Tests.release.xcconfig"; sourceTree = ""; }; 33 | 31E6AFE865EA7185E4D2033D /* RMPScrollingMenuBarController.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = RMPScrollingMenuBarController.podspec; path = ../RMPScrollingMenuBarController.podspec; sourceTree = ""; }; 34 | 3755D3E87FB3D187DD6722A8 /* Pods-RMPScrollingMenuBarController_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RMPScrollingMenuBarController_Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-RMPScrollingMenuBarController_Example/Pods-RMPScrollingMenuBarController_Example.debug.xcconfig"; sourceTree = ""; }; 35 | 3C6D077B87E4A12CB4F9D5ED /* Pods_RMPScrollingMenuBarController_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RMPScrollingMenuBarController_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 36 | 40B515E2CFF65ADC6FE6CD7D /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; }; 37 | 607FACD01AFB9204008FA782 /* RMPScrollingMenuBarController_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RMPScrollingMenuBarController_Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 38 | 607FACD41AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 39 | 607FACD51AFB9204008FA782 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 40 | 607FACDC1AFB9204008FA782 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 41 | 607FACDF1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 42 | 607FACE51AFB9204008FA782 /* RMPScrollingMenuBarController_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RMPScrollingMenuBarController_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 43 | 607FACEA1AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 44 | 607FACEB1AFB9204008FA782 /* Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tests.swift; sourceTree = ""; }; 45 | 8E4583BC1BC556FD00F1E691 /* PageViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PageViewController.swift; sourceTree = ""; }; 46 | D936C9D1FC0F8BB016C39A6B /* Pods_RMPScrollingMenuBarController_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RMPScrollingMenuBarController_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 47 | E5820239FB35908D64DC2DBA /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; 48 | /* End PBXFileReference section */ 49 | 50 | /* Begin PBXFrameworksBuildPhase section */ 51 | 607FACCD1AFB9204008FA782 /* Frameworks */ = { 52 | isa = PBXFrameworksBuildPhase; 53 | buildActionMask = 2147483647; 54 | files = ( 55 | DE49E87A5E6793B0F456BF56 /* Pods_RMPScrollingMenuBarController_Example.framework in Frameworks */, 56 | ); 57 | runOnlyForDeploymentPostprocessing = 0; 58 | }; 59 | 607FACE21AFB9204008FA782 /* Frameworks */ = { 60 | isa = PBXFrameworksBuildPhase; 61 | buildActionMask = 2147483647; 62 | files = ( 63 | 9497AD4E7A6A71793ADEA9F5 /* Pods_RMPScrollingMenuBarController_Tests.framework in Frameworks */, 64 | ); 65 | runOnlyForDeploymentPostprocessing = 0; 66 | }; 67 | /* End PBXFrameworksBuildPhase section */ 68 | 69 | /* Begin PBXGroup section */ 70 | 17F8A3C397F1EA806AD0EB99 /* Pods */ = { 71 | isa = PBXGroup; 72 | children = ( 73 | 3755D3E87FB3D187DD6722A8 /* Pods-RMPScrollingMenuBarController_Example.debug.xcconfig */, 74 | 0AD8D4DE470C59FDE1F0A57F /* Pods-RMPScrollingMenuBarController_Example.release.xcconfig */, 75 | 07A9FD3E93752E722DD2FFE9 /* Pods-RMPScrollingMenuBarController_Tests.debug.xcconfig */, 76 | 24E2E0F91024CEA4B53C9240 /* Pods-RMPScrollingMenuBarController_Tests.release.xcconfig */, 77 | ); 78 | name = Pods; 79 | sourceTree = ""; 80 | }; 81 | 5FFF9D819E722101F6332F13 /* Frameworks */ = { 82 | isa = PBXGroup; 83 | children = ( 84 | D936C9D1FC0F8BB016C39A6B /* Pods_RMPScrollingMenuBarController_Example.framework */, 85 | 3C6D077B87E4A12CB4F9D5ED /* Pods_RMPScrollingMenuBarController_Tests.framework */, 86 | ); 87 | name = Frameworks; 88 | sourceTree = ""; 89 | }; 90 | 607FACC71AFB9204008FA782 = { 91 | isa = PBXGroup; 92 | children = ( 93 | 607FACF51AFB993E008FA782 /* Podspec Metadata */, 94 | 607FACD21AFB9204008FA782 /* Example for RMPScrollingMenuBarController */, 95 | 607FACE81AFB9204008FA782 /* Tests */, 96 | 607FACD11AFB9204008FA782 /* Products */, 97 | 17F8A3C397F1EA806AD0EB99 /* Pods */, 98 | 5FFF9D819E722101F6332F13 /* Frameworks */, 99 | ); 100 | sourceTree = ""; 101 | }; 102 | 607FACD11AFB9204008FA782 /* Products */ = { 103 | isa = PBXGroup; 104 | children = ( 105 | 607FACD01AFB9204008FA782 /* RMPScrollingMenuBarController_Example.app */, 106 | 607FACE51AFB9204008FA782 /* RMPScrollingMenuBarController_Tests.xctest */, 107 | ); 108 | name = Products; 109 | sourceTree = ""; 110 | }; 111 | 607FACD21AFB9204008FA782 /* Example for RMPScrollingMenuBarController */ = { 112 | isa = PBXGroup; 113 | children = ( 114 | 607FACD51AFB9204008FA782 /* AppDelegate.swift */, 115 | 8E4583BC1BC556FD00F1E691 /* PageViewController.swift */, 116 | 607FACDC1AFB9204008FA782 /* Images.xcassets */, 117 | 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */, 118 | 607FACD31AFB9204008FA782 /* Supporting Files */, 119 | ); 120 | name = "Example for RMPScrollingMenuBarController"; 121 | path = RMPScrollingMenuBarController; 122 | sourceTree = ""; 123 | }; 124 | 607FACD31AFB9204008FA782 /* Supporting Files */ = { 125 | isa = PBXGroup; 126 | children = ( 127 | 607FACD41AFB9204008FA782 /* Info.plist */, 128 | ); 129 | name = "Supporting Files"; 130 | sourceTree = ""; 131 | }; 132 | 607FACE81AFB9204008FA782 /* Tests */ = { 133 | isa = PBXGroup; 134 | children = ( 135 | 607FACEB1AFB9204008FA782 /* Tests.swift */, 136 | 607FACE91AFB9204008FA782 /* Supporting Files */, 137 | ); 138 | path = Tests; 139 | sourceTree = ""; 140 | }; 141 | 607FACE91AFB9204008FA782 /* Supporting Files */ = { 142 | isa = PBXGroup; 143 | children = ( 144 | 607FACEA1AFB9204008FA782 /* Info.plist */, 145 | ); 146 | name = "Supporting Files"; 147 | sourceTree = ""; 148 | }; 149 | 607FACF51AFB993E008FA782 /* Podspec Metadata */ = { 150 | isa = PBXGroup; 151 | children = ( 152 | 31E6AFE865EA7185E4D2033D /* RMPScrollingMenuBarController.podspec */, 153 | E5820239FB35908D64DC2DBA /* README.md */, 154 | 40B515E2CFF65ADC6FE6CD7D /* LICENSE */, 155 | ); 156 | name = "Podspec Metadata"; 157 | sourceTree = ""; 158 | }; 159 | /* End PBXGroup section */ 160 | 161 | /* Begin PBXNativeTarget section */ 162 | 607FACCF1AFB9204008FA782 /* RMPScrollingMenuBarController_Example */ = { 163 | isa = PBXNativeTarget; 164 | buildConfigurationList = 607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "RMPScrollingMenuBarController_Example" */; 165 | buildPhases = ( 166 | EC0FF6A6F0FF889C88840E46 /* Check Pods Manifest.lock */, 167 | 607FACCC1AFB9204008FA782 /* Sources */, 168 | 607FACCD1AFB9204008FA782 /* Frameworks */, 169 | 607FACCE1AFB9204008FA782 /* Resources */, 170 | 45122AD49BDD099A993CBCAA /* Embed Pods Frameworks */, 171 | C38498AEC155BCD0365EE153 /* Copy Pods Resources */, 172 | ); 173 | buildRules = ( 174 | ); 175 | dependencies = ( 176 | ); 177 | name = RMPScrollingMenuBarController_Example; 178 | productName = RMPScrollingMenuBarController; 179 | productReference = 607FACD01AFB9204008FA782 /* RMPScrollingMenuBarController_Example.app */; 180 | productType = "com.apple.product-type.application"; 181 | }; 182 | 607FACE41AFB9204008FA782 /* RMPScrollingMenuBarController_Tests */ = { 183 | isa = PBXNativeTarget; 184 | buildConfigurationList = 607FACF21AFB9204008FA782 /* Build configuration list for PBXNativeTarget "RMPScrollingMenuBarController_Tests" */; 185 | buildPhases = ( 186 | 2EDA264FA55D7FCB87689712 /* Check Pods Manifest.lock */, 187 | 607FACE11AFB9204008FA782 /* Sources */, 188 | 607FACE21AFB9204008FA782 /* Frameworks */, 189 | 607FACE31AFB9204008FA782 /* Resources */, 190 | 4A308140D7B6FEC9FE81680E /* Embed Pods Frameworks */, 191 | 9504059DB9FC36DFF6394202 /* Copy Pods Resources */, 192 | ); 193 | buildRules = ( 194 | ); 195 | dependencies = ( 196 | 607FACE71AFB9204008FA782 /* PBXTargetDependency */, 197 | ); 198 | name = RMPScrollingMenuBarController_Tests; 199 | productName = Tests; 200 | productReference = 607FACE51AFB9204008FA782 /* RMPScrollingMenuBarController_Tests.xctest */; 201 | productType = "com.apple.product-type.bundle.unit-test"; 202 | }; 203 | /* End PBXNativeTarget section */ 204 | 205 | /* Begin PBXProject section */ 206 | 607FACC81AFB9204008FA782 /* Project object */ = { 207 | isa = PBXProject; 208 | attributes = { 209 | LastSwiftUpdateCheck = 0700; 210 | LastUpgradeCheck = 0630; 211 | ORGANIZATIONNAME = CocoaPods; 212 | TargetAttributes = { 213 | 607FACCF1AFB9204008FA782 = { 214 | CreatedOnToolsVersion = 6.3.1; 215 | }; 216 | 607FACE41AFB9204008FA782 = { 217 | CreatedOnToolsVersion = 6.3.1; 218 | TestTargetID = 607FACCF1AFB9204008FA782; 219 | }; 220 | }; 221 | }; 222 | buildConfigurationList = 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "RMPScrollingMenuBarController" */; 223 | compatibilityVersion = "Xcode 3.2"; 224 | developmentRegion = English; 225 | hasScannedForEncodings = 0; 226 | knownRegions = ( 227 | en, 228 | Base, 229 | ); 230 | mainGroup = 607FACC71AFB9204008FA782; 231 | productRefGroup = 607FACD11AFB9204008FA782 /* Products */; 232 | projectDirPath = ""; 233 | projectRoot = ""; 234 | targets = ( 235 | 607FACCF1AFB9204008FA782 /* RMPScrollingMenuBarController_Example */, 236 | 607FACE41AFB9204008FA782 /* RMPScrollingMenuBarController_Tests */, 237 | ); 238 | }; 239 | /* End PBXProject section */ 240 | 241 | /* Begin PBXResourcesBuildPhase section */ 242 | 607FACCE1AFB9204008FA782 /* Resources */ = { 243 | isa = PBXResourcesBuildPhase; 244 | buildActionMask = 2147483647; 245 | files = ( 246 | 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */, 247 | 607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */, 248 | ); 249 | runOnlyForDeploymentPostprocessing = 0; 250 | }; 251 | 607FACE31AFB9204008FA782 /* Resources */ = { 252 | isa = PBXResourcesBuildPhase; 253 | buildActionMask = 2147483647; 254 | files = ( 255 | ); 256 | runOnlyForDeploymentPostprocessing = 0; 257 | }; 258 | /* End PBXResourcesBuildPhase section */ 259 | 260 | /* Begin PBXShellScriptBuildPhase section */ 261 | 2EDA264FA55D7FCB87689712 /* Check Pods Manifest.lock */ = { 262 | isa = PBXShellScriptBuildPhase; 263 | buildActionMask = 2147483647; 264 | files = ( 265 | ); 266 | inputPaths = ( 267 | ); 268 | name = "Check Pods Manifest.lock"; 269 | outputPaths = ( 270 | ); 271 | runOnlyForDeploymentPostprocessing = 0; 272 | shellPath = /bin/sh; 273 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; 274 | showEnvVarsInLog = 0; 275 | }; 276 | 45122AD49BDD099A993CBCAA /* Embed Pods Frameworks */ = { 277 | isa = PBXShellScriptBuildPhase; 278 | buildActionMask = 2147483647; 279 | files = ( 280 | ); 281 | inputPaths = ( 282 | ); 283 | name = "Embed Pods Frameworks"; 284 | outputPaths = ( 285 | ); 286 | runOnlyForDeploymentPostprocessing = 0; 287 | shellPath = /bin/sh; 288 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-RMPScrollingMenuBarController_Example/Pods-RMPScrollingMenuBarController_Example-frameworks.sh\"\n"; 289 | showEnvVarsInLog = 0; 290 | }; 291 | 4A308140D7B6FEC9FE81680E /* Embed Pods Frameworks */ = { 292 | isa = PBXShellScriptBuildPhase; 293 | buildActionMask = 2147483647; 294 | files = ( 295 | ); 296 | inputPaths = ( 297 | ); 298 | name = "Embed Pods Frameworks"; 299 | outputPaths = ( 300 | ); 301 | runOnlyForDeploymentPostprocessing = 0; 302 | shellPath = /bin/sh; 303 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-RMPScrollingMenuBarController_Tests/Pods-RMPScrollingMenuBarController_Tests-frameworks.sh\"\n"; 304 | showEnvVarsInLog = 0; 305 | }; 306 | 9504059DB9FC36DFF6394202 /* Copy Pods Resources */ = { 307 | isa = PBXShellScriptBuildPhase; 308 | buildActionMask = 2147483647; 309 | files = ( 310 | ); 311 | inputPaths = ( 312 | ); 313 | name = "Copy Pods Resources"; 314 | outputPaths = ( 315 | ); 316 | runOnlyForDeploymentPostprocessing = 0; 317 | shellPath = /bin/sh; 318 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-RMPScrollingMenuBarController_Tests/Pods-RMPScrollingMenuBarController_Tests-resources.sh\"\n"; 319 | showEnvVarsInLog = 0; 320 | }; 321 | C38498AEC155BCD0365EE153 /* Copy Pods Resources */ = { 322 | isa = PBXShellScriptBuildPhase; 323 | buildActionMask = 2147483647; 324 | files = ( 325 | ); 326 | inputPaths = ( 327 | ); 328 | name = "Copy Pods Resources"; 329 | outputPaths = ( 330 | ); 331 | runOnlyForDeploymentPostprocessing = 0; 332 | shellPath = /bin/sh; 333 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-RMPScrollingMenuBarController_Example/Pods-RMPScrollingMenuBarController_Example-resources.sh\"\n"; 334 | showEnvVarsInLog = 0; 335 | }; 336 | EC0FF6A6F0FF889C88840E46 /* Check Pods Manifest.lock */ = { 337 | isa = PBXShellScriptBuildPhase; 338 | buildActionMask = 2147483647; 339 | files = ( 340 | ); 341 | inputPaths = ( 342 | ); 343 | name = "Check Pods Manifest.lock"; 344 | outputPaths = ( 345 | ); 346 | runOnlyForDeploymentPostprocessing = 0; 347 | shellPath = /bin/sh; 348 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; 349 | showEnvVarsInLog = 0; 350 | }; 351 | /* End PBXShellScriptBuildPhase section */ 352 | 353 | /* Begin PBXSourcesBuildPhase section */ 354 | 607FACCC1AFB9204008FA782 /* Sources */ = { 355 | isa = PBXSourcesBuildPhase; 356 | buildActionMask = 2147483647; 357 | files = ( 358 | 8E4583BD1BC556FD00F1E691 /* PageViewController.swift in Sources */, 359 | 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */, 360 | ); 361 | runOnlyForDeploymentPostprocessing = 0; 362 | }; 363 | 607FACE11AFB9204008FA782 /* Sources */ = { 364 | isa = PBXSourcesBuildPhase; 365 | buildActionMask = 2147483647; 366 | files = ( 367 | 607FACEC1AFB9204008FA782 /* Tests.swift in Sources */, 368 | ); 369 | runOnlyForDeploymentPostprocessing = 0; 370 | }; 371 | /* End PBXSourcesBuildPhase section */ 372 | 373 | /* Begin PBXTargetDependency section */ 374 | 607FACE71AFB9204008FA782 /* PBXTargetDependency */ = { 375 | isa = PBXTargetDependency; 376 | target = 607FACCF1AFB9204008FA782 /* RMPScrollingMenuBarController_Example */; 377 | targetProxy = 607FACE61AFB9204008FA782 /* PBXContainerItemProxy */; 378 | }; 379 | /* End PBXTargetDependency section */ 380 | 381 | /* Begin PBXVariantGroup section */ 382 | 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */ = { 383 | isa = PBXVariantGroup; 384 | children = ( 385 | 607FACDF1AFB9204008FA782 /* Base */, 386 | ); 387 | name = LaunchScreen.xib; 388 | sourceTree = ""; 389 | }; 390 | /* End PBXVariantGroup section */ 391 | 392 | /* Begin XCBuildConfiguration section */ 393 | 607FACED1AFB9204008FA782 /* Debug */ = { 394 | isa = XCBuildConfiguration; 395 | buildSettings = { 396 | ALWAYS_SEARCH_USER_PATHS = NO; 397 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 398 | CLANG_CXX_LIBRARY = "libc++"; 399 | CLANG_ENABLE_MODULES = YES; 400 | CLANG_ENABLE_OBJC_ARC = YES; 401 | CLANG_WARN_BOOL_CONVERSION = YES; 402 | CLANG_WARN_CONSTANT_CONVERSION = YES; 403 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 404 | CLANG_WARN_EMPTY_BODY = YES; 405 | CLANG_WARN_ENUM_CONVERSION = YES; 406 | CLANG_WARN_INT_CONVERSION = YES; 407 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 408 | CLANG_WARN_UNREACHABLE_CODE = YES; 409 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 410 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 411 | COPY_PHASE_STRIP = NO; 412 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 413 | ENABLE_STRICT_OBJC_MSGSEND = YES; 414 | GCC_C_LANGUAGE_STANDARD = gnu99; 415 | GCC_DYNAMIC_NO_PIC = NO; 416 | GCC_NO_COMMON_BLOCKS = YES; 417 | GCC_OPTIMIZATION_LEVEL = 0; 418 | GCC_PREPROCESSOR_DEFINITIONS = ( 419 | "DEBUG=1", 420 | "$(inherited)", 421 | ); 422 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 423 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 424 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 425 | GCC_WARN_UNDECLARED_SELECTOR = YES; 426 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 427 | GCC_WARN_UNUSED_FUNCTION = YES; 428 | GCC_WARN_UNUSED_VARIABLE = YES; 429 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 430 | MTL_ENABLE_DEBUG_INFO = YES; 431 | ONLY_ACTIVE_ARCH = YES; 432 | SDKROOT = iphoneos; 433 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 434 | }; 435 | name = Debug; 436 | }; 437 | 607FACEE1AFB9204008FA782 /* Release */ = { 438 | isa = XCBuildConfiguration; 439 | buildSettings = { 440 | ALWAYS_SEARCH_USER_PATHS = NO; 441 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 442 | CLANG_CXX_LIBRARY = "libc++"; 443 | CLANG_ENABLE_MODULES = YES; 444 | CLANG_ENABLE_OBJC_ARC = YES; 445 | CLANG_WARN_BOOL_CONVERSION = YES; 446 | CLANG_WARN_CONSTANT_CONVERSION = YES; 447 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 448 | CLANG_WARN_EMPTY_BODY = YES; 449 | CLANG_WARN_ENUM_CONVERSION = YES; 450 | CLANG_WARN_INT_CONVERSION = YES; 451 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 452 | CLANG_WARN_UNREACHABLE_CODE = YES; 453 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 454 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 455 | COPY_PHASE_STRIP = NO; 456 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 457 | ENABLE_NS_ASSERTIONS = NO; 458 | ENABLE_STRICT_OBJC_MSGSEND = YES; 459 | GCC_C_LANGUAGE_STANDARD = gnu99; 460 | GCC_NO_COMMON_BLOCKS = YES; 461 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 462 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 463 | GCC_WARN_UNDECLARED_SELECTOR = YES; 464 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 465 | GCC_WARN_UNUSED_FUNCTION = YES; 466 | GCC_WARN_UNUSED_VARIABLE = YES; 467 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 468 | MTL_ENABLE_DEBUG_INFO = NO; 469 | SDKROOT = iphoneos; 470 | VALIDATE_PRODUCT = YES; 471 | }; 472 | name = Release; 473 | }; 474 | 607FACF01AFB9204008FA782 /* Debug */ = { 475 | isa = XCBuildConfiguration; 476 | baseConfigurationReference = 3755D3E87FB3D187DD6722A8 /* Pods-RMPScrollingMenuBarController_Example.debug.xcconfig */; 477 | buildSettings = { 478 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 479 | INFOPLIST_FILE = RMPScrollingMenuBarController/Info.plist; 480 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 481 | MODULE_NAME = ExampleApp; 482 | PRODUCT_NAME = "$(TARGET_NAME)"; 483 | SWIFT_OBJC_BRIDGING_HEADER = ""; 484 | }; 485 | name = Debug; 486 | }; 487 | 607FACF11AFB9204008FA782 /* Release */ = { 488 | isa = XCBuildConfiguration; 489 | baseConfigurationReference = 0AD8D4DE470C59FDE1F0A57F /* Pods-RMPScrollingMenuBarController_Example.release.xcconfig */; 490 | buildSettings = { 491 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 492 | INFOPLIST_FILE = RMPScrollingMenuBarController/Info.plist; 493 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 494 | MODULE_NAME = ExampleApp; 495 | PRODUCT_NAME = "$(TARGET_NAME)"; 496 | SWIFT_OBJC_BRIDGING_HEADER = ""; 497 | }; 498 | name = Release; 499 | }; 500 | 607FACF31AFB9204008FA782 /* Debug */ = { 501 | isa = XCBuildConfiguration; 502 | baseConfigurationReference = 07A9FD3E93752E722DD2FFE9 /* Pods-RMPScrollingMenuBarController_Tests.debug.xcconfig */; 503 | buildSettings = { 504 | BUNDLE_LOADER = "$(TEST_HOST)"; 505 | FRAMEWORK_SEARCH_PATHS = ( 506 | "$(SDKROOT)/Developer/Library/Frameworks", 507 | "$(inherited)", 508 | ); 509 | GCC_PREPROCESSOR_DEFINITIONS = ( 510 | "DEBUG=1", 511 | "$(inherited)", 512 | ); 513 | INFOPLIST_FILE = Tests/Info.plist; 514 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 515 | PRODUCT_NAME = "$(TARGET_NAME)"; 516 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/RMPScrollingMenuBarController_Example.app/RMPScrollingMenuBarController_Example"; 517 | }; 518 | name = Debug; 519 | }; 520 | 607FACF41AFB9204008FA782 /* Release */ = { 521 | isa = XCBuildConfiguration; 522 | baseConfigurationReference = 24E2E0F91024CEA4B53C9240 /* Pods-RMPScrollingMenuBarController_Tests.release.xcconfig */; 523 | buildSettings = { 524 | BUNDLE_LOADER = "$(TEST_HOST)"; 525 | FRAMEWORK_SEARCH_PATHS = ( 526 | "$(SDKROOT)/Developer/Library/Frameworks", 527 | "$(inherited)", 528 | ); 529 | INFOPLIST_FILE = Tests/Info.plist; 530 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 531 | PRODUCT_NAME = "$(TARGET_NAME)"; 532 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/RMPScrollingMenuBarController_Example.app/RMPScrollingMenuBarController_Example"; 533 | }; 534 | name = Release; 535 | }; 536 | /* End XCBuildConfiguration section */ 537 | 538 | /* Begin XCConfigurationList section */ 539 | 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "RMPScrollingMenuBarController" */ = { 540 | isa = XCConfigurationList; 541 | buildConfigurations = ( 542 | 607FACED1AFB9204008FA782 /* Debug */, 543 | 607FACEE1AFB9204008FA782 /* Release */, 544 | ); 545 | defaultConfigurationIsVisible = 0; 546 | defaultConfigurationName = Release; 547 | }; 548 | 607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "RMPScrollingMenuBarController_Example" */ = { 549 | isa = XCConfigurationList; 550 | buildConfigurations = ( 551 | 607FACF01AFB9204008FA782 /* Debug */, 552 | 607FACF11AFB9204008FA782 /* Release */, 553 | ); 554 | defaultConfigurationIsVisible = 0; 555 | defaultConfigurationName = Release; 556 | }; 557 | 607FACF21AFB9204008FA782 /* Build configuration list for PBXNativeTarget "RMPScrollingMenuBarController_Tests" */ = { 558 | isa = XCConfigurationList; 559 | buildConfigurations = ( 560 | 607FACF31AFB9204008FA782 /* Debug */, 561 | 607FACF41AFB9204008FA782 /* Release */, 562 | ); 563 | defaultConfigurationIsVisible = 0; 564 | defaultConfigurationName = Release; 565 | }; 566 | /* End XCConfigurationList section */ 567 | }; 568 | rootObject = 607FACC81AFB9204008FA782 /* Project object */; 569 | } 570 | -------------------------------------------------------------------------------- /Example_Swift2/RMPScrollingMenuBarController.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example_Swift2/RMPScrollingMenuBarController.xcodeproj/xcshareddata/xcschemes/RMPScrollingMenuBarController-Example.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 75 | 77 | 83 | 84 | 85 | 86 | 87 | 88 | 94 | 96 | 102 | 103 | 104 | 105 | 107 | 108 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /Example_Swift2/RMPScrollingMenuBarController.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Example_Swift2/RMPScrollingMenuBarController/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Recruit Marketing Partners Co.,Ltd. All rights reserved. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | import UIKit 22 | import RMPScrollingMenuBarController 23 | 24 | @UIApplicationMain 25 | class AppDelegate: UIResponder, UIApplicationDelegate { 26 | 27 | var window: UIWindow? 28 | 29 | 30 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 31 | 32 | self.setup() 33 | 34 | return true 35 | } 36 | 37 | func applicationWillResignActive(application: UIApplication) { 38 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 39 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 40 | } 41 | 42 | func applicationDidEnterBackground(application: UIApplication) { 43 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 44 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 45 | } 46 | 47 | func applicationWillEnterForeground(application: UIApplication) { 48 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 49 | } 50 | 51 | func applicationDidBecomeActive(application: UIApplication) { 52 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 53 | } 54 | 55 | func applicationWillTerminate(application: UIApplication) { 56 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 57 | } 58 | 59 | // MARK: - private methods 60 | 61 | func setup() { 62 | self.window = UIWindow(frame: UIScreen.mainScreen().bounds) 63 | 64 | // Setup menu bar controller 65 | let menuController = RMPScrollingMenuBarController() 66 | menuController.delegate = self 67 | 68 | // Customize appearance of menu bar. 69 | menuController.view.backgroundColor = UIColor.whiteColor() 70 | menuController.menuBar.indicatorColor = UIColor.blueColor() 71 | //menuController.menuBar.style = .InfinitePaging 72 | //menuController.menuBar.showsIndicator = false 73 | //menuController.menuBar.showsSeparatorLine = false 74 | 75 | // Set ViewControllers for menu bar controller 76 | var viewControllers: [PageViewController] = [] 77 | for var i = 0 ; i < 10 ; ++i { 78 | let vc = PageViewController() 79 | vc.view.backgroundColor = UIColor(white: CGFloat(0.3) + CGFloat(0.05) * CGFloat(i), alpha: 1) 80 | vc.message = "Message for No.\(i)" 81 | viewControllers.append(vc) 82 | } 83 | 84 | menuController.setViewControllers(viewControllers, animated: false) 85 | 86 | let naviController = UINavigationController(rootViewController: menuController) 87 | self.window?.rootViewController = naviController 88 | self.window?.makeKeyAndVisible() 89 | } 90 | } 91 | 92 | extension AppDelegate: RMPScrollingMenuBarControllerDelegate { 93 | func menuBarController(menuBarController: RMPScrollingMenuBarController!, willSelectViewController viewController: UIViewController!) { 94 | print("will select \(viewController)") 95 | } 96 | 97 | func menuBarController(menuBarController: RMPScrollingMenuBarController!, didSelectViewController viewController: UIViewController!) { 98 | print("did select \(viewController)") 99 | } 100 | 101 | func menuBarController(menuBarController: RMPScrollingMenuBarController!, didCancelViewController viewController: UIViewController!) { 102 | print("did cancel \(viewController)") 103 | } 104 | 105 | func menuBarController(menuBarController: RMPScrollingMenuBarController!, menuBarItemAtIndex index: Int) -> RMPScrollingMenuBarItem! { 106 | let item = RMPScrollingMenuBarItem() 107 | item.title = "Title \(index)" 108 | 109 | // Customize appearance of menu bar item. 110 | let button = item.button() 111 | button.setTitleColor(UIColor.lightGrayColor(), forState: .Normal) 112 | button.setTitleColor(UIColor.blueColor(), forState: .Disabled) 113 | button.setTitleColor(UIColor.grayColor(), forState: .Selected) 114 | return item 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /Example_Swift2/RMPScrollingMenuBarController/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Example_Swift2/RMPScrollingMenuBarController/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Example_Swift2/RMPScrollingMenuBarController/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /Example_Swift2/RMPScrollingMenuBarController/PageViewController.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Recruit Marketing Partners Co.,Ltd. All rights reserved. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | import UIKit 22 | 23 | class PageViewController: UIViewController { 24 | 25 | private var messageLabel: UILabel? 26 | 27 | private var _message: String? 28 | var message: String? { 29 | get { 30 | return _message 31 | } 32 | set(newMessage) { 33 | _message = newMessage 34 | messageLabel?.text = _message 35 | } 36 | } 37 | 38 | override func viewDidLoad() { 39 | super.viewDidLoad() 40 | 41 | var f = self.view.bounds 42 | f.size.height = 32 43 | messageLabel = UILabel(frame: f) 44 | messageLabel?.numberOfLines = 0 45 | messageLabel?.textColor = UIColor.whiteColor() 46 | messageLabel?.textAlignment = .Center 47 | messageLabel?.center = CGPointMake(self.view.bounds.size.width * 0.5, self.view.bounds.size.height * 0.5) 48 | self.view.addSubview(messageLabel!) 49 | 50 | if message != nil { 51 | messageLabel?.text = message 52 | } 53 | 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /Example_Swift2/Tests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | org.cocoapods.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Example_Swift2/Tests/Tests.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import XCTest 3 | import RMPScrollingMenuBarController 4 | 5 | class Tests: XCTestCase { 6 | 7 | override func setUp() { 8 | super.setUp() 9 | // Put setup code here. This method is called before the invocation of each test method in the class. 10 | } 11 | 12 | override func tearDown() { 13 | // Put teardown code here. This method is called after the invocation of each test method in the class. 14 | super.tearDown() 15 | } 16 | 17 | func testExample() { 18 | // This is an example of a functional test case. 19 | XCTAssert(true, "Pass") 20 | } 21 | 22 | func testPerformanceExample() { 23 | // This is an example of a performance test case. 24 | self.measureBlock() { 25 | // Put the code you want to measure the time of here. 26 | } 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 Recruit Marketing Partners Co.,Ltd. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /Pod/Assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recruit-mp/RMPScrollingMenuBarController/2de637e2e86d8fe986e6dd26cd2910c78739b95d/Pod/Assets/.gitkeep -------------------------------------------------------------------------------- /Pod/Classes/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recruit-mp/RMPScrollingMenuBarController/2de637e2e86d8fe986e6dd26cd2910c78739b95d/Pod/Classes/.gitkeep -------------------------------------------------------------------------------- /Pod/Classes/RMPScrollingMenuBar.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Recruit Marketing Partners Co.,Ltd. All rights reserved. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #import 22 | #import "RMPScrollingMenuBarItem.h" 23 | 24 | #define kRMPMenuBarDefaultBarHeight 36.0f 25 | 26 | typedef NS_ENUM(NSUInteger, RMPScrollingMenuBarStyle) { 27 | RMPScrollingMenuBarStyleNormal, 28 | RMPScrollingMenuBarStyleInfinitePaging, 29 | }; 30 | 31 | typedef NS_ENUM(NSInteger, RMPScrollingMenuBarDirection){ 32 | RMPScrollingMenuBarDirectionNone, 33 | RMPScrollingMenuBarDirectionLeft, 34 | RMPScrollingMenuBarDirectionRight, 35 | }; 36 | 37 | @class RMPScrollingMenuBar; 38 | 39 | /** ScrollingMenuBar's delegate protocol 40 | */ 41 | @protocol RMPScrollingMenuBarDelegate 42 | 43 | - (void)menuBar:(RMPScrollingMenuBar*)menuBar didSelectItem:(RMPScrollingMenuBarItem*)item direction:(RMPScrollingMenuBarDirection)direction; 44 | 45 | @end 46 | 47 | /** View Class of ScrollingMenuBar 48 | */ 49 | @interface RMPScrollingMenuBar : UIView 50 | 51 | /** Height of menu bar 52 | */ 53 | @property (nonatomic, assign)CGFloat barHeight; 54 | 55 | /** Insets of menu items on menu bar. Use for adjusting spaces between menu items. 56 | */ 57 | @property (nonatomic, assign)UIEdgeInsets itemInsets; 58 | 59 | /** Delegate object 60 | */ 61 | @property (nonatomic, weak)id delegate; 62 | 63 | /** Array of menu items. 64 | */ 65 | @property (nonatomic, copy)NSArray* items; 66 | 67 | /** Selected menu item. 68 | */ 69 | @property (nonatomic, weak)RMPScrollingMenuBarItem* selectedItem; 70 | 71 | /** A Boolean value that controls whether the indicator is visible or not. 72 | Default value is YES. 73 | */ 74 | @property (nonatomic, assign)BOOL showsIndicator; 75 | 76 | /** Color of indicator which be displayed under selected menu item. 77 | */ 78 | @property (nonatomic, strong)UIColor* indicatorColor; 79 | 80 | /** A Boolean value that controls whether the separator line is visible or not. 81 | Default value is YES. 82 | */ 83 | @property (nonatomic, assign)BOOL showsSeparatorLine; 84 | 85 | /* The menu bar style that specifies its behaviour. 86 | */ 87 | @property (nonatomic, assign)RMPScrollingMenuBarStyle style; 88 | 89 | @property (nonatomic, readonly)CGFloat scrollOffsetX; 90 | 91 | /** Setter of menu items. 92 | */ 93 | - (void)setItems:(NSArray *)items animated:(BOOL)animated; 94 | 95 | /** Scrolls menu bar by a ratio of the width of the item 96 | Move to right item by setting to 1.0, Also Move to left item by setting to -1.0. 97 | */ 98 | - (void)scrollByRatio:(CGFloat)ratio from:(CGFloat)from; 99 | 100 | 101 | @end 102 | -------------------------------------------------------------------------------- /Pod/Classes/RMPScrollingMenuBar.m: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Recruit Marketing Partners Co.,Ltd. All rights reserved. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #import "RMPScrollingMenuBar.h" 22 | 23 | @interface RMPScrollingMenuBarScrollView :UIScrollView 24 | 25 | @end 26 | 27 | @implementation RMPScrollingMenuBarScrollView 28 | 29 | - (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event 30 | { 31 | // はみ出たViewもタッチできるように拡張する 32 | UIView* view = [super hitTest:point withEvent:event]; 33 | if(view){ 34 | return view; 35 | } 36 | 37 | for(UIView* v in self.subviews){ 38 | CGPoint convertedPoint = [self convertPoint:point toView:v]; 39 | if(CGRectContainsPoint(v.bounds, convertedPoint)){ 40 | view = v; 41 | break; 42 | } 43 | } 44 | return view; 45 | } 46 | 47 | @end 48 | 49 | @interface RMPScrollingMenuBar () 50 | 51 | @end 52 | 53 | @implementation RMPScrollingMenuBar { 54 | RMPScrollingMenuBarScrollView* _scrollView; 55 | UIView* _indicatorView; 56 | UIView* _border; 57 | 58 | CGFloat _infinitePagingBoundsWidth; 59 | CGFloat _infinitePagingOffsetX; 60 | NSMutableArray* _infinitePagingOrder; 61 | BOOL _infinitePagingIsTappedItem; 62 | CGFloat _infinitePagingLastContentOffsetX; 63 | 64 | } 65 | 66 | - (instancetype)init 67 | { 68 | self = [super init]; 69 | if(self){ 70 | [self setup]; 71 | } 72 | return self; 73 | } 74 | 75 | - (instancetype)initWithFrame:(CGRect)frame 76 | { 77 | self = [super initWithFrame:frame]; 78 | if(self){ 79 | [self setup]; 80 | } 81 | return self; 82 | } 83 | 84 | - (CGSize)sizeThatFits:(CGSize)size 85 | { 86 | CGFloat w, h; 87 | if(self.superview){ 88 | w = self.superview.bounds.size.width; 89 | }else { 90 | w = [[UIScreen mainScreen] bounds].size.width; 91 | } 92 | h = _barHeight; 93 | 94 | return CGSizeMake(w, h); 95 | } 96 | 97 | - (void)layoutSubviews 98 | { 99 | _scrollView.frame = self.bounds; 100 | _scrollView.contentInset = UIEdgeInsetsZero; 101 | if(_style == RMPScrollingMenuBarStyleNormal){ 102 | _scrollView.frame = CGRectMake(0, 0, _scrollView.frame.size.width, _scrollView.frame.size.height); 103 | }else if(_style == RMPScrollingMenuBarStyleInfinitePaging){ 104 | _scrollView.frame = CGRectMake((_scrollView.frame.size.width-_infinitePagingBoundsWidth)*0.5, 105 | 0, _infinitePagingBoundsWidth, _scrollView.frame.size.height); 106 | } 107 | 108 | CGFloat lineWidth = 1.0f/[[UIScreen mainScreen] scale]; 109 | _border.frame = CGRectMake(0, self.bounds.size.height - lineWidth, self.bounds.size.width, lineWidth); 110 | } 111 | 112 | - (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event 113 | { 114 | if(!self.userInteractionEnabled) return nil; 115 | 116 | // Expands ScrollView's tachable area 117 | UIView* view = [_scrollView hitTest:[self convertPoint:point toView:_scrollView] withEvent:event]; 118 | if(!view && CGRectContainsPoint(self.bounds, point)){ 119 | view = _scrollView; 120 | } 121 | return view; 122 | } 123 | 124 | #pragma mark - 125 | - (void)setup 126 | { 127 | _showsIndicator = YES; 128 | _showsSeparatorLine = YES; 129 | 130 | _barHeight = kRMPMenuBarDefaultBarHeight; 131 | _itemInsets = UIEdgeInsetsZero; 132 | _indicatorColor = [UIColor colorWithRed:0.988 green:0.224 blue:0.129 alpha:1.000]; 133 | 134 | RMPScrollingMenuBarScrollView* scrollView = [[RMPScrollingMenuBarScrollView alloc] initWithFrame:self.bounds]; 135 | _scrollView = scrollView; 136 | _scrollView.showsVerticalScrollIndicator = NO; 137 | _scrollView.showsHorizontalScrollIndicator = NO; 138 | _scrollView.contentOffset = CGPointZero; 139 | _scrollView.scrollsToTop = NO; 140 | [self addSubview:_scrollView]; 141 | 142 | UIView* indicator = [[UIView alloc] initWithFrame:CGRectMake(0, self.bounds.size.height - 4, 0, 2)]; 143 | _indicatorView = indicator; 144 | _indicatorView.backgroundColor = _indicatorColor; 145 | [_scrollView addSubview:_indicatorView]; 146 | 147 | UIView* border = [[UIView alloc] initWithFrame:CGRectMake(0, self.bounds.size.height - 0.25f, self.bounds.size.width, 0.25f)]; 148 | _border = border; 149 | _border.backgroundColor = [UIColor colorWithWhite:0.698 alpha:1.000]; 150 | [self addSubview:_border]; 151 | } 152 | 153 | - (void)setStyle:(RMPScrollingMenuBarStyle)style 154 | { 155 | _style = style; 156 | if(_items.count > 0){ 157 | [self setItems:_items animated:YES]; 158 | } 159 | } 160 | 161 | - (void)setItems:(NSArray *)items 162 | { 163 | [self setItems:items animated:NO]; 164 | } 165 | 166 | - (void)setItems:(NSArray *)items animated:(BOOL)animated 167 | { 168 | _selectedItem = nil; 169 | _items = [items copy]; 170 | 171 | // Clear all of menu items. 172 | for(UIView* view in _scrollView.subviews){ 173 | if([view isKindOfClass:[RMPScrollingMenuBarButton class]]){ 174 | [view removeFromSuperview]; 175 | } 176 | } 177 | 178 | if(_items.count == 0){ 179 | return; 180 | } 181 | 182 | if(_style == RMPScrollingMenuBarStyleNormal){ 183 | [self setupMenuBarButtonsForNormalStyle:animated]; 184 | }else if(_style == RMPScrollingMenuBarStyleInfinitePaging){ 185 | [self setupMenuBarButtonsForInfinitePagingStyle:animated]; 186 | } 187 | } 188 | 189 | - (void)setupMenuBarButtonsForNormalStyle:(BOOL)animated 190 | { 191 | CGRect f; 192 | 193 | _scrollView.pagingEnabled = NO; 194 | _scrollView.decelerationRate = UIScrollViewDecelerationRateNormal; 195 | _scrollView.clipsToBounds = YES; 196 | _scrollView.delegate = nil; 197 | 198 | // Set up button of menu items. 199 | CGFloat offset = _itemInsets.left; 200 | for(RMPScrollingMenuBarItem* item in _items){ 201 | RMPScrollingMenuBarButton* view = [item button]; 202 | if(view){ 203 | f = CGRectMake(offset, _itemInsets.top, item.width, 204 | _scrollView.bounds.size.height-_itemInsets.top + _itemInsets.bottom); 205 | offset += f.size.width + _itemInsets.right + _itemInsets.left; 206 | view.frame = f; 207 | view.alpha = 0.0; 208 | [_scrollView addSubview:view]; 209 | 210 | [(RMPScrollingMenuBarButton*)view addTarget:self 211 | action:@selector(didTapMenuButton:) 212 | forControlEvents:UIControlEventTouchUpInside]; 213 | 214 | } 215 | } 216 | CGFloat contentWidth = offset - _itemInsets.left; 217 | if(contentWidth < _scrollView.bounds.size.width){ 218 | // Align items to center if number of items is less. 219 | offset = (_scrollView.bounds.size.width - contentWidth)*0.5; 220 | contentWidth = _scrollView.bounds.size.width; 221 | for(UIView* view in _scrollView.subviews){ 222 | if([view isKindOfClass:[RMPScrollingMenuBarButton class]]){ 223 | f = view.frame; 224 | f.origin.x += offset; 225 | view.frame = f; 226 | } 227 | } 228 | 229 | } 230 | _scrollView.contentSize = CGSizeMake(contentWidth, _scrollView.bounds.size.height); 231 | 232 | if(!animated){ 233 | // Without Animate. 234 | for(UIView* view in _scrollView.subviews){ 235 | if([view isKindOfClass:[RMPScrollingMenuBarButton class]]){ 236 | view.alpha = 1.0; 237 | } 238 | } 239 | }else { 240 | // With Animate. 241 | int i = 0; 242 | for(UIView* view in _scrollView.subviews){ 243 | if([view isKindOfClass:[RMPScrollingMenuBarButton class]]){ 244 | [self animateButton:view atIndex:i]; 245 | i++; 246 | } 247 | } 248 | } 249 | 250 | if(!_selectedItem && _items.count > 0){ 251 | [self setSelectedItem:_items[0]]; 252 | } 253 | } 254 | 255 | - (void)setupMenuBarButtonsForInfinitePagingStyle:(BOOL)animated 256 | { 257 | CGRect f; 258 | 259 | _scrollView.pagingEnabled = YES; 260 | _scrollView.decelerationRate = UIScrollViewDecelerationRateFast; 261 | _scrollView.clipsToBounds = NO; 262 | _scrollView.delegate = self; 263 | 264 | // Get max width of buttons 265 | CGFloat maxWidth = 0.0; 266 | CGFloat totalWidth = 0.0; 267 | for(RMPScrollingMenuBarItem* item in _items){ 268 | if(item.width > maxWidth){ 269 | maxWidth = item.width; 270 | } 271 | totalWidth += item.width + _itemInsets.right + _itemInsets.left; 272 | } 273 | 274 | maxWidth = (NSInteger)(maxWidth + 0.5); 275 | 276 | // Display normal style if can show all items. 277 | if(totalWidth < _scrollView.bounds.size.width){ 278 | NSLog(@"Can not infinite paging, because the number of items is too small."); 279 | _style = RMPScrollingMenuBarStyleNormal; 280 | [self setupMenuBarButtonsForNormalStyle:animated]; 281 | return; 282 | } 283 | 284 | _infinitePagingOrder = [NSMutableArray array]; 285 | 286 | // Set up button of menu items. 287 | // Center _items[0]. 288 | CGFloat offset = _itemInsets.left; 289 | NSInteger totalCount = _items.count; 290 | NSInteger halfCount = totalCount/2; 291 | NSInteger evenFactor = (totalCount%2) ? 0 : 1; 292 | 293 | CGFloat firstItemOriginX = 0.0; 294 | for(NSInteger i = -(halfCount-evenFactor); i <= halfCount; i++){ 295 | NSInteger index = (totalCount + i)%totalCount; 296 | RMPScrollingMenuBarItem* item = _items[index]; 297 | RMPScrollingMenuBarButton* view = [item button]; 298 | if(view){ 299 | CGFloat diffWidth = maxWidth-item.width; 300 | f = CGRectMake(offset+diffWidth*0.5, _itemInsets.top, item.width, 301 | _scrollView.bounds.size.height-_itemInsets.top + _itemInsets.bottom); 302 | offset += f.size.width + _itemInsets.right + _itemInsets.left + diffWidth*0.5; 303 | view.frame = f; 304 | view.alpha = 0.0; 305 | [_scrollView addSubview:view]; 306 | 307 | [(RMPScrollingMenuBarButton*)view addTarget:self 308 | action:@selector(didTapMenuButton:) 309 | forControlEvents:UIControlEventTouchUpInside]; 310 | if(index == 0){ 311 | firstItemOriginX = (NSInteger)(f.origin.x - _itemInsets.left - diffWidth*0.5); 312 | } 313 | 314 | [_infinitePagingOrder addObject:[NSValue valueWithNonretainedObject:item]]; 315 | } 316 | } 317 | _infinitePagingBoundsWidth = maxWidth + _itemInsets.left + _itemInsets.right; 318 | _scrollView.frame = CGRectMake((_scrollView.frame.size.width-_infinitePagingBoundsWidth)*0.5, 319 | 0, _infinitePagingBoundsWidth, _scrollView.frame.size.height); 320 | 321 | CGFloat contentWidth = offset - _itemInsets.left; 322 | _scrollView.contentSize = CGSizeMake(contentWidth, _scrollView.bounds.size.height); 323 | _scrollView.contentOffset = CGPointMake(firstItemOriginX, 0); 324 | _infinitePagingOffsetX = firstItemOriginX; 325 | _infinitePagingLastContentOffsetX = firstItemOriginX; 326 | [_scrollView setNeedsLayout]; 327 | 328 | if(!animated){ 329 | // Without Animate. 330 | for(UIView* view in _scrollView.subviews){ 331 | if([view isKindOfClass:[RMPScrollingMenuBarButton class]]){ 332 | view.alpha = 1.0; 333 | } 334 | } 335 | }else { 336 | // With Animate. 337 | for(NSInteger i = 0; i <= halfCount; i++){ 338 | NSInteger index1 = (totalCount + i)%totalCount; 339 | RMPScrollingMenuBarItem* item1 = _items[index1]; 340 | RMPScrollingMenuBarButton* view1 = item1.button; 341 | if([view1 isKindOfClass:[RMPScrollingMenuBarButton class]]){ 342 | [self animateButton:view1 atIndex:i]; 343 | } 344 | 345 | NSInteger index2 = (totalCount - i)%totalCount; 346 | if(index1 == index2){ 347 | continue; 348 | } 349 | 350 | RMPScrollingMenuBarItem* item2 = _items[index2]; 351 | RMPScrollingMenuBarButton* view2 = item2.button; 352 | if([view2 isKindOfClass:[RMPScrollingMenuBarButton class]]){ 353 | [self animateButton:view2 atIndex:i]; 354 | } 355 | 356 | } 357 | } 358 | 359 | if(!_selectedItem){ 360 | dispatch_async(dispatch_get_main_queue(), ^{ 361 | [self setSelectedItem:_items[0] animated:NO]; 362 | }); 363 | } 364 | } 365 | 366 | - (void)updateMenuButtonLayout 367 | { 368 | 369 | } 370 | 371 | - (void)animateButton:(UIView*)view atIndex:(NSInteger)index 372 | { 373 | view.transform = CGAffineTransformMakeScale(1.4, 1.4); 374 | [UIView animateWithDuration:0.24 delay:0.06 + 0.10*index 375 | options:UIViewAnimationOptionCurveEaseOut 376 | animations:^{ 377 | view.alpha = 1.0; 378 | view.transform = CGAffineTransformMakeScale(1.0, 1.0); 379 | } completion:^(BOOL finished) { 380 | ; 381 | }]; 382 | } 383 | 384 | - (CGFloat)scrollOffsetX 385 | { 386 | return _scrollView.contentOffset.x; 387 | } 388 | 389 | - (void)scrollByRatio:(CGFloat)ratio from:(CGFloat)from { 390 | if(_style == RMPScrollingMenuBarStyleNormal){ 391 | NSInteger index = [_items indexOfObject:_selectedItem]; 392 | NSInteger ignoreCount = (NSInteger)(_scrollView.frame.size.width*0.5/(_scrollView.contentSize.width/_items.count)); 393 | for(NSInteger i = 0; i < ignoreCount; i++){ 394 | if (index == i){ 395 | return; 396 | }else if (index == _items.count-1-i){ 397 | return; 398 | } 399 | } 400 | if(index == ignoreCount && ratio < 0.0){ 401 | return; 402 | }else if(index == _items.count-1-ignoreCount && ratio > 0.0){ 403 | return; 404 | } 405 | } 406 | 407 | _scrollView.contentOffset = CGPointMake(from + _scrollView.contentSize.width/_items.count*ratio, 0); 408 | NSLog(@"scrollByRatio %0.2f, %0.2f", ratio, _scrollView.contentOffset.x); 409 | } 410 | 411 | - (void)setSelectedItem:(RMPScrollingMenuBarItem *)selectedItem 412 | { 413 | [self setSelectedItem:selectedItem animated:YES]; 414 | } 415 | 416 | - (void)setSelectedItem:(RMPScrollingMenuBarItem *)selectedItem animated:(BOOL)animated 417 | { 418 | if(_selectedItem == selectedItem)return; 419 | 420 | self.userInteractionEnabled = NO; 421 | 422 | if(_selectedItem){ 423 | _selectedItem.selected = NO; 424 | } 425 | 426 | RMPScrollingMenuBarDirection direction = RMPScrollingMenuBarDirectionNone; 427 | if(_style == RMPScrollingMenuBarStyleInfinitePaging){ 428 | NSInteger lastIndex = [_items indexOfObject:_selectedItem]; 429 | NSInteger nextIndex = [_items indexOfObject:selectedItem]; 430 | if(nextIndex - lastIndex > 0){ 431 | if((nextIndex - lastIndex) < _items.count/2){ 432 | direction = RMPScrollingMenuBarDirectionRight; 433 | }else { 434 | direction = RMPScrollingMenuBarDirectionLeft; 435 | } 436 | }else { 437 | if((lastIndex - nextIndex) < _items.count/2){ 438 | direction = RMPScrollingMenuBarDirectionLeft; 439 | }else { 440 | direction = RMPScrollingMenuBarDirectionRight; 441 | } 442 | } 443 | } 444 | 445 | _selectedItem = selectedItem; 446 | _selectedItem.selected = YES; 447 | 448 | // Selected item want to be displayed to center as possible. 449 | CGPoint offset = CGPointZero; 450 | CGPoint newPosition = CGPointZero; 451 | if(_style == RMPScrollingMenuBarStyleNormal){ 452 | if(_selectedItem.button.center.x > _scrollView.bounds.size.width*0.5 453 | && (NSInteger)(_scrollView.contentSize.width - _selectedItem.button.center.x) >= (NSInteger)(_scrollView.bounds.size.width*0.5)){ 454 | offset = CGPointMake(_selectedItem.button.center.x - _scrollView.frame.size.width*0.5, 0); 455 | }else if(_selectedItem.button.center.x < _scrollView.bounds.size.width*0.5){ 456 | offset = CGPointMake(0, 0); 457 | }else if((NSInteger)(_scrollView.contentSize.width - _selectedItem.button.center.x) < (NSInteger)(_scrollView.bounds.size.width*0.5)){ 458 | offset = CGPointMake(_scrollView.contentSize.width-_scrollView.bounds.size.width, 0); 459 | } 460 | [_scrollView setContentOffset:offset animated:animated]; 461 | 462 | newPosition = [_scrollView convertPoint:CGPointZero fromView:_selectedItem.button]; 463 | }else if(_style == RMPScrollingMenuBarStyleInfinitePaging){ 464 | CGFloat margin = (_infinitePagingBoundsWidth - _selectedItem.width) * 0.5; 465 | offset = CGPointMake(_selectedItem.button.frame.origin.x - margin, 0.0); 466 | [_scrollView setContentOffset:offset animated:animated]; 467 | 468 | newPosition.x = _infinitePagingOffsetX + _itemInsets.left; 469 | } 470 | 471 | if((_indicatorView.frame.origin.x == 0.0 && _indicatorView.frame.size.width == 0.0)){ 472 | CGRect f = _indicatorView.frame; 473 | f.origin.x = newPosition.x - 3; 474 | f.size.width = _selectedItem.button.frame.size.width + 6; 475 | _indicatorView.frame = f; 476 | }else if(_style == RMPScrollingMenuBarStyleNormal){ 477 | NSTimeInterval dur = fabs(newPosition.x - _indicatorView.frame.origin.x)/160.0*0.4*0.8; 478 | if(dur < 0.38){ 479 | dur = 0.38; 480 | }else if(dur > 0.6){ 481 | dur = 0.6; 482 | } 483 | 484 | [UIView animateWithDuration:dur 485 | delay:0.16 486 | usingSpringWithDamping:0.8 487 | initialSpringVelocity:0.1 488 | options:UIViewAnimationOptionCurveEaseInOut 489 | animations:^{ 490 | CGRect f = _indicatorView.frame; 491 | f.origin.x = newPosition.x - 3; 492 | f.size.width = _selectedItem.button.frame.size.width + 6; 493 | _indicatorView.frame = f; 494 | } completion:^(BOOL finished) { 495 | self.userInteractionEnabled = YES; 496 | if([_delegate respondsToSelector:@selector(menuBar:didSelectItem:direction:)]){ 497 | [_delegate menuBar:self didSelectItem:_selectedItem direction:direction]; 498 | } 499 | }]; 500 | }else if(_style == RMPScrollingMenuBarStyleInfinitePaging){ 501 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 502 | [self reorderItemsForInfinitePaging]; 503 | 504 | CGRect f = _indicatorView.frame; 505 | f.origin.x = newPosition.x - 3; 506 | f.size.width = _selectedItem.button.frame.size.width + 6; 507 | _indicatorView.frame = f; 508 | 509 | self.userInteractionEnabled = YES; 510 | if([_delegate respondsToSelector:@selector(menuBar:didSelectItem:direction:)]){ 511 | [_delegate menuBar:self didSelectItem:_selectedItem direction:direction]; 512 | } 513 | _infinitePagingIsTappedItem = NO; 514 | }); 515 | } 516 | } 517 | 518 | - (void)setIndicatorColor:(UIColor *)indicatorColor 519 | { 520 | _indicatorColor = indicatorColor; 521 | if(_indicatorView){ 522 | _indicatorView.backgroundColor = _indicatorColor; 523 | } 524 | } 525 | 526 | - (void)setBarHeight:(CGFloat)barHeight 527 | { 528 | _barHeight = barHeight; 529 | 530 | [self sizeToFit]; 531 | [self layoutIfNeeded]; 532 | } 533 | 534 | - (void)setShowsIndicator:(BOOL)showsIndicator 535 | { 536 | _showsIndicator = showsIndicator; 537 | _indicatorView.hidden = !_showsIndicator; 538 | } 539 | 540 | - (void)setShowsSeparatorLine:(BOOL)showsSeparatorLine 541 | { 542 | _showsSeparatorLine = showsSeparatorLine; 543 | _border.hidden = !_showsSeparatorLine; 544 | } 545 | 546 | #pragma mark - button action 547 | - (void)didTapMenuButton:(id)sender 548 | { 549 | for(RMPScrollingMenuBarItem* item in _items){ 550 | if(sender == item.button && item != _selectedItem){ 551 | NSLog(@"did tap menu bar item"); 552 | _infinitePagingIsTappedItem = YES; 553 | self.selectedItem = item; 554 | break; 555 | } 556 | } 557 | } 558 | 559 | - (void)reorderItemsForInfinitePaging 560 | { 561 | CGFloat diffX = (NSInteger)_scrollView.contentOffset.x - (NSInteger)_infinitePagingOffsetX; 562 | NSInteger moveCount = ((NSInteger)fabs(diffX)/(NSInteger)_infinitePagingBoundsWidth); 563 | if(diffX > 0){ 564 | // right item 565 | if(_infinitePagingOrder.count > 0){ 566 | for(int i = 0; i < moveCount; i++){ 567 | id firstObj = _infinitePagingOrder[0]; 568 | [_infinitePagingOrder addObject:firstObj]; 569 | [_infinitePagingOrder removeObjectAtIndex:0]; 570 | } 571 | } 572 | }else if(diffX < 0){ 573 | // left item 574 | if(_infinitePagingOrder.count > 0){ 575 | for(int i = 0; i < moveCount; i++){ 576 | id lastObj = _infinitePagingOrder.lastObject; 577 | [_infinitePagingOrder insertObject:lastObj atIndex:0]; 578 | [_infinitePagingOrder removeObjectAtIndex:_infinitePagingOrder.count-1]; 579 | } 580 | } 581 | } 582 | 583 | NSInteger index = 0; 584 | CGRect f; 585 | for(NSValue* val in _infinitePagingOrder){ 586 | RMPScrollingMenuBarItem* item = [val nonretainedObjectValue]; 587 | 588 | f = item.button.frame; 589 | f.origin.x = index*_infinitePagingBoundsWidth + _itemInsets.left; 590 | item.button.frame = f; 591 | 592 | index++; 593 | } 594 | 595 | _scrollView.contentOffset = CGPointMake(_selectedItem.button.frame.origin.x - (_infinitePagingBoundsWidth - _selectedItem.width) * 0.5, 0); 596 | } 597 | 598 | #pragma mark - UIScrollViewDelegate 599 | - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView 600 | { 601 | if(_infinitePagingLastContentOffsetX == scrollView.contentOffset.x){ 602 | return; 603 | } 604 | 605 | if(!_infinitePagingIsTappedItem){ 606 | [self reorderItemsForInfinitePaging]; 607 | _scrollView.contentOffset = CGPointMake(_infinitePagingOffsetX, 0); 608 | 609 | NSInteger index = 0; 610 | RMPScrollingMenuBarItem* selectedItem = nil; 611 | for(NSValue* val in _infinitePagingOrder){ 612 | RMPScrollingMenuBarItem* item = [val nonretainedObjectValue]; 613 | 614 | if((NSInteger)(item.button.frame.origin.x) == (NSInteger)(_infinitePagingOffsetX + _itemInsets.left)){ 615 | selectedItem = item; 616 | } 617 | 618 | index++; 619 | } 620 | if(selectedItem && selectedItem != self.selectedItem){ 621 | [self setSelectedItem:selectedItem animated:YES]; 622 | } 623 | } 624 | 625 | _infinitePagingLastContentOffsetX = scrollView.contentOffset.x; 626 | } 627 | @end 628 | -------------------------------------------------------------------------------- /Pod/Classes/RMPScrollingMenuBarController.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Recruit Marketing Partners Co.,Ltd. All rights reserved. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #import 22 | #import "RMPScrollingMenuBar.h" 23 | 24 | @class RMPScrollingMenuBarController; 25 | 26 | typedef NS_ENUM(NSInteger, RMPMenuBarControllerDirection){ 27 | RMPScrollingMenuBarControllerDirectionLeft, 28 | RMPScrollingMenuBarControllerDirectionRight, 29 | }; 30 | 31 | /** ScrollingMenuBarController's Delegate 32 | */ 33 | @protocol RMPScrollingMenuBarControllerDelegate 34 | 35 | @optional 36 | /** The delegate method which be called before select menu item. 37 | */ 38 | - (void)menuBarController:(RMPScrollingMenuBarController*)menuBarController willSelectViewController:(UIViewController*)viewController; 39 | 40 | /** The delegate method which be called after select menu item. 41 | */ 42 | - (void)menuBarController:(RMPScrollingMenuBarController*)menuBarController didSelectViewController:(UIViewController*)viewController; 43 | 44 | /** The delegate method which be called after selection was canceled. 45 | */ 46 | - (void)menuBarController:(RMPScrollingMenuBarController*)menuBarController didCancelViewController:(UIViewController*)viewController; 47 | 48 | /** The delegate method which be called when set up menu bar items dynamically. 49 | */ 50 | - (RMPScrollingMenuBarItem*)menuBarController:(RMPScrollingMenuBarController*)menuBarController menuBarItemAtIndex:(NSInteger)index; 51 | 52 | @end 53 | 54 | // MenuBarController's delegate for view transitioning 55 | @protocol RMPScrollingMenuBarControllerTransitionDelegate 56 | 57 | @optional 58 | - (id )menuBarController:(RMPScrollingMenuBarController*)menuBarController 59 | animationControllerForDirection:(RMPMenuBarControllerDirection)direction 60 | fromViewController:(UIViewController *)fromViewController 61 | toViewController:(UIViewController *)toViewController; 62 | 63 | - (id)menuBarController:(RMPScrollingMenuBarController*)menuBarController 64 | interactionControllerForAnimationController:(id)animationController; 65 | @end 66 | 67 | /** Container type ViewController class of with a scrollable menu bar 68 | */ 69 | @interface RMPScrollingMenuBarController : UIViewController 70 | 71 | /** ScrollingMenuBar object. 72 | */ 73 | @property (nonatomic, readonly)RMPScrollingMenuBar* menuBar; 74 | 75 | /** Container view for presenting view of child view controller. 76 | */ 77 | @property (nonatomic, readonly)UIView* containerView; 78 | 79 | /** NSArray of child view controllers. 80 | */ 81 | @property (nonatomic, retain)NSArray* viewControllers; 82 | 83 | /** Selected view controller. 84 | */ 85 | @property (nonatomic, weak)UIViewController* selectedViewController; 86 | 87 | /** Index of selected view controller. 88 | */ 89 | @property (nonatomic, assign)NSInteger selectedIndex; 90 | 91 | /** Delegate object. 92 | */ 93 | @property (nonatomic, weak)id delegate; 94 | 95 | /** Transition Delegate object 96 | */ 97 | @property (nonatomic, weak)id transitionDelegate; 98 | 99 | /** Setter of view controllers. 100 | */ 101 | - (void)setViewControllers:(NSArray *)viewControllers animated:(BOOL)animated; 102 | 103 | 104 | @end 105 | 106 | #import "UIViewController+RMPScrollingMenuBarControllerHelper.h" 107 | -------------------------------------------------------------------------------- /Pod/Classes/RMPScrollingMenuBarController.m: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Recruit Marketing Partners Co.,Ltd. All rights reserved. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #import "RMPScrollingMenuBarController.h" 22 | #import "RMPScrollingMenuBarControllerTransition.h" 23 | 24 | @interface RMPScrollingMenuBarController () 25 | 26 | @end 27 | 28 | @implementation RMPScrollingMenuBarController { 29 | NSArray* _items; 30 | 31 | RMPScrollingMenuBarControllerTransition* _transition; 32 | 33 | RMPScrollingMenuBarDirection _menuBarDirection; 34 | } 35 | 36 | 37 | - (void)loadView 38 | { 39 | [super loadView]; 40 | 41 | self.automaticallyAdjustsScrollViewInsets = NO; 42 | self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 43 | [self.view setTranslatesAutoresizingMaskIntoConstraints:YES]; 44 | 45 | CGRect rect; 46 | // Menu bar 47 | rect = CGRectMake(0, 0, self.view.bounds.size.width, kRMPMenuBarDefaultBarHeight); 48 | RMPScrollingMenuBar* menuBar = [[RMPScrollingMenuBar alloc] initWithFrame:rect]; 49 | _menuBar = menuBar; 50 | CGFloat offset = 32.0f / 320.0f * [[UIScreen mainScreen] bounds].size.width; 51 | _menuBar.itemInsets = UIEdgeInsetsMake(2, offset, 0, offset); 52 | [self.view addSubview:menuBar]; 53 | [_menuBar sizeToFit]; 54 | rect = _menuBar.frame; 55 | rect.origin.y = [self.topLayoutGuide length]; 56 | _menuBar.frame = rect; 57 | _menuBar.delegate = self; 58 | _menuBar.backgroundColor = self.view.backgroundColor; 59 | 60 | // Container 61 | CGFloat y = CGRectGetMaxY(_menuBar.frame); 62 | rect = CGRectMake(0, y, 63 | self.view.bounds.size.width, 64 | self.view.bounds.size.height - y); 65 | UIView* containerView = [[UIView alloc] initWithFrame:rect]; 66 | _containerView = containerView; 67 | _containerView.backgroundColor = [UIColor colorWithWhite:0.8 alpha:1.0]; 68 | [self.view addSubview:_containerView]; 69 | 70 | [self.view insertSubview:self.containerView belowSubview:self.menuBar]; 71 | 72 | _transition = [[RMPScrollingMenuBarControllerTransition alloc] initWithMenuBarController:self]; 73 | self.transitionDelegate = _transition; 74 | 75 | if([_viewControllers count] > 0){ 76 | [self updateMenuBarWithViewControllers:_viewControllers animated:NO]; 77 | [self setSelectedViewController:_viewControllers[0]]; 78 | } 79 | } 80 | 81 | - (void)viewDidLoad { 82 | [super viewDidLoad]; 83 | // Do any additional setup after loading the view. 84 | } 85 | 86 | - (void)didReceiveMemoryWarning { 87 | [super didReceiveMemoryWarning]; 88 | // Dispose of any resources that can be recreated. 89 | } 90 | 91 | - (void)viewWillLayoutSubviews 92 | { 93 | [super viewWillLayoutSubviews]; 94 | 95 | CGRect rect; 96 | rect = CGRectMake(0, [self.topLayoutGuide length], self.view.bounds.size.width, _menuBar.barHeight); 97 | _menuBar.frame = rect; 98 | 99 | rect = CGRectMake(0, CGRectGetMaxY(_menuBar.frame), 100 | self.view.bounds.size.width, 101 | self.view.bounds.size.height - CGRectGetMaxY(_menuBar.frame)); 102 | _containerView.frame = rect; 103 | 104 | 105 | } 106 | 107 | - (void)viewDidAppear:(BOOL)animated 108 | { 109 | [super viewDidAppear:animated]; 110 | } 111 | 112 | #pragma mark - 113 | - (void)setViewControllers:(NSArray *)viewControllers 114 | { 115 | [self setViewControllers:viewControllers animated:NO]; 116 | } 117 | 118 | - (void)setViewControllers:(NSArray *)viewControllers animated:(BOOL)animated 119 | { 120 | _viewControllers = [viewControllers copy]; 121 | 122 | if(_menuBar){ 123 | [self updateMenuBarWithViewControllers:_viewControllers animated:animated]; 124 | } 125 | 126 | if([_viewControllers count] > 0){ 127 | [self setSelectedViewController:_viewControllers[0]]; 128 | } 129 | } 130 | 131 | - (void)updateMenuBarWithViewControllers:(NSArray*)viewControllers animated:(BOOL)animated 132 | { 133 | // Update menu bar items. 134 | NSMutableArray* items = [NSMutableArray array]; 135 | RMPScrollingMenuBarItem* item = nil; 136 | int i = 0; 137 | for(UIViewController* vc in viewControllers){ 138 | if([_delegate respondsToSelector:@selector(menuBarController:menuBarItemAtIndex:)]){ 139 | item = [_delegate menuBarController:self menuBarItemAtIndex:i]; 140 | }else { 141 | item = [RMPScrollingMenuBarItem item]; 142 | item.title = vc.title; 143 | item.tag = i; 144 | } 145 | [items addObject:item]; 146 | i++; 147 | } 148 | _items = [NSArray arrayWithArray:items]; 149 | 150 | [_menuBar setItems:_items animated:animated]; 151 | } 152 | 153 | - (void)setSelectedViewController:(UIViewController *)selectedViewController 154 | { 155 | if([_viewControllers containsObject:selectedViewController]){ 156 | [self transitionToViewController:selectedViewController]; 157 | } 158 | } 159 | 160 | - (void)setSelectedIndex:(NSInteger)selectedIndex 161 | { 162 | if(selectedIndex >= 0 163 | && selectedIndex < [_viewControllers count] 164 | && selectedIndex != _selectedIndex){ 165 | [self setSelectedViewController:_viewControllers[selectedIndex]]; 166 | } 167 | } 168 | 169 | #pragma mark - Private 170 | - (void)transitionToViewController:(UIViewController*)toViewController 171 | { 172 | UIViewController *fromViewController = _selectedViewController; 173 | // Do nothing if toViewController equals to fromViewController. 174 | if (toViewController == fromViewController || !_containerView) { 175 | return; 176 | } 177 | 178 | // Disabled the interaction of menu bar. 179 | _menuBar.userInteractionEnabled = NO; 180 | 181 | UIView *toView = toViewController.view; 182 | toView.frame = _containerView.bounds; 183 | [toView setTranslatesAutoresizingMaskIntoConstraints:YES]; 184 | toView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 185 | 186 | [fromViewController willMoveToParentViewController:nil]; 187 | [self addChildViewController:toViewController]; 188 | 189 | if([_delegate respondsToSelector:@selector(menuBarController:willSelectViewController:)]){ 190 | [_delegate menuBarController:self willSelectViewController:toViewController]; 191 | } 192 | 193 | // Present toViewController if not exist fromViewController. 194 | if (!fromViewController) { 195 | [_containerView addSubview:toViewController.view]; 196 | [toViewController didMoveToParentViewController:self]; 197 | 198 | // Reflect selection state. 199 | [self finishTransitionWithViewController:toViewController cancelViewController:nil]; 200 | 201 | return; 202 | } 203 | 204 | // Switch views with animation 205 | NSInteger fromIndex = [_viewControllers indexOfObject:fromViewController]; 206 | NSInteger toIndex = [_viewControllers indexOfObject:toViewController]; 207 | RMPMenuBarControllerDirection direction = RMPScrollingMenuBarControllerDirectionLeft; 208 | if(toIndex > fromIndex){ 209 | direction = RMPScrollingMenuBarControllerDirectionRight; 210 | } 211 | 212 | if(self.menuBar.style == RMPScrollingMenuBarStyleInfinitePaging){ 213 | if(toIndex == 0 && fromIndex == _viewControllers.count-1){ 214 | direction = RMPScrollingMenuBarControllerDirectionRight; 215 | }else if(toIndex == _viewControllers.count-1 && fromIndex == 0){ 216 | direction = RMPScrollingMenuBarControllerDirectionLeft; 217 | } 218 | 219 | if(_menuBarDirection == RMPScrollingMenuBarDirectionRight){ 220 | direction = RMPScrollingMenuBarControllerDirectionRight; 221 | }else if(_menuBarDirection == RMPScrollingMenuBarDirectionLeft){ 222 | direction = RMPScrollingMenuBarControllerDirectionLeft; 223 | } 224 | _menuBarDirection = RMPScrollingMenuBarDirectionNone; 225 | } 226 | 227 | id animator = nil; 228 | if ([_transitionDelegate respondsToSelector:@selector(menuBarController:animationControllerForDirection:fromViewController:toViewController:)]) { 229 | animator = [_transitionDelegate menuBarController:self 230 | animationControllerForDirection:direction 231 | fromViewController:fromViewController 232 | toViewController:toViewController]; 233 | } 234 | animator = (animator ?: [[RMPScrollingMenuBarControllerAnimator alloc] init]); 235 | 236 | UIPercentDrivenInteractiveTransition* interactionController = nil; 237 | if([_transitionDelegate respondsToSelector:@selector(menuBarController:interactionControllerForAnimationController:)]) { 238 | interactionController = [_transitionDelegate menuBarController:self 239 | interactionControllerForAnimationController:animator]; 240 | } 241 | 242 | RMPScrollingMenuBarControllerTransitionContextCompletionBlock completion = ^(BOOL didComplete){ 243 | if(didComplete){ 244 | [fromViewController.view removeFromSuperview]; 245 | [fromViewController removeFromParentViewController]; 246 | [toViewController didMoveToParentViewController:self]; 247 | 248 | // Reflect selection state. 249 | [self finishTransitionWithViewController:toViewController cancelViewController:nil]; 250 | }else { 251 | // Remove toViewController from parent view controller by cancelled. 252 | [toViewController.view removeFromSuperview]; 253 | [toViewController removeFromParentViewController]; 254 | [toViewController didMoveToParentViewController:nil]; 255 | 256 | // Reflect selection state. 257 | [self finishTransitionWithViewController:fromViewController cancelViewController:toViewController]; 258 | } 259 | 260 | 261 | }; 262 | 263 | RMPScrollingMenuBarControllerTransitionContext* transitionContext = nil; 264 | transitionContext = [[RMPScrollingMenuBarControllerTransitionContext alloc] initWithMenuBarController:self 265 | fromViewController:fromViewController 266 | toViewController:toViewController 267 | direction:direction 268 | animator:animator 269 | interactionController:interactionController 270 | completion:completion]; 271 | 272 | 273 | 274 | if(transitionContext.isInteractive){ 275 | [interactionController startInteractiveTransition:transitionContext]; 276 | }else { 277 | [animator animateTransition:transitionContext]; 278 | } 279 | } 280 | 281 | - (void)finishTransitionWithViewController:(UIViewController*)viewController cancelViewController:(UIViewController*)cancelViewController 282 | { 283 | NSInteger lastIndex = _selectedIndex; 284 | UIViewController* lastViewController = _selectedViewController; 285 | 286 | // Reflect selection state. 287 | _selectedViewController = viewController; 288 | _selectedIndex = [_viewControllers indexOfObject:viewController]; 289 | 290 | // Update menu bar. 291 | RMPScrollingMenuBarItem* item = _menuBar.items[_selectedIndex]; 292 | if(item != _menuBar.selectedItem){ 293 | [_menuBar setSelectedItem:item]; 294 | } 295 | 296 | // Call delegate method. 297 | if(lastIndex != _selectedIndex || lastViewController != _selectedViewController){ 298 | if([_delegate respondsToSelector:@selector(menuBarController:didSelectViewController:)]){ 299 | [_delegate menuBarController:self didSelectViewController:_selectedViewController]; 300 | } 301 | }else { 302 | if([_delegate respondsToSelector:@selector(menuBarController:didCancelViewController:)]){ 303 | [_delegate menuBarController:self didCancelViewController:cancelViewController]; 304 | } 305 | } 306 | 307 | _menuBar.userInteractionEnabled = YES; 308 | } 309 | 310 | #pragma mark - RMPScrollingMenuBarDelegate 311 | - (void)menuBar:(RMPScrollingMenuBar*)menuBar didSelectItem:(RMPScrollingMenuBarItem*)item direction:(RMPScrollingMenuBarDirection)direction 312 | { 313 | NSInteger index = [_items indexOfObject:item]; 314 | if(index != NSNotFound 315 | && index != self.selectedIndex){ 316 | // Switch view controller. 317 | _menuBarDirection = direction; 318 | [self setSelectedIndex:index]; 319 | } 320 | } 321 | @end 322 | -------------------------------------------------------------------------------- /Pod/Classes/RMPScrollingMenuBarControllerAnimator.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Recruit Marketing Partners Co.,Ltd. All rights reserved. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #import 22 | 23 | /** Transitioning Object for view transitioning of Scrolling menu bar controller. 24 | */ 25 | @interface RMPScrollingMenuBarControllerAnimator : NSObject 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /Pod/Classes/RMPScrollingMenuBarControllerAnimator.m: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Recruit Marketing Partners Co.,Ltd. All rights reserved. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #import "RMPScrollingMenuBarControllerAnimator.h" 22 | #import "RMPScrollingMenuBarControllerTransition.h" 23 | 24 | @implementation RMPScrollingMenuBarControllerAnimator { 25 | RMPScrollingMenuBarControllerTransitionContext* _transitionContext; 26 | } 27 | 28 | - (NSTimeInterval)transitionDuration:(id )transitionContext 29 | { 30 | return 0.3; 31 | } 32 | 33 | - (void)animateTransition:(id)transitionContext 34 | { 35 | RMPScrollingMenuBarControllerTransitionContext* tc = (RMPScrollingMenuBarControllerTransitionContext*)transitionContext; 36 | 37 | UIViewController* toViewController = [tc viewControllerForKey:UITransitionContextToViewControllerKey]; 38 | UIViewController* fromViewController = [tc viewControllerForKey:UITransitionContextFromViewControllerKey]; 39 | 40 | [[transitionContext containerView] addSubview:toViewController.view]; 41 | [[transitionContext containerView] insertSubview:toViewController.view belowSubview:fromViewController.view]; 42 | 43 | _transitionContext = tc; 44 | 45 | CGRect fromInitialFrame = [tc initialFrameForViewController:fromViewController]; 46 | CGRect fromFinalFrame = [tc finalFrameForViewController:fromViewController]; 47 | CGRect toInitialFrame = [tc initialFrameForViewController:toViewController]; 48 | CGRect toFinalFrame = [tc finalFrameForViewController:toViewController]; 49 | fromViewController.view.frame = fromInitialFrame; 50 | toViewController.view.frame = toInitialFrame; 51 | //fromViewController.view.alpha = 1.0; 52 | //toViewController.view.alpha = 1.0; 53 | 54 | [CATransaction begin]; 55 | CGPoint point; 56 | 57 | // Animation of fromView 58 | CABasicAnimation* fromViewAnimation = [CABasicAnimation animationWithKeyPath:@"position"]; 59 | point = fromInitialFrame.origin; 60 | point.x += fromInitialFrame.size.width*0.5; 61 | point.y += fromInitialFrame.size.height*0.5; 62 | [fromViewAnimation setFromValue:[NSValue valueWithCGPoint:point]]; 63 | point = fromFinalFrame.origin; 64 | point.x += fromFinalFrame.size.width*0.5; 65 | point.y += fromFinalFrame.size.height*0.5; 66 | [fromViewAnimation setToValue:[NSValue valueWithCGPoint:point]]; 67 | [fromViewAnimation setDuration:[self transitionDuration:transitionContext]]; 68 | [fromViewAnimation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]]; 69 | // Maintain final animation state. 70 | [fromViewAnimation setRemovedOnCompletion:NO]; 71 | [fromViewAnimation setFillMode:kCAFillModeForwards]; 72 | [fromViewController.view.layer addAnimation:fromViewAnimation forKey:@"from_transition"]; 73 | 74 | // Animation of toView 75 | CABasicAnimation* toViewAnimation = [CABasicAnimation animationWithKeyPath:@"position"]; 76 | point = toInitialFrame.origin; 77 | point.x += toInitialFrame.size.width*0.5; 78 | point.y += toInitialFrame.size.height*0.5; 79 | [toViewAnimation setFromValue:[NSValue valueWithCGPoint:point]]; 80 | point = toFinalFrame.origin; 81 | point.x += toFinalFrame.size.width*0.5; 82 | point.y += toFinalFrame.size.height*0.5; 83 | [toViewAnimation setToValue:[NSValue valueWithCGPoint:point]]; 84 | [toViewAnimation setDuration:[self transitionDuration:transitionContext]]; 85 | [toViewAnimation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]]; 86 | // Maintain final animation state. 87 | [toViewAnimation setRemovedOnCompletion:NO]; 88 | [toViewAnimation setFillMode:kCAFillModeForwards]; 89 | [toViewAnimation setDelegate:self]; 90 | [toViewController.view.layer addAnimation:toViewAnimation forKey:@"to_transition"]; 91 | 92 | [CATransaction commit]; 93 | } 94 | 95 | - (void)animationDidStart:(CAAnimation *)anim 96 | { 97 | 98 | } 99 | 100 | - (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag 101 | { 102 | UIViewController* toViewController = [_transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; 103 | UIViewController* fromViewController = [_transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]; 104 | if([_transitionContext transitionWasCancelled]){ 105 | fromViewController.view.frame = [_transitionContext initialFrameForViewController:fromViewController]; 106 | toViewController.view.frame = [_transitionContext initialFrameForViewController:toViewController]; 107 | }else { 108 | fromViewController.view.frame = [_transitionContext finalFrameForViewController:fromViewController]; 109 | toViewController.view.frame = [_transitionContext finalFrameForViewController:toViewController]; 110 | } 111 | [_transitionContext completeTransition:![_transitionContext transitionWasCancelled]]; 112 | 113 | // Remove animations 114 | [fromViewController.view.layer removeAllAnimations]; 115 | [toViewController.view.layer removeAllAnimations]; 116 | } 117 | 118 | 119 | @end 120 | -------------------------------------------------------------------------------- /Pod/Classes/RMPScrollingMenuBarControllerTransition.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Recruit Marketing Partners Co.,Ltd. All rights reserved. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #import 22 | #import "RMPScrollingMenuBarController.h" 23 | #import "RMPScrollingMenuBarControllerAnimator.h" 24 | 25 | typedef void(^RMPScrollingMenuBarControllerTransitionContextCompletionBlock)(BOOL didComplete); 26 | typedef void(^RMPScrollingMenuBarControllerInteractionControllerCancelCompletionBlock)(); 27 | 28 | /** Transition Delegate Object for view transitioning of Scrolling menu bar controller. 29 | */ 30 | @interface RMPScrollingMenuBarControllerTransition : NSObject 31 | 32 | - (instancetype)initWithMenuBarController:(RMPScrollingMenuBarController*)controller; 33 | 34 | @end 35 | 36 | /** InteractionController class for view transitioning of scrolling menu bar controller. 37 | */ 38 | @interface RMPScrollingMenuBarControllerInteractionController : NSObject 39 | 40 | @property(readonly) CGFloat percentComplete; 41 | 42 | 43 | - (instancetype)initWithAnimator:(id)animator; 44 | - (void)startInteractiveTransition:(id)context; 45 | - (void)updateInteractiveTransition:(CGFloat)percentComplete; 46 | - (void)cancelInteractiveTransitionWithCompletion:(RMPScrollingMenuBarControllerInteractionControllerCancelCompletionBlock)completion; 47 | - (void)finishInteractiveTransition; 48 | 49 | - (UIViewAnimationCurve)completionCurve; 50 | - (CGFloat)completionSpeed; 51 | @end 52 | 53 | /** TransitionContext class for view transitioning of scrolling menu bar controller. 54 | */ 55 | @interface RMPScrollingMenuBarControllerTransitionContext : NSObject 56 | 57 | @property (nonatomic, readonly)UIView* containerView; 58 | @property (nonatomic, readonly, getter=isAnimated)BOOL animated; 59 | @property (nonatomic, readonly, getter=isInteractive)BOOL interactive; 60 | @property (nonatomic, readonly)UIModalPresentationStyle presentationStyle; 61 | @property (nonatomic, readonly)RMPMenuBarControllerDirection direction; 62 | 63 | - (instancetype)initWithMenuBarController:(RMPScrollingMenuBarController*)menuBarControlller 64 | fromViewController:(UIViewController*)fromVC 65 | toViewController:(UIViewController*)toVC 66 | direction:(RMPMenuBarControllerDirection)direction 67 | animator:(RMPScrollingMenuBarControllerAnimator*)animator 68 | interactionController:(id)interactionController 69 | completion:(RMPScrollingMenuBarControllerTransitionContextCompletionBlock)completion; 70 | 71 | - (UIViewController *)viewControllerForKey:(NSString *)key; 72 | - (void)updateInteractiveTransition:(CGFloat)percentComplete; 73 | - (void)finishInteractiveTransition; 74 | - (void)cancelInteractiveTransition; 75 | - (BOOL)transitionWasCancelled; 76 | - (void)completeTransition:(BOOL)didComplete; 77 | - (CGRect)initialFrameForViewController:(UIViewController *)vc; 78 | - (CGRect)finalFrameForViewController:(UIViewController *)vc; 79 | @end 80 | -------------------------------------------------------------------------------- /Pod/Classes/RMPScrollingMenuBarControllerTransition.m: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Recruit Marketing Partners Co.,Ltd. All rights reserved. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #import "RMPScrollingMenuBarControllerTransition.h" 22 | 23 | @interface RMPScrollingMenuBarControllerTransition () 24 | 25 | 26 | @end 27 | 28 | @implementation RMPScrollingMenuBarControllerTransition { 29 | __weak RMPScrollingMenuBarController* _menuBarController; 30 | RMPScrollingMenuBarControllerAnimator* _animator; 31 | 32 | UIPanGestureRecognizer* _panGesture; 33 | 34 | RMPScrollingMenuBarControllerInteractionController* _interactionController; 35 | 36 | RMPMenuBarControllerDirection _direction; 37 | } 38 | 39 | - (instancetype)initWithMenuBarController:(RMPScrollingMenuBarController*)controller 40 | { 41 | self = [super init]; 42 | if(self){ 43 | _menuBarController = controller; 44 | [self setup]; 45 | } 46 | return self; 47 | } 48 | 49 | - (void)setup 50 | { 51 | _animator = [[RMPScrollingMenuBarControllerAnimator alloc] init]; 52 | _panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(didDetectPanGesture:)]; 53 | [_menuBarController.containerView addGestureRecognizer:_panGesture]; 54 | } 55 | 56 | #pragma mark - gesture action 57 | - (void)didDetectPanGesture:(UIPanGestureRecognizer*)gesture 58 | { 59 | UIView* view = _menuBarController.containerView; 60 | if (gesture.state == UIGestureRecognizerStateBegan) { 61 | CGPoint location = [gesture locationInView:view]; 62 | if (location.x < CGRectGetMidX(view.bounds) 63 | && _menuBarController.viewControllers.count > 1) { 64 | // to left side menu item. 65 | if(_menuBarController.menuBar.style == RMPScrollingMenuBarStyleNormal 66 | && _menuBarController.selectedIndex > 0){ 67 | _direction = RMPScrollingMenuBarControllerDirectionLeft; 68 | _interactionController = [[RMPScrollingMenuBarControllerInteractionController alloc] initWithAnimator:_animator]; 69 | UIViewController* vc = _menuBarController.viewControllers[_menuBarController.selectedIndex-1]; 70 | [_menuBarController setSelectedViewController:vc]; 71 | }else if(_menuBarController.menuBar.style == RMPScrollingMenuBarStyleInfinitePaging 72 | && _menuBarController.selectedIndex >= 0){ 73 | _direction = RMPScrollingMenuBarControllerDirectionLeft; 74 | _interactionController = [[RMPScrollingMenuBarControllerInteractionController alloc] initWithAnimator:_animator]; 75 | NSInteger index = _menuBarController.selectedIndex-1; 76 | if(index < 0) index = _menuBarController.viewControllers.count - 1; 77 | UIViewController* vc = _menuBarController.viewControllers[index]; 78 | [_menuBarController setSelectedViewController:vc]; 79 | } 80 | }else if(location.x >= CGRectGetMidX(view.bounds) 81 | && _menuBarController.viewControllers.count > 1){ 82 | // to right side menu item. 83 | if(_menuBarController.menuBar.style == RMPScrollingMenuBarStyleNormal 84 | && _menuBarController.selectedIndex < [_menuBarController.viewControllers count]-1){ 85 | _direction = RMPScrollingMenuBarControllerDirectionRight; 86 | _interactionController = [[RMPScrollingMenuBarControllerInteractionController alloc] initWithAnimator:_animator]; 87 | UIViewController* vc = _menuBarController.viewControllers[_menuBarController.selectedIndex+1]; 88 | [_menuBarController setSelectedViewController:vc]; 89 | }else if(_menuBarController.menuBar.style == RMPScrollingMenuBarStyleInfinitePaging 90 | && _menuBarController.selectedIndex <= [_menuBarController.viewControllers count]-1){ 91 | _direction = RMPScrollingMenuBarControllerDirectionRight; 92 | _interactionController = [[RMPScrollingMenuBarControllerInteractionController alloc] initWithAnimator:_animator]; 93 | NSInteger index = _menuBarController.selectedIndex+1; 94 | if(index > _menuBarController.viewControllers.count - 1) index = 0; 95 | UIViewController* vc = _menuBarController.viewControllers[index]; 96 | [_menuBarController setSelectedViewController:vc]; 97 | } 98 | } 99 | } else if (gesture.state == UIGestureRecognizerStateChanged) { 100 | CGPoint translation = [gesture translationInView:view]; 101 | // Only if moving direction was matched, Updates the interaction controller. 102 | if((_direction == RMPScrollingMenuBarControllerDirectionLeft && translation.x > 0) 103 | || (_direction == RMPScrollingMenuBarControllerDirectionRight && translation.x < 0)){ 104 | CGFloat d = fabs(translation.x / CGRectGetWidth(view.bounds)); 105 | [_interactionController updateInteractiveTransition:d]; 106 | } 107 | } else if (gesture.state == UIGestureRecognizerStateEnded) { 108 | //If progress is less than 15%, Cancel transition. 109 | if (_interactionController.percentComplete > 0.15f) { 110 | [_interactionController finishInteractiveTransition]; 111 | } else { 112 | if(_interactionController){ 113 | // be disabled recognizing pan gesture during animation for canceling transition. 114 | _panGesture.enabled = NO; 115 | [_interactionController cancelInteractiveTransitionWithCompletion:^{ 116 | _panGesture.enabled = YES; 117 | }]; 118 | } 119 | } 120 | _interactionController = nil; 121 | } 122 | } 123 | 124 | #pragma mark - RMPScrollingMenuBarControllerTransitionDelegate 125 | - (id )menuBarController:(RMPScrollingMenuBarController*)menuBarController 126 | animationControllerForDirection:(RMPMenuBarControllerDirection)direction 127 | fromViewController:(UIViewController *)fromViewController 128 | toViewController:(UIViewController *)toViewController 129 | { 130 | return _animator; 131 | } 132 | 133 | - (id)menuBarController:(RMPScrollingMenuBarController*)menuBarController 134 | interactionControllerForAnimationController:(id)animationController 135 | { 136 | return _interactionController; 137 | } 138 | 139 | @end 140 | 141 | #pragma mark - 142 | @implementation RMPScrollingMenuBarControllerInteractionController { 143 | id _animator; 144 | id _context; 145 | 146 | CADisplayLink* _displayLink; 147 | 148 | RMPScrollingMenuBarControllerInteractionControllerCancelCompletionBlock _completion; 149 | } 150 | 151 | - (instancetype)initWithAnimator:(id)animator 152 | { 153 | self = [super init]; 154 | if(self){ 155 | _animator = animator; 156 | } 157 | return self; 158 | } 159 | 160 | - (void)startInteractiveTransition:(id)context 161 | { 162 | _context = context; 163 | _context.containerView.layer.speed = 0; 164 | [_animator animateTransition:_context]; 165 | } 166 | 167 | - (void)updateInteractiveTransition:(CGFloat)percentComplete 168 | { 169 | _percentComplete = percentComplete; 170 | NSTimeInterval duration = [_animator transitionDuration:_context]; 171 | _context.containerView.layer.timeOffset = percentComplete*duration; 172 | [_context updateInteractiveTransition:percentComplete]; 173 | } 174 | 175 | - (void)cancelInteractiveTransitionWithCompletion:(RMPScrollingMenuBarControllerInteractionControllerCancelCompletionBlock)completion 176 | { 177 | _completion = completion; 178 | 179 | _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateCancelAnimation)]; 180 | [_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; 181 | } 182 | 183 | - (void)finishInteractiveTransition 184 | { 185 | _context.containerView.layer.speed = self.completionSpeed; 186 | 187 | CFTimeInterval pausedTimeOffset = _context.containerView.layer.timeOffset; 188 | _context.containerView.layer.timeOffset = 0.0; 189 | _context.containerView.layer.beginTime = 0.0; 190 | CFTimeInterval newBeginTime = [_context.containerView.layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTimeOffset; 191 | _context.containerView.layer.beginTime = newBeginTime; 192 | 193 | [_context finishInteractiveTransition]; 194 | } 195 | 196 | - (UIViewAnimationCurve)completionCurve 197 | { 198 | return UIViewAnimationCurveLinear; 199 | } 200 | 201 | - (CGFloat)completionSpeed 202 | { 203 | return 1.0f; 204 | } 205 | 206 | - (void)updateCancelAnimation 207 | { 208 | // Rollback animation when cancelled. 209 | NSTimeInterval timeOffset = _context.containerView.layer.timeOffset - _displayLink.duration*0.3; 210 | if(timeOffset < 0){ 211 | // Completed rollback. 212 | 213 | [_displayLink invalidate]; 214 | _displayLink = nil; 215 | 216 | _context.containerView.layer.speed = self.completionSpeed; 217 | _context.containerView.layer.timeOffset = 0.0; 218 | 219 | [_context updateInteractiveTransition:timeOffset/[_animator transitionDuration:_context]]; 220 | 221 | UIViewController* toViewController = [_context viewControllerForKey:UITransitionContextToViewControllerKey]; 222 | [toViewController.view.layer removeAllAnimations]; 223 | UIViewController* fromViewController = [_context viewControllerForKey:UITransitionContextFromViewControllerKey]; 224 | [fromViewController.view.layer removeAllAnimations]; 225 | 226 | [_context cancelInteractiveTransition]; 227 | 228 | if(_completion){ 229 | _completion(); 230 | } 231 | }else { 232 | _context.containerView.layer.timeOffset = timeOffset; 233 | 234 | [_context updateInteractiveTransition:timeOffset/[_animator transitionDuration:_context]]; 235 | } 236 | } 237 | 238 | @end 239 | 240 | #pragma mark - 241 | @implementation RMPScrollingMenuBarControllerTransitionContext { 242 | RMPScrollingMenuBarController* _menuBarController; 243 | NSDictionary* _viewControllers; 244 | RMPScrollingMenuBarControllerAnimator* _animator; 245 | RMPScrollingMenuBarControllerTransitionContextCompletionBlock _completion; 246 | BOOL _isCancelled; 247 | 248 | CGRect _appearingToRect; 249 | CGRect _appearingFromRect; 250 | CGRect _disappearingToRect; 251 | CGRect _disappearingFromRect; 252 | 253 | CGFloat _fromOffsetX; 254 | } 255 | 256 | - (instancetype)initWithMenuBarController:(RMPScrollingMenuBarController*)menuBarControlller 257 | fromViewController:(UIViewController*)fromVC 258 | toViewController:(UIViewController*)toVC 259 | direction:(RMPMenuBarControllerDirection)direction 260 | animator:(RMPScrollingMenuBarControllerAnimator*)animator 261 | interactionController:(id)interactionController 262 | completion:(RMPScrollingMenuBarControllerTransitionContextCompletionBlock)completion; 263 | { 264 | self = [super init]; 265 | if(self){ 266 | _menuBarController = menuBarControlller; 267 | _presentationStyle = UIModalPresentationNone; 268 | _interactive = (interactionController) ? YES : NO; 269 | _containerView = _menuBarController.containerView; 270 | _viewControllers = @{ 271 | UITransitionContextFromViewControllerKey:fromVC, 272 | UITransitionContextToViewControllerKey:toVC, 273 | }; 274 | _direction = direction; 275 | _animator = animator; 276 | _completion = [completion copy]; 277 | _isCancelled = NO; 278 | 279 | CGFloat offset = _containerView.bounds.size.width; 280 | offset *= (_direction == RMPScrollingMenuBarControllerDirectionRight) ? -1 : 1; 281 | _disappearingFromRect = _appearingToRect = _containerView.bounds; 282 | _disappearingToRect = CGRectOffset (_containerView.bounds, offset, 0); 283 | _appearingFromRect = CGRectOffset (_containerView.bounds, -offset, 0); 284 | } 285 | return self; 286 | } 287 | 288 | - (UIViewController *)viewControllerForKey:(NSString *)key 289 | { 290 | return [_viewControllers objectForKey:key]; 291 | } 292 | 293 | - (UIView*)viewForKey:(NSString *)key 294 | { 295 | return [[_viewControllers objectForKey:key] view]; 296 | } 297 | 298 | - (void)updateInteractiveTransition:(CGFloat)percentComplete 299 | { 300 | if(!_animated){ 301 | _fromOffsetX = _menuBarController.menuBar.scrollOffsetX; 302 | } 303 | 304 | _animated = YES; 305 | 306 | [_menuBarController.menuBar scrollByRatio:percentComplete * ((_direction == RMPScrollingMenuBarControllerDirectionRight) ? 1 : -1) 307 | from:_fromOffsetX]; 308 | } 309 | 310 | - (void)finishInteractiveTransition 311 | { 312 | _isCancelled = NO; 313 | _animated = NO; 314 | } 315 | 316 | - (void)cancelInteractiveTransition 317 | { 318 | _isCancelled = YES; 319 | _animated = NO; 320 | } 321 | 322 | - (BOOL)transitionWasCancelled 323 | { 324 | return _isCancelled; 325 | } 326 | 327 | - (void)completeTransition:(BOOL)didComplete 328 | { 329 | if(_completion){ 330 | _completion(didComplete); 331 | } 332 | 333 | if ([_animator respondsToSelector:@selector (animationEnded:)]) { 334 | [_animator animationEnded:didComplete]; 335 | } 336 | _animated = NO; 337 | } 338 | 339 | - (CGRect)initialFrameForViewController:(UIViewController *)vc 340 | { 341 | if (vc == [self viewControllerForKey:UITransitionContextFromViewControllerKey]) { 342 | return _disappearingFromRect; 343 | } else { 344 | return _appearingFromRect; 345 | } 346 | } 347 | 348 | - (CGRect)finalFrameForViewController:(UIViewController *)vc 349 | { 350 | if (vc == [self viewControllerForKey:UITransitionContextFromViewControllerKey]) { 351 | return _disappearingToRect; 352 | } else { 353 | return _appearingToRect; 354 | } 355 | } 356 | 357 | - (CGAffineTransform)targetTransform 358 | { 359 | return CGAffineTransformIdentity; 360 | } 361 | @end 362 | -------------------------------------------------------------------------------- /Pod/Classes/RMPScrollingMenuBarItem.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Recruit Marketing Partners Co.,Ltd. All rights reserved. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #import 22 | 23 | #define kRMPScrollingMenuBarItemDefaultWidth 90.0f 24 | 25 | /** MenuBar's button class 26 | */ 27 | @interface RMPScrollingMenuBarButton : UIButton 28 | 29 | + (instancetype)button; 30 | 31 | @end 32 | 33 | /** MenuBar's item class 34 | */ 35 | @interface RMPScrollingMenuBarItem : NSObject 36 | 37 | @property (nonatomic, strong)NSString* title; 38 | @property (nonatomic, assign)NSInteger tag; 39 | @property (nonatomic, assign)CGFloat width; 40 | @property (nonatomic, assign, getter=isEnabled)BOOL enabled; 41 | @property (nonatomic, assign, getter=isSelected)BOOL selected; 42 | 43 | + (instancetype)item; 44 | 45 | - (RMPScrollingMenuBarButton*)button; 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /Pod/Classes/RMPScrollingMenuBarItem.m: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Recruit Marketing Partners Co.,Ltd. All rights reserved. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #import "RMPScrollingMenuBarItem.h" 22 | 23 | @implementation RMPScrollingMenuBarButton { 24 | 25 | } 26 | 27 | + (instancetype)button 28 | { 29 | RMPScrollingMenuBarButton* button = [self buttonWithType:UIButtonTypeCustom]; 30 | 31 | return button; 32 | } 33 | 34 | @end 35 | 36 | @implementation RMPScrollingMenuBarItem { 37 | RMPScrollingMenuBarButton* _itemButton; 38 | CGFloat _width; 39 | } 40 | 41 | + (instancetype)item 42 | { 43 | return [[self alloc] init]; 44 | } 45 | 46 | - (instancetype)init 47 | { 48 | self = [super init]; 49 | if(self){ 50 | _width = kRMPScrollingMenuBarItemDefaultWidth; 51 | _enabled = YES; 52 | } 53 | return self; 54 | } 55 | 56 | - (RMPScrollingMenuBarButton*)button 57 | { 58 | if(!_itemButton){ 59 | RMPScrollingMenuBarButton* button = [RMPScrollingMenuBarButton button]; 60 | _itemButton = button; 61 | _itemButton.tag = self.tag; 62 | _itemButton.frame = CGRectMake(0, 0, _width, 24); 63 | 64 | _itemButton.titleLabel.font = [UIFont systemFontOfSize:16.0]; 65 | [_itemButton setTitle:self.title 66 | forState:UIControlStateNormal]; 67 | [_itemButton setTitleColor:[UIColor colorWithRed:0.647 green:0.631 blue:0.604 alpha:1.000] 68 | forState:UIControlStateNormal]; 69 | [_itemButton setTitleColor:[UIColor colorWithWhite:0.886 alpha:1.000] 70 | forState:UIControlStateDisabled]; 71 | [_itemButton setTitleColor:[UIColor colorWithRed:0.988 green:0.224 blue:0.129 alpha:1.000] 72 | forState:UIControlStateSelected]; 73 | _itemButton.enabled = _enabled; 74 | _itemButton.exclusiveTouch = NO; 75 | [_itemButton sizeToFit]; 76 | } 77 | return _itemButton; 78 | } 79 | 80 | - (CGFloat)width 81 | { 82 | return _itemButton.frame.size.width; 83 | } 84 | 85 | - (void)setWidth:(CGFloat)width 86 | { 87 | _width = width; 88 | _itemButton.frame = CGRectMake(0, 0, _width, 36); 89 | [_itemButton sizeToFit]; 90 | } 91 | 92 | - (void)setEnabled:(BOOL)enabled 93 | { 94 | _enabled = enabled; 95 | _itemButton.enabled = _enabled; 96 | } 97 | 98 | - (void)setSelected:(BOOL)selected 99 | { 100 | _selected = selected; 101 | _itemButton.selected = selected; 102 | } 103 | 104 | - (NSString*)description 105 | { 106 | return [NSString stringWithFormat:@"", self.title, NSStringFromCGRect(self.button.frame)]; 107 | } 108 | 109 | @end 110 | -------------------------------------------------------------------------------- /Pod/Classes/UIViewController+RMPScrollingMenuBarControllerHelper.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Recruit Marketing Partners Co.,Ltd. All rights reserved. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #import 22 | #import "RMPScrollingMenuBarController.h" 23 | 24 | /** ScrollingMenuBarController's Helper Category 25 | */ 26 | @interface UIViewController (RMPScrollingMenuBarControllerHelper) 27 | 28 | /** Return the parent menu bar controller. 29 | */ 30 | - (RMPScrollingMenuBarController*)menuBarController; 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /Pod/Classes/UIViewController+RMPScrollingMenuBarControllerHelper.m: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Recruit Marketing Partners Co.,Ltd. All rights reserved. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #import "UIViewController+RMPScrollingMenuBarControllerHelper.h" 22 | 23 | @implementation UIViewController (RMPScrollingMenuBarControllerHelper) 24 | 25 | - (RMPScrollingMenuBarController*)menuBarController { 26 | RMPScrollingMenuBarController* menuBar = nil; 27 | 28 | if(self.parentViewController){ 29 | if([self.parentViewController isKindOfClass:[RMPScrollingMenuBarController class]]){ 30 | menuBar = (RMPScrollingMenuBarController*)self.parentViewController; 31 | }else { 32 | menuBar = [self.parentViewController menuBarController]; 33 | } 34 | } 35 | 36 | return menuBar; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RMPScrollingMenuBarController 2 | 3 | [![Version](https://img.shields.io/cocoapods/v/RMPScrollingMenuBarController.svg?style=flat)](http://cocoadocs.org/docsets/RMPScrollingMenuBarController) 4 | [![License](https://img.shields.io/cocoapods/l/RMPScrollingMenuBarController.svg?style=flat)](http://cocoadocs.org/docsets/RMPScrollingMenuBarController) 5 | [![Platform](https://img.shields.io/cocoapods/p/RMPScrollingMenuBarController.svg?style=flat)](http://cocoadocs.org/docsets/RMPScrollingMenuBarController) 6 | 7 | ## Overview 8 | 9 | `RMPScrollingMenuBarController` has a scrollable menu bar, and multiple view controllers. 10 | 11 | You can switch view controllers, which is managed like a `UITabBarController`, by swiping a screen or scrolling the menu. 12 | 13 | 14 | ![Screen shot](docs/rmpscrollingmenubarcontroller.gif) 15 | 16 | ## Installation 17 | 18 | RMPScrollingMenuBarController is available through [CocoaPods](http://cocoapods.org). 19 | To install 20 | it, simply add the following line to your Podfile: 21 | 22 | ```ruby 23 | pod "RMPScrollingMenuBarController" 24 | ``` 25 | 26 | ## Usage 27 | 28 | To run the example project, clone the repo, and run `pod install` from the Example directory first. 29 | 30 | Setup is as below: 31 | ```objective-c 32 | RMPScrollingMenuBarController* menuController = [[RMPScrollingMenuBarController alloc] init]; 33 | menuController.delegate = self; 34 | 35 | NSArray* viewControllers = @[vc1, vc2, vc3, vc4, vc5]; 36 | [menuController setViewControllers:viewControllers]; 37 | 38 | UINavigationController* naviController; 39 | naviController = [[UINavigationController alloc] initWithRootViewController:menuController]; 40 | ``` 41 | 42 | Delegate methods are as below: 43 | ```objective-c 44 | - (RMPScrollingMenuBarItem*)menuBarController:(RMPScrollingMenuBarController *)menuBarController 45 | menuBarItemAtIndex:(NSInteger)index 46 | { 47 | RMPScrollingMenuBarItem* item = [[RMPScrollingMenuBarItem alloc] init]; 48 | item.title = [NSString stringWithFormat:@"Title %02ld", (long)(index+1)]; 49 | 50 | return item; 51 | } 52 | 53 | - (void)menuBarController:(RMPScrollingMenuBarController *)menuBarController 54 | willSelectViewController:(UIViewController *)viewController 55 | { 56 | NSLog(@"will select %@", viewController); 57 | } 58 | 59 | - (void)menuBarController:(RMPScrollingMenuBarController *)menuBarController 60 | didSelectViewController:(UIViewController *)viewController 61 | { 62 | NSLog(@"did select %@", viewController); 63 | } 64 | 65 | - (void)menuBarController:(RMPScrollingMenuBarController *)menuBarController 66 | didCancelViewController:(UIViewController *)viewController 67 | { 68 | NSLog(@"did cancel %@", viewController); 69 | } 70 | 71 | ``` 72 | 73 | ## Customize 74 | 75 | You can customize menu bar, as below: 76 | ```objective-c 77 | RMPScrollingMenuBarController* menuController = [[RMPScrollingMenuBarController alloc] init]; 78 | 79 | // Sets background color. 80 | menuController.view.backgroundColor = [UIColor whiteColor]; 81 | 82 | // Sets color of indicator line which displayed under menu bar item. 83 | menuController.menuBar.indicatorColor = [UIColor blueColor]; 84 | 85 | // Hides indicator line which displayed under menu bar item. 86 | menuController.menuBar.showsIndicator = NO; 87 | 88 | // Hides Separator line which displayed bottom of menu bar. 89 | menuController.menuBar.showsSeparatorLine = NO; 90 | 91 | ``` 92 | 93 | Also you can customize buttons of menu bar item by implementing delegate methods, as below: 94 | ```objective-c 95 | 96 | - (RMPScrollingMenuBarItem*)menuBarController:(RMPScrollingMenuBarController *)menuBarController 97 | menuBarItemAtIndex:(NSInteger)index 98 | { 99 | RMPScrollingMenuBarItem* item = [[RMPScrollingMenuBarItem alloc] init]; 100 | item.title = titles[index]; 101 | 102 | // Customize appearance of menu bar item. 103 | UIButton* button = item.button; 104 | [button setTitleColor:[UIColor lightGrayColor] 105 | forState:UIControlStateNormal]; 106 | [button setTitleColor:[UIColor grayColor] 107 | forState:UIControlStateDisabled]; 108 | [button setTitleColor:[UIColor greenColor] 109 | forState:UIControlStateSelected]; 110 | 111 | return item; 112 | } 113 | 114 | ``` 115 | 116 | ## Infinite paging 117 | Enables infinite paging mode, as below: 118 | ```objective-c 119 | RMPScrollingMenuBarController* menuController = [[RMPScrollingMenuBarController alloc] init]; 120 | menuController.menuBar.style = RMPScrollingMenuBarStyleInfinitePaging; 121 | 122 | ``` 123 | 124 | 125 | ## Requirements 126 | 127 | - iOS 7.0 or higher 128 | 129 | ## Change Log 130 | 131 | ### 1.0.6 132 | - Adds infinite paging mode. 133 | 134 | ### 1.0.5 135 | - Adds properties for customizing appearance. 136 | 137 | ### 1.0.4 138 | - Fixes crash issue. 139 | 140 | ### 1.0.1 ~ 1.0.3 141 | - Fixes minor issues. 142 | 143 | ### 1.0.0 144 | - First release. 145 | 146 | ## Contribution 147 | 148 | If you have feature requests or bug reports, feel free to help out by sending pull requests or by creating new issues. 149 | 150 | ## Author 151 | 152 | Yoshihiro Kato, yoshihiro@sputnik-apps.com 153 | Recruit Marketing Partners Co.,Ltd. recruit_mp_oss@ml.cocorou.jp 154 | 155 | ## License 156 | 157 | RMPScrollingMenuBarController is available under the MIT license. 158 | -------------------------------------------------------------------------------- /RMPScrollingMenuBarController.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod lib lint RMPScrollingMenuBarController.podspec' to ensure this is a 3 | # valid spec and remove all comments before submitting the spec. 4 | # 5 | # Any lines starting with a # are optional, but encouraged 6 | # 7 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html 8 | # 9 | 10 | Pod::Spec.new do |s| 11 | s.name = "RMPScrollingMenuBarController" 12 | s.version = "1.0.6" 13 | s.summary = "A scrollable menu bar and multiple view controllers, which is managed like a UITabBarController." 14 | s.description = <<-DESC 15 | `RMPScrollingMenuBarController` has a scrollable menu bar, and multiple view controllers. 16 | 17 | You can switch view controllers, which is managed like a `UITabBarController`, by swiping a screen or scrolling the menu. 18 | DESC 19 | s.homepage = "https://github.com/recruit-mp/RMPScrollingMenuBarController" 20 | s.screenshots = "https://raw.githubusercontent.com/recruit-mp/RMPScrollingMenuBarController/master/docs/rmpscrollingmenubarcontroller.gif" 21 | s.license = 'MIT' 22 | s.author = { "kato" => "yoshihiro@sputnik-apps.com", "Recruit Marketing Partners Co.,Ltd." => "recruit_mp_oss@ml.cocorou.jp" } 23 | s.source = { :git => "https://github.com/recruit-mp/RMPScrollingMenuBarController.git", :tag => s.version.to_s } 24 | # s.social_media_url = 'https://twitter.com/' 25 | 26 | s.platform = :ios, '7.0' 27 | s.requires_arc = true 28 | 29 | s.source_files = 'Pod/Classes' 30 | s.resource_bundles = { 31 | 'RMPScrollingMenuBarController' => ['Pod/Assets/*.png'] 32 | } 33 | 34 | # s.public_header_files = 'Pod/Classes/**/*.h' 35 | s.frameworks = 'UIKit' 36 | # s.dependency 'AFNetworking', '~> 2.3' 37 | end 38 | -------------------------------------------------------------------------------- /docs/rmpscrollingmenubarcontroller.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/recruit-mp/RMPScrollingMenuBarController/2de637e2e86d8fe986e6dd26cd2910c78739b95d/docs/rmpscrollingmenubarcontroller.gif --------------------------------------------------------------------------------