├── .gitignore ├── .swift-version ├── .swiftpm └── xcode │ └── package.xcworkspace │ └── contents.xcworkspacedata ├── Example ├── Example.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── Example │ ├── AppDelegate.swift │ ├── Dummies │ ├── DummyCell.swift │ ├── DummyController.swift │ └── MiddleView.swift │ ├── Resources │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── Ramotion.png │ │ │ ├── icon-120.png │ │ │ ├── icon-152.png │ │ │ ├── icon-167.png │ │ │ ├── icon-180.png │ │ │ ├── icon-20.png │ │ │ ├── icon-29.png │ │ │ ├── icon-40.png │ │ │ ├── icon-58.png │ │ │ ├── icon-60.png │ │ │ ├── icon-76.png │ │ │ ├── icon-80.png │ │ │ └── icon-87.png │ │ ├── Contents.json │ │ ├── background.imageset │ │ │ ├── Contents.json │ │ │ ├── collection_bg-1.png │ │ │ ├── collection_bg-2.png │ │ │ └── collection_bg.png │ │ └── controllers │ │ │ ├── Contents.json │ │ │ ├── image1.imageset │ │ │ ├── Contents.json │ │ │ └── image1.jpeg │ │ │ ├── image10.imageset │ │ │ ├── Contents.json │ │ │ └── image10.jpeg │ │ │ ├── image11.imageset │ │ │ ├── Contents.json │ │ │ └── image11.jpeg │ │ │ ├── image12.imageset │ │ │ ├── Contents.json │ │ │ └── image12.jpeg │ │ │ ├── image13.imageset │ │ │ ├── Contents.json │ │ │ └── image13.jpeg │ │ │ ├── image14.imageset │ │ │ ├── Contents.json │ │ │ └── image14.jpeg │ │ │ ├── image15.imageset │ │ │ ├── Contents.json │ │ │ └── image15.jpeg │ │ │ ├── image2.imageset │ │ │ ├── Contents.json │ │ │ └── image2.jpeg │ │ │ ├── image3.imageset │ │ │ ├── Contents.json │ │ │ └── image3.jpeg │ │ │ ├── image4.imageset │ │ │ ├── Contents.json │ │ │ └── image4.jpeg │ │ │ ├── image5.imageset │ │ │ ├── Contents.json │ │ │ └── image5.jpeg │ │ │ ├── image6.imageset │ │ │ ├── Contents.json │ │ │ └── image6.jpeg │ │ │ ├── image7.imageset │ │ │ ├── Contents.json │ │ │ └── image7.jpeg │ │ │ ├── image8.imageset │ │ │ ├── Contents.json │ │ │ └── image8.jpeg │ │ │ └── image9.imageset │ │ │ ├── Contents.json │ │ │ └── image9.jpeg │ ├── Base.lproj │ │ └── LaunchScreen.storyboard │ └── Info.plist │ ├── Utilities │ └── UIColor+HEX.swift │ └── ViewController.swift ├── LICENSE ├── Navigation-Toolbar.podspec ├── NavigationToolbar.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── xcshareddata │ └── xcschemes │ └── NavigationToolbar.xcscheme ├── Package.swift ├── README.md ├── Sources ├── Components │ ├── Label.swift │ └── PanDirectionGestureRecognizer.swift ├── Extensions │ └── UIImage+gradient.swift ├── Info.plist ├── NavigationToolbar.h ├── NavigationView.swift ├── Objects │ └── ScreenObject.swift ├── Settings │ └── Settings.swift └── SubViews │ ├── BottomView │ └── BottomView.swift │ ├── FullscreenView │ ├── CellView.swift │ ├── FulllscreenView.swift │ └── LabelView.swift │ └── TopView │ ├── SizingView.swift │ ├── TopView.swift │ ├── TopViewAnimators.swift │ ├── TopViewCells.swift │ └── TopViewCollectionLayout.swift ├── header.png └── iOS-Navigation-Toolbar-1x.gif /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xccheckout 23 | *.xcscmblueprint 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | *.ipa 28 | *.dSYM.zip 29 | *.dSYM 30 | 31 | ## Playgrounds 32 | timeline.xctimeline 33 | playground.xcworkspace 34 | 35 | # Swift Package Manager 36 | # 37 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 38 | # Packages/ 39 | # Package.pins 40 | .build/ 41 | 42 | # CocoaPods 43 | # 44 | # We recommend against adding the Pods directory to your .gitignore. However 45 | # you should judge for yourself, the pros and cons are mentioned at: 46 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 47 | # 48 | # Pods/ 49 | 50 | # Carthage 51 | # 52 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 53 | # Carthage/Checkouts 54 | 55 | Carthage/Build 56 | 57 | # fastlane 58 | # 59 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 60 | # screenshots whenever they are needed. 61 | # For more information about the recommended setup visit: 62 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 63 | 64 | fastlane/report.xml 65 | fastlane/Preview.html 66 | fastlane/screenshots 67 | fastlane/test_output 68 | /NavigationToolBar/.DS_Store 69 | .DS_Store 70 | -------------------------------------------------------------------------------- /.swift-version: -------------------------------------------------------------------------------- 1 | 4.1 2 | -------------------------------------------------------------------------------- /.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/Example.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 393FDA3321132D6A00909225 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 393FDA2821132D6A00909225 /* ViewController.swift */; }; 11 | 393FDA3421132D6A00909225 /* UIColor+HEX.swift in Sources */ = {isa = PBXBuildFile; fileRef = 393FDA2921132D6A00909225 /* UIColor+HEX.swift */; }; 12 | 393FDA3521132D6A00909225 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 393FDA2A21132D6A00909225 /* Assets.xcassets */; }; 13 | 393FDA3621132D6A00909225 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 393FDA2B21132D6A00909225 /* LaunchScreen.storyboard */; }; 14 | 393FDA3821132D6A00909225 /* DummyController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 393FDA2F21132D6A00909225 /* DummyController.swift */; }; 15 | 393FDA3921132D6A00909225 /* DummyCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 393FDA3021132D6A00909225 /* DummyCell.swift */; }; 16 | 393FDA3A21132D6A00909225 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 393FDA3121132D6A00909225 /* AppDelegate.swift */; }; 17 | 393FDA4421132F6200909225 /* NavigationToolbar.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 393FDA4321132F5800909225 /* NavigationToolbar.framework */; }; 18 | 393FDA4521132F6200909225 /* NavigationToolbar.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 393FDA4321132F5800909225 /* NavigationToolbar.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 19 | EE32E8C42119A85C00193C32 /* MiddleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE32E8C32119A85C00193C32 /* MiddleView.swift */; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXContainerItemProxy section */ 23 | 393FDA4221132F5800909225 /* PBXContainerItemProxy */ = { 24 | isa = PBXContainerItemProxy; 25 | containerPortal = 393FDA3E21132F5700909225 /* NavigationToolbar.xcodeproj */; 26 | proxyType = 2; 27 | remoteGlobalIDString = 393FD9CF21132AD000909225; 28 | remoteInfo = NavigationToolbar; 29 | }; 30 | 393FDA4621132F6200909225 /* PBXContainerItemProxy */ = { 31 | isa = PBXContainerItemProxy; 32 | containerPortal = 393FDA3E21132F5700909225 /* NavigationToolbar.xcodeproj */; 33 | proxyType = 1; 34 | remoteGlobalIDString = 393FD9CE21132AD000909225; 35 | remoteInfo = NavigationToolbar; 36 | }; 37 | /* End PBXContainerItemProxy section */ 38 | 39 | /* Begin PBXCopyFilesBuildPhase section */ 40 | 393FDA4821132F6200909225 /* Embed Frameworks */ = { 41 | isa = PBXCopyFilesBuildPhase; 42 | buildActionMask = 2147483647; 43 | dstPath = ""; 44 | dstSubfolderSpec = 10; 45 | files = ( 46 | 393FDA4521132F6200909225 /* NavigationToolbar.framework in Embed Frameworks */, 47 | ); 48 | name = "Embed Frameworks"; 49 | runOnlyForDeploymentPostprocessing = 0; 50 | }; 51 | /* End PBXCopyFilesBuildPhase section */ 52 | 53 | /* Begin PBXFileReference section */ 54 | 393FDA1221132D2900909225 /* Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 55 | 393FDA2821132D6A00909225 /* ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 56 | 393FDA2921132D6A00909225 /* UIColor+HEX.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIColor+HEX.swift"; sourceTree = ""; }; 57 | 393FDA2A21132D6A00909225 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 58 | 393FDA2C21132D6A00909225 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 59 | 393FDA2F21132D6A00909225 /* DummyController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DummyController.swift; sourceTree = ""; }; 60 | 393FDA3021132D6A00909225 /* DummyCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DummyCell.swift; sourceTree = ""; }; 61 | 393FDA3121132D6A00909225 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 62 | 393FDA3221132D6A00909225 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 63 | 393FDA3E21132F5700909225 /* NavigationToolbar.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = NavigationToolbar.xcodeproj; path = ../NavigationToolbar.xcodeproj; sourceTree = ""; }; 64 | EE32E8C32119A85C00193C32 /* MiddleView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MiddleView.swift; sourceTree = ""; }; 65 | /* End PBXFileReference section */ 66 | 67 | /* Begin PBXFrameworksBuildPhase section */ 68 | 393FDA0F21132D2900909225 /* Frameworks */ = { 69 | isa = PBXFrameworksBuildPhase; 70 | buildActionMask = 2147483647; 71 | files = ( 72 | 393FDA4421132F6200909225 /* NavigationToolbar.framework in Frameworks */, 73 | ); 74 | runOnlyForDeploymentPostprocessing = 0; 75 | }; 76 | /* End PBXFrameworksBuildPhase section */ 77 | 78 | /* Begin PBXGroup section */ 79 | 393FDA0921132D2900909225 = { 80 | isa = PBXGroup; 81 | children = ( 82 | 393FDA2721132D6A00909225 /* Example */, 83 | 393FDA1321132D2900909225 /* Products */, 84 | 393FDA3E21132F5700909225 /* NavigationToolbar.xcodeproj */, 85 | ); 86 | sourceTree = ""; 87 | }; 88 | 393FDA1321132D2900909225 /* Products */ = { 89 | isa = PBXGroup; 90 | children = ( 91 | 393FDA1221132D2900909225 /* Example.app */, 92 | ); 93 | name = Products; 94 | sourceTree = ""; 95 | }; 96 | 393FDA2721132D6A00909225 /* Example */ = { 97 | isa = PBXGroup; 98 | children = ( 99 | 393FDA3121132D6A00909225 /* AppDelegate.swift */, 100 | 393FDA2821132D6A00909225 /* ViewController.swift */, 101 | 393FDA3D21132F2600909225 /* Utilities */, 102 | 393FDA3C21132DD200909225 /* Resources */, 103 | 393FDA2E21132D6A00909225 /* Dummies */, 104 | ); 105 | path = Example; 106 | sourceTree = ""; 107 | }; 108 | 393FDA2E21132D6A00909225 /* Dummies */ = { 109 | isa = PBXGroup; 110 | children = ( 111 | 393FDA2F21132D6A00909225 /* DummyController.swift */, 112 | 393FDA3021132D6A00909225 /* DummyCell.swift */, 113 | EE32E8C32119A85C00193C32 /* MiddleView.swift */, 114 | ); 115 | path = Dummies; 116 | sourceTree = ""; 117 | }; 118 | 393FDA3C21132DD200909225 /* Resources */ = { 119 | isa = PBXGroup; 120 | children = ( 121 | 393FDA2A21132D6A00909225 /* Assets.xcassets */, 122 | 393FDA2B21132D6A00909225 /* LaunchScreen.storyboard */, 123 | 393FDA3221132D6A00909225 /* Info.plist */, 124 | ); 125 | path = Resources; 126 | sourceTree = ""; 127 | }; 128 | 393FDA3D21132F2600909225 /* Utilities */ = { 129 | isa = PBXGroup; 130 | children = ( 131 | 393FDA2921132D6A00909225 /* UIColor+HEX.swift */, 132 | ); 133 | path = Utilities; 134 | sourceTree = ""; 135 | }; 136 | 393FDA3F21132F5700909225 /* Products */ = { 137 | isa = PBXGroup; 138 | children = ( 139 | 393FDA4321132F5800909225 /* NavigationToolbar.framework */, 140 | ); 141 | name = Products; 142 | sourceTree = ""; 143 | }; 144 | /* End PBXGroup section */ 145 | 146 | /* Begin PBXNativeTarget section */ 147 | 393FDA1121132D2900909225 /* Example */ = { 148 | isa = PBXNativeTarget; 149 | buildConfigurationList = 393FDA2421132D2B00909225 /* Build configuration list for PBXNativeTarget "Example" */; 150 | buildPhases = ( 151 | 393FDA0E21132D2900909225 /* Sources */, 152 | 393FDA0F21132D2900909225 /* Frameworks */, 153 | 393FDA1021132D2900909225 /* Resources */, 154 | 393FDA4821132F6200909225 /* Embed Frameworks */, 155 | ); 156 | buildRules = ( 157 | ); 158 | dependencies = ( 159 | 393FDA4721132F6200909225 /* PBXTargetDependency */, 160 | ); 161 | name = Example; 162 | productName = Example; 163 | productReference = 393FDA1221132D2900909225 /* Example.app */; 164 | productType = "com.apple.product-type.application"; 165 | }; 166 | /* End PBXNativeTarget section */ 167 | 168 | /* Begin PBXProject section */ 169 | 393FDA0A21132D2900909225 /* Project object */ = { 170 | isa = PBXProject; 171 | attributes = { 172 | LastSwiftUpdateCheck = 0940; 173 | LastUpgradeCheck = 0940; 174 | ORGANIZATIONNAME = Ramotion; 175 | TargetAttributes = { 176 | 393FDA1121132D2900909225 = { 177 | CreatedOnToolsVersion = 9.4.1; 178 | }; 179 | }; 180 | }; 181 | buildConfigurationList = 393FDA0D21132D2900909225 /* Build configuration list for PBXProject "Example" */; 182 | compatibilityVersion = "Xcode 9.3"; 183 | developmentRegion = en; 184 | hasScannedForEncodings = 0; 185 | knownRegions = ( 186 | en, 187 | Base, 188 | ); 189 | mainGroup = 393FDA0921132D2900909225; 190 | productRefGroup = 393FDA1321132D2900909225 /* Products */; 191 | projectDirPath = ""; 192 | projectReferences = ( 193 | { 194 | ProductGroup = 393FDA3F21132F5700909225 /* Products */; 195 | ProjectRef = 393FDA3E21132F5700909225 /* NavigationToolbar.xcodeproj */; 196 | }, 197 | ); 198 | projectRoot = ""; 199 | targets = ( 200 | 393FDA1121132D2900909225 /* Example */, 201 | ); 202 | }; 203 | /* End PBXProject section */ 204 | 205 | /* Begin PBXReferenceProxy section */ 206 | 393FDA4321132F5800909225 /* NavigationToolbar.framework */ = { 207 | isa = PBXReferenceProxy; 208 | fileType = wrapper.framework; 209 | path = NavigationToolbar.framework; 210 | remoteRef = 393FDA4221132F5800909225 /* PBXContainerItemProxy */; 211 | sourceTree = BUILT_PRODUCTS_DIR; 212 | }; 213 | /* End PBXReferenceProxy section */ 214 | 215 | /* Begin PBXResourcesBuildPhase section */ 216 | 393FDA1021132D2900909225 /* Resources */ = { 217 | isa = PBXResourcesBuildPhase; 218 | buildActionMask = 2147483647; 219 | files = ( 220 | 393FDA3521132D6A00909225 /* Assets.xcassets in Resources */, 221 | 393FDA3621132D6A00909225 /* LaunchScreen.storyboard in Resources */, 222 | ); 223 | runOnlyForDeploymentPostprocessing = 0; 224 | }; 225 | /* End PBXResourcesBuildPhase section */ 226 | 227 | /* Begin PBXSourcesBuildPhase section */ 228 | 393FDA0E21132D2900909225 /* Sources */ = { 229 | isa = PBXSourcesBuildPhase; 230 | buildActionMask = 2147483647; 231 | files = ( 232 | 393FDA3821132D6A00909225 /* DummyController.swift in Sources */, 233 | 393FDA3921132D6A00909225 /* DummyCell.swift in Sources */, 234 | 393FDA3321132D6A00909225 /* ViewController.swift in Sources */, 235 | EE32E8C42119A85C00193C32 /* MiddleView.swift in Sources */, 236 | 393FDA3A21132D6A00909225 /* AppDelegate.swift in Sources */, 237 | 393FDA3421132D6A00909225 /* UIColor+HEX.swift in Sources */, 238 | ); 239 | runOnlyForDeploymentPostprocessing = 0; 240 | }; 241 | /* End PBXSourcesBuildPhase section */ 242 | 243 | /* Begin PBXTargetDependency section */ 244 | 393FDA4721132F6200909225 /* PBXTargetDependency */ = { 245 | isa = PBXTargetDependency; 246 | name = NavigationToolbar; 247 | targetProxy = 393FDA4621132F6200909225 /* PBXContainerItemProxy */; 248 | }; 249 | /* End PBXTargetDependency section */ 250 | 251 | /* Begin PBXVariantGroup section */ 252 | 393FDA2B21132D6A00909225 /* LaunchScreen.storyboard */ = { 253 | isa = PBXVariantGroup; 254 | children = ( 255 | 393FDA2C21132D6A00909225 /* Base */, 256 | ); 257 | name = LaunchScreen.storyboard; 258 | sourceTree = ""; 259 | }; 260 | /* End PBXVariantGroup section */ 261 | 262 | /* Begin XCBuildConfiguration section */ 263 | 393FDA2221132D2B00909225 /* Debug */ = { 264 | isa = XCBuildConfiguration; 265 | buildSettings = { 266 | ALWAYS_SEARCH_USER_PATHS = NO; 267 | CLANG_ANALYZER_NONNULL = YES; 268 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 269 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 270 | CLANG_CXX_LIBRARY = "libc++"; 271 | CLANG_ENABLE_MODULES = YES; 272 | CLANG_ENABLE_OBJC_ARC = YES; 273 | CLANG_ENABLE_OBJC_WEAK = YES; 274 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 275 | CLANG_WARN_BOOL_CONVERSION = YES; 276 | CLANG_WARN_COMMA = YES; 277 | CLANG_WARN_CONSTANT_CONVERSION = YES; 278 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 279 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 280 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 281 | CLANG_WARN_EMPTY_BODY = YES; 282 | CLANG_WARN_ENUM_CONVERSION = YES; 283 | CLANG_WARN_INFINITE_RECURSION = YES; 284 | CLANG_WARN_INT_CONVERSION = YES; 285 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 286 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 287 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 288 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 289 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 290 | CLANG_WARN_STRICT_PROTOTYPES = YES; 291 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 292 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 293 | CLANG_WARN_UNREACHABLE_CODE = YES; 294 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 295 | CODE_SIGN_IDENTITY = "iPhone Developer"; 296 | COPY_PHASE_STRIP = NO; 297 | DEBUG_INFORMATION_FORMAT = dwarf; 298 | ENABLE_STRICT_OBJC_MSGSEND = YES; 299 | ENABLE_TESTABILITY = YES; 300 | GCC_C_LANGUAGE_STANDARD = gnu11; 301 | GCC_DYNAMIC_NO_PIC = NO; 302 | GCC_NO_COMMON_BLOCKS = YES; 303 | GCC_OPTIMIZATION_LEVEL = 0; 304 | GCC_PREPROCESSOR_DEFINITIONS = ( 305 | "DEBUG=1", 306 | "$(inherited)", 307 | ); 308 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 309 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 310 | GCC_WARN_UNDECLARED_SELECTOR = YES; 311 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 312 | GCC_WARN_UNUSED_FUNCTION = YES; 313 | GCC_WARN_UNUSED_VARIABLE = YES; 314 | IPHONEOS_DEPLOYMENT_TARGET = 11.4; 315 | MTL_ENABLE_DEBUG_INFO = YES; 316 | ONLY_ACTIVE_ARCH = YES; 317 | SDKROOT = iphoneos; 318 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 319 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 320 | }; 321 | name = Debug; 322 | }; 323 | 393FDA2321132D2B00909225 /* Release */ = { 324 | isa = XCBuildConfiguration; 325 | buildSettings = { 326 | ALWAYS_SEARCH_USER_PATHS = NO; 327 | CLANG_ANALYZER_NONNULL = YES; 328 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 329 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 330 | CLANG_CXX_LIBRARY = "libc++"; 331 | CLANG_ENABLE_MODULES = YES; 332 | CLANG_ENABLE_OBJC_ARC = YES; 333 | CLANG_ENABLE_OBJC_WEAK = YES; 334 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 335 | CLANG_WARN_BOOL_CONVERSION = YES; 336 | CLANG_WARN_COMMA = YES; 337 | CLANG_WARN_CONSTANT_CONVERSION = YES; 338 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 339 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 340 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 341 | CLANG_WARN_EMPTY_BODY = YES; 342 | CLANG_WARN_ENUM_CONVERSION = YES; 343 | CLANG_WARN_INFINITE_RECURSION = YES; 344 | CLANG_WARN_INT_CONVERSION = YES; 345 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 346 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 347 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 348 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 349 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 350 | CLANG_WARN_STRICT_PROTOTYPES = YES; 351 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 352 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 353 | CLANG_WARN_UNREACHABLE_CODE = YES; 354 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 355 | CODE_SIGN_IDENTITY = "iPhone Developer"; 356 | COPY_PHASE_STRIP = NO; 357 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 358 | ENABLE_NS_ASSERTIONS = NO; 359 | ENABLE_STRICT_OBJC_MSGSEND = YES; 360 | GCC_C_LANGUAGE_STANDARD = gnu11; 361 | GCC_NO_COMMON_BLOCKS = YES; 362 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 363 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 364 | GCC_WARN_UNDECLARED_SELECTOR = YES; 365 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 366 | GCC_WARN_UNUSED_FUNCTION = YES; 367 | GCC_WARN_UNUSED_VARIABLE = YES; 368 | IPHONEOS_DEPLOYMENT_TARGET = 11.4; 369 | MTL_ENABLE_DEBUG_INFO = NO; 370 | SDKROOT = iphoneos; 371 | SWIFT_COMPILATION_MODE = wholemodule; 372 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 373 | VALIDATE_PRODUCT = YES; 374 | }; 375 | name = Release; 376 | }; 377 | 393FDA2521132D2B00909225 /* Debug */ = { 378 | isa = XCBuildConfiguration; 379 | buildSettings = { 380 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 381 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 382 | CODE_SIGN_STYLE = Automatic; 383 | DEVELOPMENT_TEAM = 34MUF9YXTA; 384 | INFOPLIST_FILE = Example/Resources/Info.plist; 385 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 386 | LD_RUNPATH_SEARCH_PATHS = ( 387 | "$(inherited)", 388 | "@executable_path/Frameworks", 389 | ); 390 | PRODUCT_BUNDLE_IDENTIFIER = com.ramotion.Example; 391 | PRODUCT_NAME = "$(TARGET_NAME)"; 392 | SWIFT_VERSION = 5.0; 393 | TARGETED_DEVICE_FAMILY = "1,2"; 394 | }; 395 | name = Debug; 396 | }; 397 | 393FDA2621132D2B00909225 /* Release */ = { 398 | isa = XCBuildConfiguration; 399 | buildSettings = { 400 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 401 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 402 | CODE_SIGN_STYLE = Automatic; 403 | DEVELOPMENT_TEAM = 34MUF9YXTA; 404 | INFOPLIST_FILE = Example/Resources/Info.plist; 405 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 406 | LD_RUNPATH_SEARCH_PATHS = ( 407 | "$(inherited)", 408 | "@executable_path/Frameworks", 409 | ); 410 | PRODUCT_BUNDLE_IDENTIFIER = com.ramotion.Example; 411 | PRODUCT_NAME = "$(TARGET_NAME)"; 412 | SWIFT_VERSION = 5.0; 413 | TARGETED_DEVICE_FAMILY = "1,2"; 414 | }; 415 | name = Release; 416 | }; 417 | /* End XCBuildConfiguration section */ 418 | 419 | /* Begin XCConfigurationList section */ 420 | 393FDA0D21132D2900909225 /* Build configuration list for PBXProject "Example" */ = { 421 | isa = XCConfigurationList; 422 | buildConfigurations = ( 423 | 393FDA2221132D2B00909225 /* Debug */, 424 | 393FDA2321132D2B00909225 /* Release */, 425 | ); 426 | defaultConfigurationIsVisible = 0; 427 | defaultConfigurationName = Release; 428 | }; 429 | 393FDA2421132D2B00909225 /* Build configuration list for PBXNativeTarget "Example" */ = { 430 | isa = XCConfigurationList; 431 | buildConfigurations = ( 432 | 393FDA2521132D2B00909225 /* Debug */, 433 | 393FDA2621132D2B00909225 /* Release */, 434 | ); 435 | defaultConfigurationIsVisible = 0; 436 | defaultConfigurationName = Release; 437 | }; 438 | /* End XCConfigurationList section */ 439 | }; 440 | rootObject = 393FDA0A21132D2900909225 /* Project object */; 441 | } 442 | -------------------------------------------------------------------------------- /Example/Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/Example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Example/Example/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // NavigationToolbar 4 | // 5 | // Created by Artem P. on 21/05/2018. 6 | // Copyright © 2018 Ramotion. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? = UIWindow(frame: UIScreen.main.bounds) 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 17 | 18 | window?.rootViewController = ViewController() 19 | window?.makeKeyAndVisible() 20 | 21 | return true 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Example/Example/Dummies/DummyCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DummyView.swift 3 | // NavigationToolbar 4 | // 5 | // Created by Artem P. on 22/05/2018. 6 | // Copyright © 2018 Ramotion. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class DummyCell: UITableViewCell { 12 | 13 | private var avatarImageView = UIImageView() 14 | private var titleLabel = UILabel() 15 | private var subtitleLabel = UILabel() 16 | private var separatorView = UIView() 17 | private var contentImageView = UIImageView() 18 | 19 | override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { 20 | super.init(style: style, reuseIdentifier: reuseIdentifier) 21 | setup() 22 | } 23 | 24 | required init?(coder aDecoder: NSCoder) { 25 | super.init(coder: aDecoder) 26 | setup() 27 | } 28 | 29 | override func awakeFromNib() { 30 | 31 | } 32 | 33 | private func setup() { 34 | avatarImageView.contentMode = .scaleAspectFill 35 | avatarImageView.clipsToBounds = true 36 | avatarImageView.layer.cornerRadius = 4.0 37 | 38 | contentImageView.contentMode = .scaleAspectFill 39 | contentImageView.clipsToBounds = true 40 | contentImageView.layer.cornerRadius = 4.0 41 | 42 | titleLabel.font = UIFont.systemFont(ofSize: 15) 43 | titleLabel.textColor = UIColor.darkText 44 | 45 | subtitleLabel.font = UIFont.systemFont(ofSize: 13) 46 | subtitleLabel.textColor = UIColor.gray 47 | 48 | separatorView.backgroundColor = UIColor.gray 49 | separatorView.alpha = 0.5 50 | 51 | addSubview(avatarImageView) 52 | addSubview(titleLabel) 53 | addSubview(subtitleLabel) 54 | addSubview(separatorView) 55 | addSubview(contentImageView) 56 | } 57 | 58 | override func layoutSubviews() { 59 | super.layoutSubviews() 60 | 61 | let w = bounds.width 62 | 63 | avatarImageView.frame = CGRect(x: 16, y: 16, width: 40, height: 40) 64 | titleLabel.frame = CGRect(x: avatarImageView.frame.maxX + 16, y: 16, width: w - 40 - 48, height: 20) 65 | subtitleLabel.frame = CGRect(x: avatarImageView.frame.maxX + 16, y: titleLabel.frame.maxY, width: w - 40 - 48, height: 20) 66 | separatorView.frame = CGRect(x: 16, y: avatarImageView.frame.maxY + 16, width: w - 32, height: 0.5) 67 | contentImageView.frame = CGRect(x: 16, y: separatorView.frame.maxY + 8, width: w - 32, height: 250) 68 | } 69 | 70 | func setData(avatar: UIImage, title: String, subtitle: String, content: UIImage) { 71 | avatarImageView.image = avatar 72 | titleLabel.text = title 73 | subtitleLabel.text = subtitle 74 | contentImageView.image = content 75 | } 76 | 77 | override func setSelected(_ selected: Bool, animated: Bool) { 78 | selectionStyle = .none 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /Example/Example/Dummies/DummyController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DummyController.swift 3 | // NavigationToolbar 4 | // 5 | // Created by Artem P. on 22/05/2018. 6 | // Copyright © 2018 Ramotion. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class DummyController: UIViewController { 12 | 13 | private var tableView = UITableView() 14 | 15 | override func viewDidLoad() { 16 | super.viewDidLoad() 17 | 18 | view.backgroundColor = UIColor.black 19 | 20 | tableView.delegate = self 21 | tableView.dataSource = self 22 | tableView.register(DummyCell.self, forCellReuseIdentifier: String(describing: DummyCell.self)) 23 | tableView.separatorColor = .clear 24 | tableView.bounces = false 25 | 26 | view.addSubview(tableView) 27 | } 28 | 29 | override func viewDidLayoutSubviews() { 30 | super.viewDidLayoutSubviews() 31 | tableView.frame = view.bounds 32 | } 33 | } 34 | 35 | extension DummyController: UITableViewDelegate, UITableViewDataSource { 36 | 37 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 38 | return 100 39 | } 40 | 41 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 42 | let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: DummyCell.self), for: indexPath) as! DummyCell 43 | cell.setData(avatar: UIImage(named: "image14")!, title: "Jellyfish Cam offers Stunning Views", subtitle: "3k views • 5 days ago", content: UIImage(named: "image13")!) 44 | 45 | return cell 46 | } 47 | 48 | func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 49 | return 350 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Example/Example/Dummies/MiddleView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MiddleView.swift 3 | // NavigationToolbar 4 | // 5 | // Created by Artem P. on 22/05/2018. 6 | // Copyright © 2018 Ramotion. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class MiddleView: UIView { 12 | 13 | private var separatorView = UIView() 14 | private var leftButton = UIButton() 15 | private var rightButton = UIButton() 16 | 17 | override init(frame: CGRect) { 18 | super.init(frame: frame) 19 | setup() 20 | } 21 | 22 | required init?(coder aDecoder: NSCoder) { 23 | super.init(coder: aDecoder) 24 | setup() 25 | } 26 | 27 | private func setup() { 28 | backgroundColor = .white 29 | 30 | layer.shadowColor = UIColor.black.cgColor 31 | layer.shadowRadius = 10.0 32 | layer.shadowOpacity = 0.1 33 | layer.shadowOffset = CGSize.zero 34 | layer.masksToBounds = false 35 | clipsToBounds = false 36 | 37 | separatorView.backgroundColor = .lightGray 38 | 39 | leftButton.setTitle("Left", for: .normal) 40 | rightButton.setTitle("Right", for: .normal) 41 | 42 | leftButton.setTitleColor(.gray, for: .normal) 43 | rightButton.setTitleColor(.gray, for: .normal) 44 | 45 | self.addSubview(separatorView) 46 | self.addSubview(leftButton) 47 | self.addSubview(rightButton) 48 | } 49 | 50 | override func layoutSubviews() { 51 | super.layoutSubviews() 52 | 53 | let w = bounds.width 54 | let h = bounds.height 55 | 56 | let half = w / 2 57 | 58 | 59 | separatorView.frame = CGRect(x: half, y: 14, width: 1, height: h - 28) 60 | leftButton.frame = CGRect(x: half - 100, y: 0, width: 90, height: h) 61 | rightButton.frame = CGRect(x: separatorView.frame.maxX + 10, y: 0, width: 90, height: h) 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "icon-40.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "icon-60.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "icon-58.png", 19 | "scale" : "2x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "icon-87.png", 25 | "scale" : "3x" 26 | }, 27 | { 28 | "size" : "40x40", 29 | "idiom" : "iphone", 30 | "filename" : "icon-80.png", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "icon-120.png", 37 | "scale" : "3x" 38 | }, 39 | { 40 | "size" : "60x60", 41 | "idiom" : "iphone", 42 | "filename" : "icon-120.png", 43 | "scale" : "2x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "icon-180.png", 49 | "scale" : "3x" 50 | }, 51 | { 52 | "size" : "20x20", 53 | "idiom" : "ipad", 54 | "filename" : "icon-20.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "icon-40.png", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "size" : "29x29", 65 | "idiom" : "ipad", 66 | "filename" : "icon-29.png", 67 | "scale" : "1x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "icon-58.png", 73 | "scale" : "2x" 74 | }, 75 | { 76 | "size" : "40x40", 77 | "idiom" : "ipad", 78 | "filename" : "icon-40.png", 79 | "scale" : "1x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "icon-80.png", 85 | "scale" : "2x" 86 | }, 87 | { 88 | "size" : "76x76", 89 | "idiom" : "ipad", 90 | "filename" : "icon-76.png", 91 | "scale" : "1x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "icon-152.png", 97 | "scale" : "2x" 98 | }, 99 | { 100 | "size" : "83.5x83.5", 101 | "idiom" : "ipad", 102 | "filename" : "icon-167.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "1024x1024", 107 | "idiom" : "ios-marketing", 108 | "filename" : "Ramotion.png", 109 | "scale" : "1x" 110 | } 111 | ], 112 | "info" : { 113 | "version" : 1, 114 | "author" : "xcode" 115 | }, 116 | "properties" : { 117 | "pre-rendered" : true 118 | } 119 | } -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/AppIcon.appiconset/Ramotion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/navigation-toolbar/6d917775fb4f72fea8f2706a4bb0ba0db4787332/Example/Example/Resources/Assets.xcassets/AppIcon.appiconset/Ramotion.png -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/AppIcon.appiconset/icon-120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/navigation-toolbar/6d917775fb4f72fea8f2706a4bb0ba0db4787332/Example/Example/Resources/Assets.xcassets/AppIcon.appiconset/icon-120.png -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/AppIcon.appiconset/icon-152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/navigation-toolbar/6d917775fb4f72fea8f2706a4bb0ba0db4787332/Example/Example/Resources/Assets.xcassets/AppIcon.appiconset/icon-152.png -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/AppIcon.appiconset/icon-167.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/navigation-toolbar/6d917775fb4f72fea8f2706a4bb0ba0db4787332/Example/Example/Resources/Assets.xcassets/AppIcon.appiconset/icon-167.png -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/AppIcon.appiconset/icon-180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/navigation-toolbar/6d917775fb4f72fea8f2706a4bb0ba0db4787332/Example/Example/Resources/Assets.xcassets/AppIcon.appiconset/icon-180.png -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/AppIcon.appiconset/icon-20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/navigation-toolbar/6d917775fb4f72fea8f2706a4bb0ba0db4787332/Example/Example/Resources/Assets.xcassets/AppIcon.appiconset/icon-20.png -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/AppIcon.appiconset/icon-29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/navigation-toolbar/6d917775fb4f72fea8f2706a4bb0ba0db4787332/Example/Example/Resources/Assets.xcassets/AppIcon.appiconset/icon-29.png -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/AppIcon.appiconset/icon-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/navigation-toolbar/6d917775fb4f72fea8f2706a4bb0ba0db4787332/Example/Example/Resources/Assets.xcassets/AppIcon.appiconset/icon-40.png -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/AppIcon.appiconset/icon-58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/navigation-toolbar/6d917775fb4f72fea8f2706a4bb0ba0db4787332/Example/Example/Resources/Assets.xcassets/AppIcon.appiconset/icon-58.png -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/AppIcon.appiconset/icon-60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/navigation-toolbar/6d917775fb4f72fea8f2706a4bb0ba0db4787332/Example/Example/Resources/Assets.xcassets/AppIcon.appiconset/icon-60.png -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/AppIcon.appiconset/icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/navigation-toolbar/6d917775fb4f72fea8f2706a4bb0ba0db4787332/Example/Example/Resources/Assets.xcassets/AppIcon.appiconset/icon-76.png -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/AppIcon.appiconset/icon-80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/navigation-toolbar/6d917775fb4f72fea8f2706a4bb0ba0db4787332/Example/Example/Resources/Assets.xcassets/AppIcon.appiconset/icon-80.png -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/AppIcon.appiconset/icon-87.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/navigation-toolbar/6d917775fb4f72fea8f2706a4bb0ba0db4787332/Example/Example/Resources/Assets.xcassets/AppIcon.appiconset/icon-87.png -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/background.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "collection_bg-2.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "collection_bg.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "collection_bg-1.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/background.imageset/collection_bg-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/navigation-toolbar/6d917775fb4f72fea8f2706a4bb0ba0db4787332/Example/Example/Resources/Assets.xcassets/background.imageset/collection_bg-1.png -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/background.imageset/collection_bg-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/navigation-toolbar/6d917775fb4f72fea8f2706a4bb0ba0db4787332/Example/Example/Resources/Assets.xcassets/background.imageset/collection_bg-2.png -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/background.imageset/collection_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/navigation-toolbar/6d917775fb4f72fea8f2706a4bb0ba0db4787332/Example/Example/Resources/Assets.xcassets/background.imageset/collection_bg.png -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/controllers/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/controllers/image1.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "image1.jpeg" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/controllers/image1.imageset/image1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/navigation-toolbar/6d917775fb4f72fea8f2706a4bb0ba0db4787332/Example/Example/Resources/Assets.xcassets/controllers/image1.imageset/image1.jpeg -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/controllers/image10.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "image10.jpeg" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/controllers/image10.imageset/image10.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/navigation-toolbar/6d917775fb4f72fea8f2706a4bb0ba0db4787332/Example/Example/Resources/Assets.xcassets/controllers/image10.imageset/image10.jpeg -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/controllers/image11.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "image11.jpeg" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/controllers/image11.imageset/image11.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/navigation-toolbar/6d917775fb4f72fea8f2706a4bb0ba0db4787332/Example/Example/Resources/Assets.xcassets/controllers/image11.imageset/image11.jpeg -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/controllers/image12.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "image12.jpeg" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/controllers/image12.imageset/image12.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/navigation-toolbar/6d917775fb4f72fea8f2706a4bb0ba0db4787332/Example/Example/Resources/Assets.xcassets/controllers/image12.imageset/image12.jpeg -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/controllers/image13.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "image13.jpeg" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/controllers/image13.imageset/image13.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/navigation-toolbar/6d917775fb4f72fea8f2706a4bb0ba0db4787332/Example/Example/Resources/Assets.xcassets/controllers/image13.imageset/image13.jpeg -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/controllers/image14.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "image14.jpeg" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/controllers/image14.imageset/image14.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/navigation-toolbar/6d917775fb4f72fea8f2706a4bb0ba0db4787332/Example/Example/Resources/Assets.xcassets/controllers/image14.imageset/image14.jpeg -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/controllers/image15.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "image15.jpeg" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/controllers/image15.imageset/image15.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/navigation-toolbar/6d917775fb4f72fea8f2706a4bb0ba0db4787332/Example/Example/Resources/Assets.xcassets/controllers/image15.imageset/image15.jpeg -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/controllers/image2.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "image2.jpeg" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/controllers/image2.imageset/image2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/navigation-toolbar/6d917775fb4f72fea8f2706a4bb0ba0db4787332/Example/Example/Resources/Assets.xcassets/controllers/image2.imageset/image2.jpeg -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/controllers/image3.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "image3.jpeg" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/controllers/image3.imageset/image3.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/navigation-toolbar/6d917775fb4f72fea8f2706a4bb0ba0db4787332/Example/Example/Resources/Assets.xcassets/controllers/image3.imageset/image3.jpeg -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/controllers/image4.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "image4.jpeg" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/controllers/image4.imageset/image4.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/navigation-toolbar/6d917775fb4f72fea8f2706a4bb0ba0db4787332/Example/Example/Resources/Assets.xcassets/controllers/image4.imageset/image4.jpeg -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/controllers/image5.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "image5.jpeg" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/controllers/image5.imageset/image5.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/navigation-toolbar/6d917775fb4f72fea8f2706a4bb0ba0db4787332/Example/Example/Resources/Assets.xcassets/controllers/image5.imageset/image5.jpeg -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/controllers/image6.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "image6.jpeg" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/controllers/image6.imageset/image6.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/navigation-toolbar/6d917775fb4f72fea8f2706a4bb0ba0db4787332/Example/Example/Resources/Assets.xcassets/controllers/image6.imageset/image6.jpeg -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/controllers/image7.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "image7.jpeg" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/controllers/image7.imageset/image7.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/navigation-toolbar/6d917775fb4f72fea8f2706a4bb0ba0db4787332/Example/Example/Resources/Assets.xcassets/controllers/image7.imageset/image7.jpeg -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/controllers/image8.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "image8.jpeg" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/controllers/image8.imageset/image8.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/navigation-toolbar/6d917775fb4f72fea8f2706a4bb0ba0db4787332/Example/Example/Resources/Assets.xcassets/controllers/image8.imageset/image8.jpeg -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/controllers/image9.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "image9.jpeg" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Example/Example/Resources/Assets.xcassets/controllers/image9.imageset/image9.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/navigation-toolbar/6d917775fb4f72fea8f2706a4bb0ba0db4787332/Example/Example/Resources/Assets.xcassets/controllers/image9.imageset/image9.jpeg -------------------------------------------------------------------------------- /Example/Example/Resources/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /Example/Example/Resources/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIRequiredDeviceCapabilities 26 | 27 | armv7 28 | 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | 33 | UISupportedInterfaceOrientations~ipad 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationPortraitUpsideDown 37 | UIInterfaceOrientationLandscapeLeft 38 | UIInterfaceOrientationLandscapeRight 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Example/Example/Utilities/UIColor+HEX.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+HEX.swift 3 | // NavigationToolbar 4 | // 5 | // Created by Artem P. on 22/05/2018. 6 | // Copyright © 2018 Ramotion. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | 12 | extension UIColor { 13 | 14 | convenience init(HEX: String) { 15 | let scanner = Scanner(string: HEX) 16 | scanner.scanLocation = 0 17 | 18 | var rgbValue: UInt64 = 0 19 | 20 | scanner.scanHexInt64(&rgbValue) 21 | 22 | let r = (rgbValue & 0xff0000) >> 16 23 | let g = (rgbValue & 0xff00) >> 8 24 | let b = rgbValue & 0xff 25 | 26 | self.init( 27 | red : CGFloat(r) / 0xff, 28 | green : CGFloat(g) / 0xff, 29 | blue : CGFloat(b) / 0xff, alpha : 1 30 | ) 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /Example/Example/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // NavigationToolbarDemo 4 | // 5 | // Created by Artem P. on 21/05/2018. 6 | // Copyright © 2018 Ramotion. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import NavigationToolbar 11 | 12 | class ViewController: UIViewController { 13 | 14 | private var navigationView: NavigationView? 15 | 16 | override func viewDidLoad() { 17 | super.viewDidLoad() 18 | 19 | navigationView = NavigationView.init(frame: view.bounds, middleView: MiddleView(), screens: createObjects(), backgroundImage: #imageLiteral(resourceName: "background")) 20 | navigationView?.autoresizingMask = [.flexibleWidth, .flexibleHeight] 21 | view.addSubview(navigationView!) 22 | } 23 | 24 | override var prefersStatusBarHidden: Bool { 25 | return true 26 | } 27 | 28 | private func createObjects() -> [ScreenObject] { 29 | let obj01 = ScreenObject(title: "OBSESSION", startColor: UIColor.init(HEX: "FDEB71"), endColor: UIColor.init(HEX: "F8D800"), image: UIImage(named : "image1")!, controller: DummyController()) 30 | let obj02 = ScreenObject(title: "RECREATION", startColor: UIColor.init(HEX: "ABDCFF"), endColor: UIColor.init(HEX: "0396FF"), image: UIImage(named : "image2")!, controller: DummyController()) 31 | let obj03 = ScreenObject(title: "EDUCATION", startColor: UIColor.init(HEX: "FEB692"), endColor: UIColor.init(HEX: "EA5455"), image: UIImage(named : "image3")!, controller: DummyController()) 32 | let obj04 = ScreenObject(title: "MOVIES", startColor: UIColor.init(HEX: "CE9FFC"), endColor: UIColor.init(HEX: "7367F0"), image: UIImage(named : "image4")!, controller: DummyController()) 33 | let obj05 = ScreenObject(title: "PROGRAMMING", startColor: UIColor.init(HEX: "90F7EC"), endColor: UIColor.init(HEX: "32CCBC"), image: UIImage(named : "image5")!, controller: DummyController()) 34 | let obj06 = ScreenObject(title: "SURFING", startColor: UIColor.init(HEX: "FFF6B7"), endColor: UIColor.init(HEX: "F6416C"), image: UIImage(named : "image6")!, controller: DummyController()) 35 | let obj07 = ScreenObject(title: "FLIGHT", startColor: UIColor.init(HEX: "81FBB8"), endColor: UIColor.init(HEX: "28C76F"), image: UIImage(named : "image7")!, controller: DummyController()) 36 | let obj08 = ScreenObject(title: "MINIMALISM", startColor: UIColor.init(HEX: "E2B0FF"), endColor: UIColor.init(HEX: "9F44D3"), image: UIImage(named : "image8")!, controller: DummyController()) 37 | 38 | return [obj01, 39 | obj02, 40 | obj03, 41 | obj04, 42 | obj05, 43 | obj06, 44 | obj07, 45 | obj08 46 | ] 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Ramotion 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Navigation-Toolbar.podspec: -------------------------------------------------------------------------------- 1 | 2 | Pod::Spec.new do |s| 3 | 4 | s.name = 'Navigation-Toolbar' 5 | s.version = '1.0.0' 6 | s.summary = 'Amazing navigation.' 7 | s.license = 'MIT' 8 | s.homepage = 'https://github.com/Ramotion/navigation-toolbar' 9 | s.author = { 'Juri Vasylenko' => 'juri.v@ramotion.com' } 10 | s.ios.deployment_target = '10.0' 11 | s.source = { :git => 'https://github.com/Ramotion/navigation-toolbar.git', :tag => s.version.to_s } 12 | s.source_files = 'Sources/**/*.swift' 13 | end 14 | -------------------------------------------------------------------------------- /NavigationToolbar.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 393FD9F721132B6F00909225 /* Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 393FD9DC21132B6F00909225 /* Settings.swift */; }; 11 | 393FD9F821132B6F00909225 /* NavigationToolbar.h in Headers */ = {isa = PBXBuildFile; fileRef = 393FD9DE21132B6F00909225 /* NavigationToolbar.h */; settings = {ATTRIBUTES = (Public, ); }; }; 12 | 393FD9FA21132B6F00909225 /* ScreenObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 393FD9E121132B6F00909225 /* ScreenObject.swift */; }; 13 | 393FD9FC21132B6F00909225 /* TopViewCells.swift in Sources */ = {isa = PBXBuildFile; fileRef = 393FD9E621132B6F00909225 /* TopViewCells.swift */; }; 14 | 393FD9FD21132B6F00909225 /* TopViewCollectionLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 393FD9E721132B6F00909225 /* TopViewCollectionLayout.swift */; }; 15 | 393FD9FE21132B6F00909225 /* SizingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 393FD9E821132B6F00909225 /* SizingView.swift */; }; 16 | 393FD9FF21132B6F00909225 /* TopViewAnimators.swift in Sources */ = {isa = PBXBuildFile; fileRef = 393FD9E921132B6F00909225 /* TopViewAnimators.swift */; }; 17 | 393FDA0021132B6F00909225 /* TopView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 393FD9EA21132B6F00909225 /* TopView.swift */; }; 18 | 393FDA0121132B6F00909225 /* CellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 393FD9EC21132B6F00909225 /* CellView.swift */; }; 19 | 393FDA0221132B6F00909225 /* FulllscreenView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 393FD9ED21132B6F00909225 /* FulllscreenView.swift */; }; 20 | 393FDA0321132B6F00909225 /* LabelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 393FD9EE21132B6F00909225 /* LabelView.swift */; }; 21 | 393FDA0421132B6F00909225 /* BottomView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 393FD9F021132B6F00909225 /* BottomView.swift */; }; 22 | 393FDA0521132B6F00909225 /* UIImage+gradient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 393FD9F221132B6F00909225 /* UIImage+gradient.swift */; }; 23 | 393FDA0621132B6F00909225 /* Label.swift in Sources */ = {isa = PBXBuildFile; fileRef = 393FD9F421132B6F00909225 /* Label.swift */; }; 24 | 393FDA0721132B6F00909225 /* PanDirectionGestureRecognizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 393FD9F521132B6F00909225 /* PanDirectionGestureRecognizer.swift */; }; 25 | 393FDA0821132B6F00909225 /* NavigationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 393FD9F621132B6F00909225 /* NavigationView.swift */; }; 26 | /* End PBXBuildFile section */ 27 | 28 | /* Begin PBXFileReference section */ 29 | 393FD9CF21132AD000909225 /* NavigationToolbar.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = NavigationToolbar.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 30 | 393FD9DC21132B6F00909225 /* Settings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Settings.swift; sourceTree = ""; }; 31 | 393FD9DE21132B6F00909225 /* NavigationToolbar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NavigationToolbar.h; sourceTree = ""; }; 32 | 393FD9DF21132B6F00909225 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 33 | 393FD9E121132B6F00909225 /* ScreenObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScreenObject.swift; sourceTree = ""; }; 34 | 393FD9E621132B6F00909225 /* TopViewCells.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TopViewCells.swift; sourceTree = ""; }; 35 | 393FD9E721132B6F00909225 /* TopViewCollectionLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TopViewCollectionLayout.swift; sourceTree = ""; }; 36 | 393FD9E821132B6F00909225 /* SizingView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SizingView.swift; sourceTree = ""; }; 37 | 393FD9E921132B6F00909225 /* TopViewAnimators.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TopViewAnimators.swift; sourceTree = ""; }; 38 | 393FD9EA21132B6F00909225 /* TopView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TopView.swift; sourceTree = ""; }; 39 | 393FD9EC21132B6F00909225 /* CellView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CellView.swift; sourceTree = ""; }; 40 | 393FD9ED21132B6F00909225 /* FulllscreenView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FulllscreenView.swift; sourceTree = ""; }; 41 | 393FD9EE21132B6F00909225 /* LabelView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LabelView.swift; sourceTree = ""; }; 42 | 393FD9F021132B6F00909225 /* BottomView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BottomView.swift; sourceTree = ""; }; 43 | 393FD9F221132B6F00909225 /* UIImage+gradient.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImage+gradient.swift"; sourceTree = ""; }; 44 | 393FD9F421132B6F00909225 /* Label.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Label.swift; sourceTree = ""; }; 45 | 393FD9F521132B6F00909225 /* PanDirectionGestureRecognizer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PanDirectionGestureRecognizer.swift; sourceTree = ""; }; 46 | 393FD9F621132B6F00909225 /* NavigationView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NavigationView.swift; sourceTree = ""; }; 47 | /* End PBXFileReference section */ 48 | 49 | /* Begin PBXFrameworksBuildPhase section */ 50 | 393FD9CB21132AD000909225 /* Frameworks */ = { 51 | isa = PBXFrameworksBuildPhase; 52 | buildActionMask = 2147483647; 53 | files = ( 54 | ); 55 | runOnlyForDeploymentPostprocessing = 0; 56 | }; 57 | /* End PBXFrameworksBuildPhase section */ 58 | 59 | /* Begin PBXGroup section */ 60 | 393FD9C521132AD000909225 = { 61 | isa = PBXGroup; 62 | children = ( 63 | 393FD9DA21132B6F00909225 /* Sources */, 64 | 393FD9D021132AD000909225 /* Products */, 65 | ); 66 | sourceTree = ""; 67 | }; 68 | 393FD9D021132AD000909225 /* Products */ = { 69 | isa = PBXGroup; 70 | children = ( 71 | 393FD9CF21132AD000909225 /* NavigationToolbar.framework */, 72 | ); 73 | name = Products; 74 | sourceTree = ""; 75 | }; 76 | 393FD9DA21132B6F00909225 /* Sources */ = { 77 | isa = PBXGroup; 78 | children = ( 79 | 393FD9F621132B6F00909225 /* NavigationView.swift */, 80 | 393FD9DB21132B6F00909225 /* Settings */, 81 | 393FD9E021132B6F00909225 /* Objects */, 82 | 393FD9E221132B6F00909225 /* SubViews */, 83 | 393FD9F121132B6F00909225 /* Extensions */, 84 | 393FD9F321132B6F00909225 /* Components */, 85 | 393FD9DE21132B6F00909225 /* NavigationToolbar.h */, 86 | 393FD9DF21132B6F00909225 /* Info.plist */, 87 | ); 88 | path = Sources; 89 | sourceTree = ""; 90 | }; 91 | 393FD9DB21132B6F00909225 /* Settings */ = { 92 | isa = PBXGroup; 93 | children = ( 94 | 393FD9DC21132B6F00909225 /* Settings.swift */, 95 | ); 96 | path = Settings; 97 | sourceTree = ""; 98 | }; 99 | 393FD9E021132B6F00909225 /* Objects */ = { 100 | isa = PBXGroup; 101 | children = ( 102 | 393FD9E121132B6F00909225 /* ScreenObject.swift */, 103 | ); 104 | path = Objects; 105 | sourceTree = ""; 106 | }; 107 | 393FD9E221132B6F00909225 /* SubViews */ = { 108 | isa = PBXGroup; 109 | children = ( 110 | 393FD9E521132B6F00909225 /* TopView */, 111 | 393FD9EB21132B6F00909225 /* FullscreenView */, 112 | 393FD9EF21132B6F00909225 /* BottomView */, 113 | ); 114 | path = SubViews; 115 | sourceTree = ""; 116 | }; 117 | 393FD9E521132B6F00909225 /* TopView */ = { 118 | isa = PBXGroup; 119 | children = ( 120 | 393FD9E621132B6F00909225 /* TopViewCells.swift */, 121 | 393FD9E721132B6F00909225 /* TopViewCollectionLayout.swift */, 122 | 393FD9E821132B6F00909225 /* SizingView.swift */, 123 | 393FD9E921132B6F00909225 /* TopViewAnimators.swift */, 124 | 393FD9EA21132B6F00909225 /* TopView.swift */, 125 | ); 126 | path = TopView; 127 | sourceTree = ""; 128 | }; 129 | 393FD9EB21132B6F00909225 /* FullscreenView */ = { 130 | isa = PBXGroup; 131 | children = ( 132 | 393FD9EC21132B6F00909225 /* CellView.swift */, 133 | 393FD9ED21132B6F00909225 /* FulllscreenView.swift */, 134 | 393FD9EE21132B6F00909225 /* LabelView.swift */, 135 | ); 136 | path = FullscreenView; 137 | sourceTree = ""; 138 | }; 139 | 393FD9EF21132B6F00909225 /* BottomView */ = { 140 | isa = PBXGroup; 141 | children = ( 142 | 393FD9F021132B6F00909225 /* BottomView.swift */, 143 | ); 144 | path = BottomView; 145 | sourceTree = ""; 146 | }; 147 | 393FD9F121132B6F00909225 /* Extensions */ = { 148 | isa = PBXGroup; 149 | children = ( 150 | 393FD9F221132B6F00909225 /* UIImage+gradient.swift */, 151 | ); 152 | path = Extensions; 153 | sourceTree = ""; 154 | }; 155 | 393FD9F321132B6F00909225 /* Components */ = { 156 | isa = PBXGroup; 157 | children = ( 158 | 393FD9F421132B6F00909225 /* Label.swift */, 159 | 393FD9F521132B6F00909225 /* PanDirectionGestureRecognizer.swift */, 160 | ); 161 | path = Components; 162 | sourceTree = ""; 163 | }; 164 | /* End PBXGroup section */ 165 | 166 | /* Begin PBXHeadersBuildPhase section */ 167 | 393FD9CC21132AD000909225 /* Headers */ = { 168 | isa = PBXHeadersBuildPhase; 169 | buildActionMask = 2147483647; 170 | files = ( 171 | 393FD9F821132B6F00909225 /* NavigationToolbar.h in Headers */, 172 | ); 173 | runOnlyForDeploymentPostprocessing = 0; 174 | }; 175 | /* End PBXHeadersBuildPhase section */ 176 | 177 | /* Begin PBXNativeTarget section */ 178 | 393FD9CE21132AD000909225 /* NavigationToolbar */ = { 179 | isa = PBXNativeTarget; 180 | buildConfigurationList = 393FD9D721132AD000909225 /* Build configuration list for PBXNativeTarget "NavigationToolbar" */; 181 | buildPhases = ( 182 | 393FD9CA21132AD000909225 /* Sources */, 183 | 393FD9CB21132AD000909225 /* Frameworks */, 184 | 393FD9CC21132AD000909225 /* Headers */, 185 | 393FD9CD21132AD000909225 /* Resources */, 186 | ); 187 | buildRules = ( 188 | ); 189 | dependencies = ( 190 | ); 191 | name = NavigationToolbar; 192 | productName = NavigationToolbar; 193 | productReference = 393FD9CF21132AD000909225 /* NavigationToolbar.framework */; 194 | productType = "com.apple.product-type.framework"; 195 | }; 196 | /* End PBXNativeTarget section */ 197 | 198 | /* Begin PBXProject section */ 199 | 393FD9C621132AD000909225 /* Project object */ = { 200 | isa = PBXProject; 201 | attributes = { 202 | LastUpgradeCheck = 0940; 203 | ORGANIZATIONNAME = Ramotion; 204 | TargetAttributes = { 205 | 393FD9CE21132AD000909225 = { 206 | CreatedOnToolsVersion = 9.4.1; 207 | LastSwiftMigration = 1010; 208 | }; 209 | }; 210 | }; 211 | buildConfigurationList = 393FD9C921132AD000909225 /* Build configuration list for PBXProject "NavigationToolbar" */; 212 | compatibilityVersion = "Xcode 9.3"; 213 | developmentRegion = en; 214 | hasScannedForEncodings = 0; 215 | knownRegions = ( 216 | en, 217 | Base, 218 | ); 219 | mainGroup = 393FD9C521132AD000909225; 220 | productRefGroup = 393FD9D021132AD000909225 /* Products */; 221 | projectDirPath = ""; 222 | projectRoot = ""; 223 | targets = ( 224 | 393FD9CE21132AD000909225 /* NavigationToolbar */, 225 | ); 226 | }; 227 | /* End PBXProject section */ 228 | 229 | /* Begin PBXResourcesBuildPhase section */ 230 | 393FD9CD21132AD000909225 /* Resources */ = { 231 | isa = PBXResourcesBuildPhase; 232 | buildActionMask = 2147483647; 233 | files = ( 234 | ); 235 | runOnlyForDeploymentPostprocessing = 0; 236 | }; 237 | /* End PBXResourcesBuildPhase section */ 238 | 239 | /* Begin PBXSourcesBuildPhase section */ 240 | 393FD9CA21132AD000909225 /* Sources */ = { 241 | isa = PBXSourcesBuildPhase; 242 | buildActionMask = 2147483647; 243 | files = ( 244 | 393FD9FD21132B6F00909225 /* TopViewCollectionLayout.swift in Sources */, 245 | 393FD9FF21132B6F00909225 /* TopViewAnimators.swift in Sources */, 246 | 393FDA0421132B6F00909225 /* BottomView.swift in Sources */, 247 | 393FD9FA21132B6F00909225 /* ScreenObject.swift in Sources */, 248 | 393FDA0521132B6F00909225 /* UIImage+gradient.swift in Sources */, 249 | 393FDA0221132B6F00909225 /* FulllscreenView.swift in Sources */, 250 | 393FDA0721132B6F00909225 /* PanDirectionGestureRecognizer.swift in Sources */, 251 | 393FD9FC21132B6F00909225 /* TopViewCells.swift in Sources */, 252 | 393FD9FE21132B6F00909225 /* SizingView.swift in Sources */, 253 | 393FDA0821132B6F00909225 /* NavigationView.swift in Sources */, 254 | 393FDA0321132B6F00909225 /* LabelView.swift in Sources */, 255 | 393FDA0021132B6F00909225 /* TopView.swift in Sources */, 256 | 393FD9F721132B6F00909225 /* Settings.swift in Sources */, 257 | 393FDA0621132B6F00909225 /* Label.swift in Sources */, 258 | 393FDA0121132B6F00909225 /* CellView.swift in Sources */, 259 | ); 260 | runOnlyForDeploymentPostprocessing = 0; 261 | }; 262 | /* End PBXSourcesBuildPhase section */ 263 | 264 | /* Begin XCBuildConfiguration section */ 265 | 393FD9D521132AD000909225 /* Debug */ = { 266 | isa = XCBuildConfiguration; 267 | buildSettings = { 268 | ALWAYS_SEARCH_USER_PATHS = NO; 269 | CLANG_ANALYZER_NONNULL = YES; 270 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 271 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 272 | CLANG_CXX_LIBRARY = "libc++"; 273 | CLANG_ENABLE_MODULES = YES; 274 | CLANG_ENABLE_OBJC_ARC = YES; 275 | CLANG_ENABLE_OBJC_WEAK = YES; 276 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 277 | CLANG_WARN_BOOL_CONVERSION = YES; 278 | CLANG_WARN_COMMA = YES; 279 | CLANG_WARN_CONSTANT_CONVERSION = YES; 280 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 281 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 282 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 283 | CLANG_WARN_EMPTY_BODY = YES; 284 | CLANG_WARN_ENUM_CONVERSION = YES; 285 | CLANG_WARN_INFINITE_RECURSION = YES; 286 | CLANG_WARN_INT_CONVERSION = YES; 287 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 288 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 289 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 290 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 291 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 292 | CLANG_WARN_STRICT_PROTOTYPES = YES; 293 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 294 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 295 | CLANG_WARN_UNREACHABLE_CODE = YES; 296 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 297 | CODE_SIGN_IDENTITY = "iPhone Developer"; 298 | COPY_PHASE_STRIP = NO; 299 | CURRENT_PROJECT_VERSION = 1; 300 | DEBUG_INFORMATION_FORMAT = dwarf; 301 | ENABLE_STRICT_OBJC_MSGSEND = YES; 302 | ENABLE_TESTABILITY = YES; 303 | GCC_C_LANGUAGE_STANDARD = gnu11; 304 | GCC_DYNAMIC_NO_PIC = NO; 305 | GCC_NO_COMMON_BLOCKS = YES; 306 | GCC_OPTIMIZATION_LEVEL = 0; 307 | GCC_PREPROCESSOR_DEFINITIONS = ( 308 | "DEBUG=1", 309 | "$(inherited)", 310 | ); 311 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 312 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 313 | GCC_WARN_UNDECLARED_SELECTOR = YES; 314 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 315 | GCC_WARN_UNUSED_FUNCTION = YES; 316 | GCC_WARN_UNUSED_VARIABLE = YES; 317 | IPHONEOS_DEPLOYMENT_TARGET = 11.4; 318 | MTL_ENABLE_DEBUG_INFO = YES; 319 | ONLY_ACTIVE_ARCH = YES; 320 | SDKROOT = iphoneos; 321 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 322 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 323 | VERSIONING_SYSTEM = "apple-generic"; 324 | VERSION_INFO_PREFIX = ""; 325 | }; 326 | name = Debug; 327 | }; 328 | 393FD9D621132AD000909225 /* Release */ = { 329 | isa = XCBuildConfiguration; 330 | buildSettings = { 331 | ALWAYS_SEARCH_USER_PATHS = NO; 332 | CLANG_ANALYZER_NONNULL = YES; 333 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 334 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 335 | CLANG_CXX_LIBRARY = "libc++"; 336 | CLANG_ENABLE_MODULES = YES; 337 | CLANG_ENABLE_OBJC_ARC = YES; 338 | CLANG_ENABLE_OBJC_WEAK = YES; 339 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 340 | CLANG_WARN_BOOL_CONVERSION = YES; 341 | CLANG_WARN_COMMA = YES; 342 | CLANG_WARN_CONSTANT_CONVERSION = YES; 343 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 344 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 345 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 346 | CLANG_WARN_EMPTY_BODY = YES; 347 | CLANG_WARN_ENUM_CONVERSION = YES; 348 | CLANG_WARN_INFINITE_RECURSION = YES; 349 | CLANG_WARN_INT_CONVERSION = YES; 350 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 351 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 352 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 353 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 354 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 355 | CLANG_WARN_STRICT_PROTOTYPES = YES; 356 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 357 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 358 | CLANG_WARN_UNREACHABLE_CODE = YES; 359 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 360 | CODE_SIGN_IDENTITY = "iPhone Developer"; 361 | COPY_PHASE_STRIP = NO; 362 | CURRENT_PROJECT_VERSION = 1; 363 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 364 | ENABLE_NS_ASSERTIONS = NO; 365 | ENABLE_STRICT_OBJC_MSGSEND = YES; 366 | GCC_C_LANGUAGE_STANDARD = gnu11; 367 | GCC_NO_COMMON_BLOCKS = YES; 368 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 369 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 370 | GCC_WARN_UNDECLARED_SELECTOR = YES; 371 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 372 | GCC_WARN_UNUSED_FUNCTION = YES; 373 | GCC_WARN_UNUSED_VARIABLE = YES; 374 | IPHONEOS_DEPLOYMENT_TARGET = 11.4; 375 | MTL_ENABLE_DEBUG_INFO = NO; 376 | SDKROOT = iphoneos; 377 | SWIFT_COMPILATION_MODE = wholemodule; 378 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 379 | VALIDATE_PRODUCT = YES; 380 | VERSIONING_SYSTEM = "apple-generic"; 381 | VERSION_INFO_PREFIX = ""; 382 | }; 383 | name = Release; 384 | }; 385 | 393FD9D821132AD000909225 /* Debug */ = { 386 | isa = XCBuildConfiguration; 387 | buildSettings = { 388 | CODE_SIGN_IDENTITY = ""; 389 | CODE_SIGN_STYLE = Automatic; 390 | DEFINES_MODULE = YES; 391 | DEVELOPMENT_TEAM = 34MUF9YXTA; 392 | DYLIB_COMPATIBILITY_VERSION = 1; 393 | DYLIB_CURRENT_VERSION = 1; 394 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 395 | INFOPLIST_FILE = Sources/Info.plist; 396 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 397 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 398 | LD_RUNPATH_SEARCH_PATHS = ( 399 | "$(inherited)", 400 | "@executable_path/Frameworks", 401 | "@loader_path/Frameworks", 402 | ); 403 | PRODUCT_BUNDLE_IDENTIFIER = com.ramotion.NavigationToolbar; 404 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 405 | SKIP_INSTALL = YES; 406 | SWIFT_VERSION = 5.0; 407 | TARGETED_DEVICE_FAMILY = "1,2"; 408 | }; 409 | name = Debug; 410 | }; 411 | 393FD9D921132AD000909225 /* Release */ = { 412 | isa = XCBuildConfiguration; 413 | buildSettings = { 414 | CODE_SIGN_IDENTITY = ""; 415 | CODE_SIGN_STYLE = Automatic; 416 | DEFINES_MODULE = YES; 417 | DEVELOPMENT_TEAM = 34MUF9YXTA; 418 | DYLIB_COMPATIBILITY_VERSION = 1; 419 | DYLIB_CURRENT_VERSION = 1; 420 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 421 | INFOPLIST_FILE = Sources/Info.plist; 422 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 423 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 424 | LD_RUNPATH_SEARCH_PATHS = ( 425 | "$(inherited)", 426 | "@executable_path/Frameworks", 427 | "@loader_path/Frameworks", 428 | ); 429 | PRODUCT_BUNDLE_IDENTIFIER = com.ramotion.NavigationToolbar; 430 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 431 | SKIP_INSTALL = YES; 432 | SWIFT_VERSION = 5.0; 433 | TARGETED_DEVICE_FAMILY = "1,2"; 434 | }; 435 | name = Release; 436 | }; 437 | /* End XCBuildConfiguration section */ 438 | 439 | /* Begin XCConfigurationList section */ 440 | 393FD9C921132AD000909225 /* Build configuration list for PBXProject "NavigationToolbar" */ = { 441 | isa = XCConfigurationList; 442 | buildConfigurations = ( 443 | 393FD9D521132AD000909225 /* Debug */, 444 | 393FD9D621132AD000909225 /* Release */, 445 | ); 446 | defaultConfigurationIsVisible = 0; 447 | defaultConfigurationName = Release; 448 | }; 449 | 393FD9D721132AD000909225 /* Build configuration list for PBXNativeTarget "NavigationToolbar" */ = { 450 | isa = XCConfigurationList; 451 | buildConfigurations = ( 452 | 393FD9D821132AD000909225 /* Debug */, 453 | 393FD9D921132AD000909225 /* Release */, 454 | ); 455 | defaultConfigurationIsVisible = 0; 456 | defaultConfigurationName = Release; 457 | }; 458 | /* End XCConfigurationList section */ 459 | }; 460 | rootObject = 393FD9C621132AD000909225 /* Project object */; 461 | } 462 | -------------------------------------------------------------------------------- /NavigationToolbar.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /NavigationToolbar.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /NavigationToolbar.xcodeproj/xcshareddata/xcschemes/NavigationToolbar.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.1 2 | // 3 | // Package.swift 4 | // 5 | // Copyright (c) Ramotion (https://www.ramotion.com/) 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | // 25 | 26 | import PackageDescription 27 | 28 | 29 | let package = Package( 30 | name: "NavigationToolbar", 31 | platforms: [ 32 | .iOS(.v9) 33 | ], 34 | products: [ 35 | .library(name: "NavigationToolbar", 36 | targets: ["NavigationToolbar"]), 37 | ], 38 | targets: [ 39 | .target(name: "NavigationToolbar", 40 | path: "Sources") 41 | ], 42 | swiftLanguageVersions: [.v5] 43 | ) 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |

NAVIGATION TOOLBAR

7 | 8 |

Navigation toolbar is a Swift slide-modeled UI navigation controller.

9 | 10 | 11 | ___ 12 | 13 | 14 | 15 |

We specialize in the designing and coding of custom UI for Mobile Apps and Websites.
16 | 17 | 18 |

19 |

Stay tuned for the latest updates:
20 | 21 |

22 | 23 |
24 | 25 | [![Twitter](https://img.shields.io/badge/Twitter-@Ramotion-blue.svg?style=flat)](http://twitter.com/Ramotion) 26 | [![CocoaPods](https://img.shields.io/cocoapods/p/navigation-toolbar.svg)](https://cocoapods.org/pods/Navigation-Toolbar) 27 | [![CocoaPods](https://img.shields.io/cocoapods/v/navigation-toolbar.svg)](http://cocoapods.org/pods/Navigation-Toolbar) 28 | [![Carthage compatible](https://img.shields.io/badge/Carthage-uncompatible-4BC51D.svg?style=flat)](https://github.com/Ramotion/navigation-toolbar) 29 | [![codebeat badge](https://codebeat.co/badges/9460af06-c0f9-4063-8bb5-a802136d3cbf)](https://codebeat.co/projects/github-com-ramotion-navigation-toolbar-master) 30 | [![Donate](https://img.shields.io/badge/Donate-PayPal-blue.svg)](https://paypal.me/Ramotion) 31 | 32 | 33 | ## Requirements 34 | 35 | - iOS 10.0+ 36 | - Xcode 9 37 | 38 | ## Installation 39 | 40 | Just add the Source folder to your project. 41 | 42 | or use [CocoaPods](https://cocoapods.org) with Podfile: 43 | 44 | ``` ruby 45 | pod 'Navigation-Toolbar' 46 | ``` 47 | 48 | or [Carthage](https://github.com/Carthage/Carthage) users can simply add to their `Cartfile`: 49 | ``` 50 | github "Ramotion/navigation-toolbar" 51 | ``` 52 | 53 | ## Usage 54 | 55 | #### Storyboard 56 | 57 | 1) Create a new UIView inheriting from ```NavigationView``` 58 | 59 | 2) Create ScreenObject for every required screen with configuration, see example: 60 | 61 | ``` swift 62 | class ViewController: UIViewController { 63 | 64 | private var navigationView: NavigationView? 65 | 66 | override func viewDidLoad() { 67 | super.viewDidLoad() 68 | 69 | navigationView = NavigationView.init(frame: view.bounds, 70 | middleView: MiddleView(), 71 | screens: [ 72 | ScreenObject(title: "MUSIC", 73 | startColor: .red, 74 | endColor: .blue, 75 | image: UIImage(named : "image1")!, 76 | controller: YourFirstViewController()), 77 | 78 | ScreenObject(title: "EDUCATION", 79 | startColor: .black, 80 | endColor: .white, 81 | image: UIImage(named : "image2")!, 82 | controller: YourSecondViewController()), 83 | ], 84 | backgroundImage: #imageLiteral(resourceName: "background")) 85 | 86 | navigationView?.autoresizingMask = [.flexibleWidth, .flexibleHeight] 87 | view.addSubview(navigationView!) 88 | } 89 | 90 | } 91 | ``` 92 | 93 | 94 | ## 🗂 Check this library on other language: 95 | 96 | 97 | 98 | 99 | ## 📄 License 100 | 101 | Navigation Toolbar is released under the MIT license. 102 | See [LICENSE](./LICENSE) for details. 103 | 104 | This library is a part of a selection of our best UI open-source projects. 105 | 106 | If you use the open-source library in your project, please make sure to credit and backlink to www.ramotion.com 107 | 108 | ## 📱 Get the Showroom App for iOS to give it a try 109 | Try this UI component and more like this in our iOS app. Contact us if interested. 110 | 111 | 112 | 113 | 114 | 115 | 116 |
117 |
118 | -------------------------------------------------------------------------------- /Sources/Components/Label.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Label.swift 3 | // NavigationToolbar 4 | // 5 | // Created by Artem P. on 22/05/2018. 6 | // Copyright © 2018 Ramotion. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class Label: UILabel { 12 | 13 | class func topViewCellLabel() -> UILabel { 14 | let label = UILabel() 15 | label.clipsToBounds = false 16 | label.textColor = .white 17 | label.font = UIFont.systemFont(ofSize: Settings.Sizes.labelFontSize) 18 | label.textAlignment = .center 19 | 20 | return label 21 | } 22 | 23 | class func sideLabel() -> UILabel { 24 | let label = UILabel() 25 | label.clipsToBounds = false 26 | label.textColor = .white 27 | label.font = UIFont.systemFont(ofSize: Settings.Sizes.labelFontSize) 28 | label.textAlignment = .center 29 | 30 | return label 31 | } 32 | 33 | class func menuCellLabel() -> UILabel { 34 | let label = UILabel() 35 | label.textAlignment = .left 36 | label.clipsToBounds = false 37 | label.textColor = .white 38 | label.font = UIFont.systemFont(ofSize: Settings.Sizes.labelFontSize) 39 | 40 | return label 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /Sources/Components/PanDirectionGestureRecognizer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PanGestureRecognizer.swift 3 | // NavigationToolbar 4 | // 5 | // Created by Artem P. on 22/05/2018. 6 | // Copyright © 2018 Ramotion. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit.UIGestureRecognizerSubclass 11 | 12 | enum PanDirection { 13 | case vertical 14 | case horizontal 15 | } 16 | 17 | class PanDirectionGestureRecognizer: UIPanGestureRecognizer { 18 | 19 | let direction: PanDirection 20 | 21 | init(direction: PanDirection, target: AnyObject, action: Selector) { 22 | self.direction = direction 23 | super.init(target: target, action: action) 24 | } 25 | 26 | override func touchesMoved(_ touches: Set, with event: UIEvent) { 27 | super.touchesMoved(touches, with: event) 28 | 29 | if state == .began { 30 | let vel = velocity(in: view) 31 | switch direction { 32 | case .horizontal where abs(vel.y) > abs(vel.x): 33 | state = .cancelled 34 | case .vertical where abs(vel.x) > abs(vel.y): 35 | state = .cancelled 36 | default: 37 | break 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Sources/Extensions/UIImage+gradient.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+gradient.swift 3 | // NavigationToolbar 4 | // 5 | // Created by Artem P. on 22/05/2018. 6 | // Copyright © 2018 Ramotion. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIImage { 12 | 13 | static func makeImageWithGradient(image: UIImage = UIImage(), imageAlpha: CGFloat = Settings.imageAlpha, startColor: UIColor = UIColor.red, endColor: UIColor = UIColor.blue) -> UIImage { 14 | let layer = CAGradientLayer() 15 | layer.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: Settings.Sizes.middleSize) 16 | layer.colors = [startColor.cgColor, endColor.cgColor] 17 | layer.startPoint = CGPoint(x: 0, y: 0.5) 18 | layer.endPoint = CGPoint(x: 1, y: 0.5) 19 | 20 | UIGraphicsBeginImageContext(CGSize(width: layer.frame.width, height: layer.frame.height)) 21 | layer.render(in: UIGraphicsGetCurrentContext()!) 22 | let gradientImage = UIGraphicsGetImageFromCurrentImageContext() 23 | UIGraphicsEndImageContext() 24 | 25 | return mergeImages(bottom: gradientImage!, top: image, alpha: imageAlpha) 26 | } 27 | 28 | static func mergeImages(bottom: UIImage, top: UIImage, alpha: CGFloat) -> UIImage { 29 | let bottomImage = bottom 30 | let topImage = top 31 | 32 | let size = CGSize(width: Settings.Sizes.screenWidth, height: Settings.Sizes.middleSize) 33 | UIGraphicsBeginImageContext(size) 34 | 35 | let areaSize = CGRect(x: 0, y: 0, width: size.width, height: size.height) 36 | bottomImage.draw(in: areaSize) 37 | 38 | topImage.draw(in: areaSize, blendMode: .normal, alpha: alpha) 39 | 40 | let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()! 41 | UIGraphicsEndImageContext() 42 | 43 | return newImage 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Sources/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Sources/NavigationToolbar.h: -------------------------------------------------------------------------------- 1 | // 2 | // NavigationToolbar.h 3 | // NavigationToolbar 4 | // 5 | // Created by Xorosho on 8/2/18. 6 | // Copyright © 2018 Ramotion. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for NavigationToolbar. 12 | FOUNDATION_EXPORT double NavigationToolbarVersionNumber; 13 | 14 | //! Project version string for NavigationToolbar. 15 | FOUNDATION_EXPORT const unsigned char NavigationToolbarVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /Sources/NavigationView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NavigationView.swift 3 | // NavigationToolbar 4 | // 5 | // Created by Artem P. on 22/05/2018. 6 | // Copyright © 2018 Ramotion. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | enum State { 12 | case horizontal 13 | case vertical 14 | } 15 | 16 | open class NavigationView: UIView { 17 | 18 | private var backGroundImageView = UIImageView() 19 | private var topView = TopView() 20 | private var middleView: UIView! 21 | private var bottomView = BottomView() 22 | private var fullscreenView = FulllscreenView() 23 | private var panRecognizer: PanDirectionGestureRecognizer! 24 | private var screens: [ScreenObject]! 25 | private var backgroundImage: UIImage! 26 | 27 | public var currentIndex: Int = 0 { 28 | didSet { 29 | topView.currentIndex = currentIndex 30 | fullscreenView.currentIndex = currentIndex 31 | bottomView.currentIndex = currentIndex 32 | } 33 | } 34 | 35 | private var middleOriginY: CGFloat = Settings.Sizes.navbarSize { 36 | didSet { 37 | setNeedsLayout() 38 | layoutIfNeeded() 39 | } 40 | } 41 | 42 | public init(frame: CGRect, middleView: UIView, screens: [ScreenObject], backgroundImage: UIImage) { 43 | self.middleView = middleView 44 | self.screens = screens 45 | self.backgroundImage = backgroundImage 46 | 47 | super.init(frame: frame) 48 | 49 | setup() 50 | } 51 | 52 | required public init?(coder aDecoder: NSCoder) { 53 | super.init(coder: aDecoder) 54 | setup() 55 | } 56 | 57 | private func setup() { 58 | setData() 59 | 60 | backGroundImageView.image = UIImage(named: "background") 61 | 62 | topView.backgroundColor = .clear 63 | bottomView.backgroundColor = .white 64 | bottomView.delegate = self 65 | topView.delegate = self 66 | 67 | fullscreenView.delegate = self 68 | 69 | addSubview(backGroundImageView) 70 | addSubview(fullscreenView) 71 | addSubview(topView) 72 | addSubview(bottomView) 73 | addSubview(middleView) 74 | 75 | panRecognizer = PanDirectionGestureRecognizer(direction: .vertical, 76 | target: self, 77 | action: #selector(processPan)) 78 | 79 | panRecognizer.delaysTouchesBegan = false 80 | panRecognizer.delaysTouchesEnded = false 81 | 82 | panRecognizer.delegate = self 83 | addGestureRecognizer(panRecognizer!) 84 | } 85 | 86 | override open func layoutSubviews() { 87 | super.layoutSubviews() 88 | 89 | if middleOriginY < Settings.Sizes.navbarSize { middleOriginY = Settings.Sizes.navbarSize } 90 | 91 | backGroundImageView.frame = bounds 92 | 93 | topView.frame = CGRect(x: 0, 94 | y: 0, 95 | width: bounds.width, 96 | height: Settings.Sizes.middleSize) 97 | 98 | middleView.frame = CGRect(x: 0, 99 | y: middleOriginY, 100 | width: bounds.width, 101 | height: Settings.Sizes.middleViewSize) 102 | 103 | topView.setSizingViewHeight(height: middleView.frame.minY) 104 | 105 | bottomView.frame = CGRect(x: 0, 106 | y: middleView.frame.maxY, 107 | width: bounds.width, 108 | height: bounds.height - middleView.frame.maxY) 109 | 110 | fullscreenView.frame = bounds 111 | 112 | fullscreenView.progress = getNormalizedProgress() 113 | 114 | topView.setSizingViewProgress(progress: (middleView.frame.origin.y - Settings.Sizes.navbarSize) / (Settings.Sizes.middleSize - Settings.Sizes.navbarSize)) 115 | 116 | if fullscreenView.state == .vertical { 117 | fullscreenView.setScrollOffset() 118 | } 119 | 120 | if middleOriginY > bounds.height { 121 | panRecognizer.isEnabled = false 122 | fullscreenView.updateVerticalScrollInsets() 123 | } 124 | } 125 | 126 | public func setMiddleView(middleView: UIView) { 127 | self.middleView = middleView 128 | self.setNeedsLayout() 129 | self.setNeedsDisplay() 130 | self.layoutIfNeeded() 131 | } 132 | 133 | public func setData() { 134 | var titles: [String] = [] 135 | var images: [UIImage] = [] 136 | var controllers: [UIViewController] = [] 137 | 138 | for screen in screens { 139 | titles.append(screen.title) 140 | images.append(UIImage.makeImageWithGradient(image: screen.image, 141 | imageAlpha: Settings.imageAlpha, 142 | startColor: screen.startColor, 143 | endColor: screen.endColor)) 144 | controllers.append(screen.controller) 145 | } 146 | 147 | topView.setData(titles: titles, images: images) 148 | fullscreenView.setData(titles: titles, images: images) 149 | bottomView.setData(controllers: controllers) 150 | 151 | backGroundImageView.image = backgroundImage 152 | } 153 | 154 | } 155 | 156 | extension NavigationView { 157 | 158 | @objc private func processPan() { 159 | var translation = panRecognizer.translation(in: self) 160 | 161 | var canPan: Bool = false 162 | 163 | let controlRect: CGRect = CGRect(x: 0, 164 | y: 0, 165 | width: bounds.width, 166 | height: middleOriginY + Settings.Sizes.middleViewSize) 167 | 168 | let touchLocation = panRecognizer.location(in: self) 169 | 170 | let velocity = panRecognizer.velocity(in: self) 171 | 172 | if controlRect.contains(touchLocation) { 173 | canPan = true 174 | } 175 | 176 | if bottomView.canScrollDown { 177 | canPan = true 178 | } 179 | 180 | var currentDirection: Int = 0 181 | 182 | if velocity.y > 0 { 183 | currentDirection = 2 184 | } else { 185 | currentDirection = 1 186 | } 187 | 188 | if currentDirection == 1 && middleOriginY >= Settings.Sizes.middleSize { 189 | bottomView.canScroll = false 190 | } else { 191 | bottomView.canScroll = true 192 | } 193 | 194 | switch panRecognizer.state { 195 | case .began, .changed: 196 | if canPan { 197 | topView.isScrollingEnabled = false 198 | bottomView.isScrollingEnabled = false 199 | middleOriginY = middleView.frame.origin.y + translation.y 200 | if middleOriginY < Settings.Sizes.navbarSize { middleOriginY = Settings.Sizes.navbarSize } 201 | if translation.y < Settings.Sizes.navbarSize { translation.y = Settings.Sizes.navbarSize } 202 | 203 | if 0...Settings.Sizes.navbarSize ~= middleOriginY { 204 | topView.isHidden = false 205 | topView.hideSizingView() 206 | topView.toggleTopStateViews() 207 | fullscreenView.state = .horizontal 208 | fullscreenView.updateHorizontalScrollInsets() 209 | } else if Settings.Sizes.navbarSize + 1.. bounds.height { 231 | fullscreenView.isHidden = false 232 | panRecognizer.isEnabled = false 233 | fullscreenView.updateVerticalScrollInsets() 234 | canPan = false 235 | fullscreenView.resetAlpha() 236 | } 237 | } 238 | 239 | case .possible, .ended, .cancelled, .failed: 240 | topView.isScrollingEnabled = true 241 | bottomView.isScrollingEnabled = true 242 | if 0...Settings.Sizes.middleSizeHalf ~= middleOriginY { 243 | UIView.animate(withDuration: Settings.animationsDuration, animations: { 244 | self.middleOriginY = Settings.Sizes.navbarSize 245 | self.topView.setSizingViewProgress(progress: 0.0) 246 | }) { _ in 247 | self.topView.hideSizingView() 248 | self.topView.isHidden = false 249 | self.topView.toggleTopStateViews() 250 | self.fullscreenView.updateHorizontalScrollInsets() 251 | } 252 | } else if Settings.Sizes.middleSizeHalf + 1...Settings.Sizes.middleSize ~= middleOriginY { 253 | UIView.animate(withDuration: Settings.animationsDuration, animations: { 254 | self.middleOriginY = Settings.Sizes.middleSize 255 | self.topView.setSizingViewProgress(progress: 1.0) 256 | }) { _ in 257 | self.topView.hideSizingView() 258 | self.topView.isHidden = false 259 | self.topView.toggleMiddleStateViews() 260 | self.fullscreenView.updateHorizontalScrollInsets() 261 | } 262 | } else if Settings.Sizes.middleSize + 1...bounds.height * 0.75 ~= middleOriginY { 263 | UIView.animate(withDuration: Settings.animationsDuration, animations: { 264 | self.middleOriginY = Settings.Sizes.middleSize 265 | }) { _ in 266 | self.topView.hideSizingView() 267 | self.topView.isHidden = false 268 | self.fullscreenView.isHidden = true 269 | self.topView.toggleMiddleStateViews() 270 | self.fullscreenView.updateVerticalScrollInsets() 271 | } 272 | } else if bounds.height * 0.75 + 1...bounds.height ~= middleOriginY { 273 | UIView.animate(withDuration: Settings.animationsDuration, animations: { 274 | self.middleOriginY = self.bounds.height 275 | }) { _ in 276 | self.topView.hideSizingView() 277 | self.fullscreenView.updateVerticalScrollInsets() 278 | self.panRecognizer.isEnabled = false 279 | } 280 | } 281 | 282 | @unknown default: 283 | break 284 | } 285 | panRecognizer.setTranslation(CGPoint.zero, in: self) 286 | } 287 | 288 | } 289 | 290 | extension NavigationView: UIGestureRecognizerDelegate { 291 | 292 | public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { return true } 293 | public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRequireFailureOf otherGestureRecognizer: UIGestureRecognizer) -> Bool { return false } 294 | public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldBeRequiredToFailBy otherGestureRecognizer: UIGestureRecognizer) -> Bool { return false } 295 | 296 | override open func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { 297 | let velocity = panRecognizer.velocity(in: self) 298 | return abs(velocity.y) > abs(velocity.x) 299 | } 300 | 301 | } 302 | 303 | extension NavigationView: FulllscreenViewDelegate { 304 | 305 | func didTapCell(index: Int) { 306 | currentIndex = index 307 | topView.updateOffsets() 308 | bottomView.updateOffsets() 309 | panRecognizer.isEnabled = true 310 | 311 | UIView.animate(withDuration: Settings.animationsDuration, delay: 0.0, options: .curveEaseOut, animations: { 312 | self.middleOriginY = Settings.Sizes.middleSize 313 | self.setNeedsLayout() 314 | self.layoutIfNeeded() 315 | }) { completed in 316 | if completed { 317 | self.topView.isHidden = false 318 | self.fullscreenView.isHidden = true 319 | self.topView.toggleMiddleStateViews() 320 | self.fullscreenView.updateHorizontalScrollInsets() 321 | } 322 | } 323 | } 324 | 325 | } 326 | 327 | extension NavigationView { 328 | 329 | private func getNormalizedProgress() -> CGFloat { 330 | if Settings.Sizes.middleSize...bounds.height ~= middleView.frame.origin.y { 331 | let diff: CGFloat = bounds.height - Settings.Sizes.middleSize 332 | 333 | return (middleView.frame.minY - Settings.Sizes.middleSize) / diff > 1.0 ? 1.0 : (middleView.frame.minY - Settings.Sizes.middleSize) / diff 334 | } 335 | if middleView.frame.origin.y > bounds.height { 336 | return 1.0 337 | } 338 | 339 | return 0.0 340 | } 341 | } 342 | 343 | extension NavigationView: BottomViewDelegate { 344 | 345 | func bottomDidScroll(offset: CGFloat) { 346 | topView.currentOffset = offset 347 | topView.updateIndex() 348 | } 349 | } 350 | 351 | extension NavigationView: TopViewDelegate { 352 | 353 | func topDidScroll(offset: CGFloat) { 354 | bottomView.currentOffset = offset 355 | topView.updateIndex() 356 | } 357 | } 358 | -------------------------------------------------------------------------------- /Sources/Objects/ScreenObject.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ScreenObject.swift 3 | // NavigationToolbar 4 | // 5 | // Created by Artem P. on 22/05/2018. 6 | // Copyright © 2018 Ramotion. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | open class ScreenObject { 13 | 14 | public let title: String 15 | public let startColor: UIColor 16 | public let endColor: UIColor 17 | public let image: UIImage 18 | public let controller: UIViewController 19 | 20 | public init(title: String = "Screen Title", 21 | startColor: UIColor = .red, 22 | endColor: UIColor = .green, 23 | image: UIImage = UIImage(), 24 | controller: UIViewController = UIViewController()) { 25 | 26 | self.title = title 27 | self.startColor = startColor 28 | self.endColor = endColor 29 | self.image = image 30 | self.controller = controller 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Sources/Settings/Settings.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Settings.swift 3 | // NavigationToolbar 4 | // 5 | // Created by Artem P. on 22/05/2018. 6 | // Copyright © 2018 Ramotion. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | public struct Settings { 13 | 14 | public struct Sizes { 15 | public static let isX: Bool = UIScreen.main.nativeBounds.height == 2436 ? true : false 16 | public static let statusbarSize: CGFloat = UIApplication.shared.statusBarFrame.height 17 | public static let navbarSize: CGFloat = isX ? 88 : 64 18 | public static let middleSize: CGFloat = Settings.Sizes.screenHeight / 2 - middleViewSize / 2 19 | public static let middleSizeHalf: CGFloat = (Settings.Sizes.screenHeight / 2 - middleViewSize / 2) / 2 20 | public static let fullSize: CGFloat = Settings.Sizes.screenHeight 21 | public static let middleViewSize: CGFloat = 65.5 22 | public static let menuItemsSize: CGFloat = 120.0 23 | public static let screenWidth = UIScreen.main.bounds.width 24 | public static let screenHeight = UIScreen.main.bounds.height 25 | public static let labelFontSize: CGFloat = 23 26 | public static let yOffset: CGFloat = isX ? 32 : 20 27 | public static let mainOffset: CGFloat = 200 28 | } 29 | 30 | public static var animationsDuration: TimeInterval = 0.35 31 | public static var imageCrossOffset: CGFloat = 20 32 | public static var imageAlpha: CGFloat = 0.33 33 | public static var menuItemsSpacing: CGFloat = 4 34 | public static var menuItemTextMargin: CGFloat = 40 35 | 36 | } 37 | -------------------------------------------------------------------------------- /Sources/SubViews/BottomView/BottomView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BottomView.swift 3 | // NavigationToolbar 4 | // 5 | // Created by Artem P. on 22/05/2018. 6 | // Copyright © 2018 Ramotion. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIView { 12 | 13 | func subViews(type: T.Type) -> [T] { 14 | var all = [T]() 15 | for view in self.subviews { 16 | if let aView = view as? T { 17 | all.append(aView) 18 | } 19 | } 20 | return all 21 | } 22 | 23 | func allSubViewsOf(type: T.Type) -> [T] { 24 | var all = [T]() 25 | func getSubview(view: UIView) { 26 | if let aView = view as? T { 27 | all.append(aView) 28 | } 29 | guard view.subviews.count>0 else { return } 30 | view.subviews.forEach { getSubview(view: $0) } 31 | } 32 | getSubview(view: self) 33 | 34 | return all 35 | } 36 | } 37 | 38 | protocol BottomViewDelegate { 39 | func bottomDidScroll(offset: CGFloat) 40 | } 41 | 42 | class BottomView: UIView { 43 | 44 | private var scrollView: UIScrollView = UIScrollView() 45 | private var controllers: [UIViewController] = [] 46 | 47 | var delegate: BottomViewDelegate? 48 | 49 | var isScrollingEnabled: Bool = true { 50 | didSet { 51 | scrollView.isScrollEnabled = isScrollingEnabled 52 | } 53 | } 54 | 55 | var canScroll: Bool = true { 56 | didSet { 57 | let needle = getRequiredView() 58 | needle.isScrollEnabled = canScroll 59 | } 60 | } 61 | 62 | var canScrollDown: Bool { 63 | get { 64 | let needle = getRequiredView() 65 | if needle.contentOffset.y <= 0 { 66 | return true 67 | } 68 | return false 69 | } 70 | } 71 | 72 | var currentOffset: CGFloat = 0.0 { 73 | didSet { 74 | self.scrollView.contentOffset.x = currentOffset 75 | } 76 | } 77 | 78 | var currentIndex: Int = 0 79 | 80 | override init(frame: CGRect) { 81 | super.init(frame: frame) 82 | setup() 83 | } 84 | 85 | required init?(coder aDecoder: NSCoder) { 86 | super.init(coder: aDecoder) 87 | setup() 88 | } 89 | 90 | private func getRequiredView() -> UIScrollView { 91 | let allSubviews = scrollView.allSubViewsOf(type: UIScrollView.self) 92 | 93 | var i = 0 94 | for view in allSubviews { 95 | if view.contentSize.width == bounds.width { 96 | let frame = (view.convert(view.frame, to: self)) 97 | if frame.origin.x == 0 { 98 | return view 99 | } 100 | i += 1 101 | } 102 | } 103 | 104 | return UIScrollView() 105 | } 106 | 107 | private func setup() { 108 | scrollView.showsVerticalScrollIndicator = false 109 | scrollView.showsHorizontalScrollIndicator = false 110 | scrollView.isPagingEnabled = true 111 | scrollView.delegate = self 112 | 113 | addSubview(scrollView) 114 | } 115 | 116 | override func layoutSubviews() { 117 | super.layoutSubviews() 118 | 119 | scrollView.frame = bounds 120 | scrollView.contentSize = CGSize(width : CGFloat(controllers.count) * bounds.width, height : bounds.height) 121 | 122 | for (i, controller) in controllers.enumerated() { 123 | controller.view.frame = CGRect(x: CGFloat(i) * bounds.width, y: 0, width: bounds.width, height: bounds.height) 124 | } 125 | } 126 | 127 | func setData(controllers: [UIViewController]) { 128 | self.controllers = controllers 129 | 130 | for controller in self.controllers { 131 | scrollView.addSubview(controller.view) 132 | } 133 | setNeedsLayout() 134 | layoutIfNeeded() 135 | } 136 | 137 | func updateOffsets() { 138 | scrollView.setContentOffset(CGPoint(x: CGFloat(currentIndex) * Settings.Sizes.screenWidth, y: 0), animated: false) 139 | } 140 | 141 | } 142 | 143 | extension BottomView: UIScrollViewDelegate { 144 | 145 | func scrollViewDidScroll(_ scrollView: UIScrollView) { 146 | if scrollView == self.scrollView { 147 | delegate?.bottomDidScroll(offset: scrollView.contentOffset.x) 148 | } 149 | } 150 | 151 | } 152 | -------------------------------------------------------------------------------- /Sources/SubViews/FullscreenView/CellView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AnimatedView.swift 3 | // NavigationToolbar 4 | // 5 | // Created by Artem P. on 22/05/2018. 6 | // Copyright © 2018 Ramotion. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | protocol CellViewDelegate: class { 12 | func didTapCell(index: Int, cell: CellView) 13 | } 14 | 15 | class CellView: UIView { 16 | 17 | private var imageView: UIImageView = UIImageView() 18 | private var label: UILabel = UILabel() 19 | private var view: UIView = UIView() 20 | 21 | private var imageLeftOffsetMax: CGFloat = 100 22 | private var imageLeftOffsetCurrent: CGFloat = 0 23 | private var tapGest: UITapGestureRecognizer = UITapGestureRecognizer() 24 | 25 | private var progress: CGFloat = 0.0 26 | 27 | weak var delegate: CellViewDelegate? 28 | 29 | var index: Int = 0 30 | 31 | override init(frame: CGRect) { 32 | super.init(frame: frame) 33 | setup() 34 | } 35 | 36 | required init?(coder aDecoder: NSCoder) { 37 | super.init(coder: aDecoder) 38 | setup() 39 | } 40 | 41 | private func setup() { 42 | self.backgroundColor = .clear 43 | 44 | self.clipsToBounds = true 45 | 46 | imageView.contentMode = .scaleAspectFill 47 | imageView.clipsToBounds = true 48 | imageView.isHidden = false 49 | 50 | view.backgroundColor = .white 51 | 52 | label.textAlignment = .left 53 | label.clipsToBounds = false 54 | label.textColor = .white 55 | label.font = UIFont.systemFont(ofSize : 23) 56 | 57 | label.isHidden = false 58 | 59 | tapGest.addTarget(self, action: #selector(tapCell)) 60 | self.addGestureRecognizer(tapGest) 61 | 62 | self.addSubview(imageView) 63 | self.addSubview(view) 64 | } 65 | 66 | override func layoutSubviews() { 67 | super.layoutSubviews() 68 | 69 | let w = self.bounds.width 70 | let h = self.bounds.height 71 | 72 | let half = w / 2 - label.intrinsicContentSize.width / 2 73 | 74 | label.frame = CGRect(x: half - (half - Settings.menuItemTextMargin) * progress, 75 | y: 0, 76 | width: label.intrinsicContentSize.width, 77 | height: h) 78 | 79 | imageView.frame = CGRect(x: -Settings.imageCrossOffset + imageLeftOffsetCurrent, 80 | y: 0, 81 | width: bounds.width + 2 * Settings.imageCrossOffset, 82 | height: bounds.height) 83 | } 84 | 85 | @objc private func tapCell() { 86 | self.delegate?.didTapCell(index: index, cell: self) 87 | } 88 | 89 | func setData(title: String, image: UIImage, index: Int) { 90 | label.text = title 91 | imageView.image = image 92 | self.index = index 93 | } 94 | 95 | func setState(progress: CGFloat, state: State) { 96 | imageLeftOffsetCurrent = imageLeftOffsetMax * progress 97 | self.progress = progress 98 | 99 | self.setNeedsLayout() 100 | self.layoutIfNeeded() 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /Sources/SubViews/FullscreenView/FulllscreenView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FulllscreenView.swift 3 | // NavigationToolbar 4 | // 5 | // Created by Artem P. on 22/05/2018. 6 | // Copyright © 2018 Ramotion. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | protocol FulllscreenViewDelegate { 12 | func didTapCell(index: Int) 13 | } 14 | 15 | class FulllscreenView: UIView { 16 | 17 | var scrollView: UIScrollView = UIScrollView() 18 | 19 | var delegate: FulllscreenViewDelegate? 20 | 21 | private var animatedViews: [CellView] = [] 22 | private var labelViews: [LabelView] = [] 23 | 24 | private var images: [UIImage] = [] 25 | private var titles: [String] = [] 26 | 27 | var progress: CGFloat = 0 { 28 | didSet { 29 | setNeedsLayout() 30 | layoutIfNeeded() 31 | } 32 | } 33 | 34 | var currentIndex: Int = 0 35 | 36 | var state: State = .horizontal { 37 | didSet { 38 | setNeedsLayout() 39 | layoutIfNeeded() 40 | } 41 | } 42 | 43 | override init(frame: CGRect) { 44 | super.init(frame: frame) 45 | setup() 46 | } 47 | 48 | required init?(coder aDecoder: NSCoder) { 49 | super.init(coder: aDecoder) 50 | setup() 51 | } 52 | 53 | private func setup() { 54 | backgroundColor = .clear 55 | scrollView.showsHorizontalScrollIndicator = false 56 | scrollView.showsVerticalScrollIndicator = false 57 | scrollView.alwaysBounceHorizontal = false 58 | 59 | addSubview(scrollView) 60 | } 61 | 62 | override func layoutSubviews() { 63 | super.layoutSubviews() 64 | 65 | scrollView.frame = bounds 66 | scrollView.contentSize = CGSize(width: bounds.width * CGFloat(images.count), 67 | height: CGFloat(images.count) * (Settings.menuItemsSpacing + Settings.Sizes.menuItemsSize)) 68 | 69 | for i in 0..= 0 { 78 | prevLabel = labelViews[currentIndex - 1].label 79 | } 80 | if currentIndex + 1 <= labelViews.count - 1 { 81 | nextLabel = labelViews[currentIndex + 1].label 82 | } 83 | 84 | var right: CGFloat { 85 | get { 86 | switch Settings.Sizes.screenWidth { 87 | case 320: return 128 88 | case 375: return 150 89 | case 414: return 166 90 | default: return 0 91 | } 92 | } 93 | } 94 | 95 | for labelView in labelViews { 96 | if labelView != labelViews[currentIndex] { 97 | labelView.label.alpha = 0.3 + progress * 0.7 98 | } 99 | labelViews[currentIndex].label.alpha = 1.0 100 | } 101 | 102 | prevLabel.frame = CGRect(x: prevLabel.frame.origin.x + right * (1 - progress), 103 | y: prevLabel.frame.origin.y, 104 | width: prevLabel.frame.width, 105 | height: prevLabel.frame.height) 106 | 107 | nextLabel.frame = CGRect(x: nextLabel.frame.origin.x - right + right * progress, 108 | y: nextLabel.frame.origin.y, 109 | width: nextLabel.frame.width, 110 | height: nextLabel.frame.height) 111 | } 112 | 113 | func resetAlpha() { 114 | for label in labelViews { 115 | label.alpha = 1.0 116 | } 117 | } 118 | 119 | private func makeViews() { 120 | for i in 0.. [CGRect] { 147 | var frames: [CGRect] = [] 148 | 149 | if state == .horizontal { 150 | for i in 0.. Int { 188 | return images.count 189 | } 190 | 191 | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 192 | switch collectionView { 193 | case collectionViewTop: 194 | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: String(describing: TopViewCellOne.self), for: indexPath) as! TopViewCellOne 195 | cell.setData(title: titles[indexPath.row], image: images[indexPath.row]) 196 | return cell 197 | case collectionViewMiddleImage: 198 | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: String(describing: TopViewCellTwo.self), for: indexPath) as! TopViewCellTwo 199 | cell.setImage(image: images[indexPath.row]) 200 | return cell 201 | case collectionViewMiddleText: 202 | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: String(describing: TopViewCellThree.self), for: indexPath) as! TopViewCellThree 203 | cell.setTitle(title: titles[indexPath.row]) 204 | return cell 205 | default: 206 | break 207 | } 208 | 209 | return UICollectionViewCell() 210 | } 211 | 212 | func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { 213 | return CGSize(width: bounds.width, height: collectionView.frame.height) 214 | } 215 | 216 | func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { 217 | return .zero 218 | } 219 | 220 | func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { 221 | return 0 222 | } 223 | 224 | func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { 225 | return 0 226 | } 227 | 228 | } 229 | 230 | extension TopView: UIScrollViewDelegate { 231 | 232 | func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { 233 | updateIndex() 234 | } 235 | 236 | func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer) { 237 | updateIndex() 238 | } 239 | 240 | func updateIndex() { 241 | currentIndex = Int(collectionViewMiddleImage.contentOffset.x / Settings.Sizes.screenWidth) 242 | guard let navView = superview as? NavigationView else { return } 243 | navView.currentIndex = currentIndex 244 | } 245 | 246 | func scrollViewDidScroll(_ scrollView: UIScrollView) { 247 | if collectionViewMiddleText.isTracking { 248 | collectionViewTop.contentOffset.x = collectionViewMiddleText.contentOffset.x 249 | collectionViewMiddleImage.contentOffset.x = collectionViewMiddleText.contentOffset.x 250 | delegate?.topDidScroll(offset: collectionViewMiddleText.contentOffset.x) 251 | } 252 | if collectionViewMiddleText.isDragging { 253 | collectionViewTop.contentOffset.x = collectionViewMiddleText.contentOffset.x 254 | collectionViewMiddleImage.contentOffset.x = collectionViewMiddleText.contentOffset.x 255 | delegate?.topDidScroll(offset: collectionViewMiddleText.contentOffset.x) 256 | } 257 | if collectionViewMiddleText.isDecelerating { 258 | collectionViewTop.contentOffset.x = collectionViewMiddleText.contentOffset.x 259 | collectionViewMiddleImage.contentOffset.x = collectionViewMiddleText.contentOffset.x 260 | delegate?.topDidScroll(offset: collectionViewMiddleText.contentOffset.x) 261 | } 262 | 263 | if collectionViewTop.isTracking { 264 | collectionViewMiddleText.contentOffset.x = collectionViewTop.contentOffset.x 265 | collectionViewMiddleImage.contentOffset.x = collectionViewTop.contentOffset.x 266 | delegate?.topDidScroll(offset: collectionViewTop.contentOffset.x) 267 | } 268 | if collectionViewTop.isDragging { 269 | collectionViewMiddleText.contentOffset.x = collectionViewTop.contentOffset.x 270 | collectionViewMiddleImage.contentOffset.x = collectionViewTop.contentOffset.x 271 | delegate?.topDidScroll(offset: collectionViewTop.contentOffset.x) 272 | } 273 | if collectionViewTop.isDecelerating { 274 | collectionViewMiddleText.contentOffset.x = collectionViewTop.contentOffset.x 275 | collectionViewMiddleImage.contentOffset.x = collectionViewTop.contentOffset.x 276 | delegate?.topDidScroll(offset: collectionViewTop.contentOffset.x) 277 | } 278 | } 279 | 280 | } 281 | 282 | extension TopView { 283 | 284 | func setData(titles: [String], images: [UIImage]) { 285 | self.titles = titles 286 | self.images = images 287 | 288 | collectionViewTop.reloadData() 289 | collectionViewMiddleImage.reloadData() 290 | collectionViewMiddleText.reloadData() 291 | updateIndex() 292 | } 293 | 294 | private func updateSizingView(index: Int) { 295 | var previousTitle: String = "" 296 | var nextTitle: String = "" 297 | 298 | if index - 1 >= 0 { 299 | previousTitle = titles[index - 1] 300 | } 301 | if index + 1 <= titles.count - 1 { 302 | nextTitle = titles[index + 1] 303 | } 304 | 305 | sizingView.setData(title: titles[index], 306 | image: images[index], 307 | previousTitle: previousTitle, 308 | nextTitle: nextTitle) 309 | } 310 | 311 | func updateOffsets() { 312 | let collectionContentOffset = CGPoint(x: CGFloat(currentIndex) * Settings.Sizes.screenWidth, y: 0) 313 | 314 | collectionViewTop.setContentOffset(collectionContentOffset, animated: false) 315 | collectionViewMiddleImage.setContentOffset(collectionContentOffset, animated: false) 316 | collectionViewMiddleText.setContentOffset(collectionContentOffset, animated: false) 317 | } 318 | 319 | } 320 | -------------------------------------------------------------------------------- /Sources/SubViews/TopView/TopViewAnimators.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TopViewAnimators.swift 3 | // NavigationToolbar 4 | // 5 | // Created by Artem P. on 22/05/2018. 6 | // Copyright © 2018 Ramotion. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | protocol LayoutAttributesAnimator { 12 | func animate(collectionView: UICollectionView, attributes: AnimatedCollectionViewLayoutAttributes) 13 | } 14 | 15 | struct FadeAnimator: LayoutAttributesAnimator { 16 | init() {} 17 | 18 | func animate(collectionView: UICollectionView, attributes: AnimatedCollectionViewLayoutAttributes) { 19 | let position = attributes.middleOffset 20 | let contentOffset = collectionView.contentOffset 21 | 22 | attributes.frame = CGRect(x: contentOffset.x + abs(position) * 5, y: contentOffset.y, width: attributes.frame.width, height: attributes.frame.height) 23 | attributes.alpha = 1 - abs(position) 24 | } 25 | } 26 | 27 | struct MovementAnimator: LayoutAttributesAnimator { 28 | var minAlpha: CGFloat 29 | var itemSpacing: CGFloat 30 | var scaleRate: CGFloat 31 | 32 | public init(minAlpha: CGFloat = 0.33, 33 | itemSpacing: CGFloat = 0.4, 34 | scaleRate: CGFloat = 1) { 35 | self.minAlpha = minAlpha 36 | self.itemSpacing = itemSpacing 37 | self.scaleRate = scaleRate 38 | } 39 | 40 | func animate(collectionView: UICollectionView, attributes: AnimatedCollectionViewLayoutAttributes) { 41 | let position = attributes.middleOffset 42 | let scaleFactor = scaleRate 43 | let scaleTransform = CGAffineTransform(scaleX : scaleFactor, y : scaleFactor) 44 | 45 | let translationTransform: CGAffineTransform 46 | 47 | if attributes.scrollDirection == .horizontal { 48 | let width = collectionView.frame.width 49 | let translationX = -(width * itemSpacing * position) 50 | translationTransform = CGAffineTransform(translationX : translationX, y : 0) 51 | } else { 52 | let height = collectionView.frame.height 53 | let translationY = -(height * itemSpacing * position) 54 | translationTransform = CGAffineTransform(translationX : 0, y : translationY) 55 | } 56 | 57 | attributes.alpha = 1.0 - abs(position) + minAlpha 58 | attributes.transform = translationTransform.concatenating(scaleTransform) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Sources/SubViews/TopView/TopViewCells.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TopViewCells.swift 3 | // NavigationToolbar 4 | // 5 | // Created by Artem P. on 22/05/2018. 6 | // Copyright © 2018 Ramotion. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | class TopViewCellOne: UICollectionViewCell { 13 | 14 | var imageView = UIImageView() 15 | var label = Label.topViewCellLabel() 16 | 17 | override init(frame: CGRect) { 18 | super.init(frame: frame) 19 | setup() 20 | } 21 | 22 | required init?(coder aDecoder: NSCoder) { 23 | super.init(coder: aDecoder) 24 | setup() 25 | } 26 | 27 | private func setup() { 28 | backgroundColor = .clear 29 | 30 | imageView.contentMode = .scaleAspectFill 31 | imageView.clipsToBounds = true 32 | 33 | self.addSubview(imageView) 34 | self.addSubview(label) 35 | } 36 | 37 | override func layoutSubviews() { 38 | super.layoutSubviews() 39 | 40 | 41 | label.frame = CGRect(x: 0, 42 | y: Settings.Sizes.yOffset, 43 | width: bounds.width, 44 | height: bounds.height - Settings.Sizes.yOffset) 45 | 46 | imageView.frame = CGRect(x: -Settings.imageCrossOffset, 47 | y: 0, 48 | width: bounds.width + 2 * Settings.imageCrossOffset, 49 | height: bounds.height) 50 | } 51 | 52 | func setData(title: String, image: UIImage) { 53 | label.text = title 54 | imageView.image = image 55 | } 56 | 57 | } 58 | 59 | class TopViewCellTwo: UICollectionViewCell { 60 | 61 | var imageView = UIImageView() 62 | 63 | override init(frame: CGRect) { 64 | super.init(frame: frame) 65 | setup() 66 | } 67 | 68 | required init?(coder aDecoder: NSCoder) { 69 | super.init(coder: aDecoder) 70 | setup() 71 | } 72 | 73 | private func setup() { 74 | imageView.contentMode = .scaleAspectFill 75 | imageView.clipsToBounds = true 76 | 77 | self.addSubview(imageView) 78 | } 79 | 80 | override func layoutSubviews() { 81 | super.layoutSubviews() 82 | 83 | imageView.frame = CGRect(x: -Settings.imageCrossOffset, 84 | y: 0, 85 | width: bounds.width + 2 * Settings.imageCrossOffset, 86 | height: bounds.height) 87 | } 88 | 89 | func setImage(image: UIImage) { 90 | imageView.image = image 91 | } 92 | 93 | } 94 | 95 | class TopViewCellThree: UICollectionViewCell { 96 | 97 | var label = Label.topViewCellLabel() 98 | 99 | override init(frame: CGRect) { 100 | super.init(frame: frame) 101 | setup() 102 | } 103 | 104 | required init?(coder aDecoder: NSCoder) { 105 | super.init(coder: aDecoder) 106 | setup() 107 | } 108 | 109 | private func setup() { 110 | self.addSubview(label) 111 | } 112 | 113 | override func layoutSubviews() { 114 | super.layoutSubviews() 115 | 116 | label.frame = CGRect(x: 0, y: 0, width: bounds.width, height: bounds.height) 117 | } 118 | 119 | func setTitle(title: String) { 120 | label.text = title 121 | } 122 | 123 | } 124 | -------------------------------------------------------------------------------- /Sources/SubViews/TopView/TopViewCollectionLayout.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TopViewCollectionLayout.swift 3 | // NavigationToolbar 4 | // 5 | // Created by Artem P. on 22/05/2018. 6 | // Copyright © 2018 Ramotion. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | class AnimatedCollectionViewLayout: UICollectionViewFlowLayout { 13 | 14 | var animator: LayoutAttributesAnimator? 15 | 16 | override class var layoutAttributesClass: AnyClass { return AnimatedCollectionViewLayoutAttributes.self } 17 | 18 | override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? { 19 | guard let attributes = super.layoutAttributesForElements(in: rect) else { return nil } 20 | return attributes.compactMap { $0.copy() as? AnimatedCollectionViewLayoutAttributes }.map { self.transformLayoutAttributes($0) } 21 | } 22 | 23 | override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool { return true } 24 | 25 | private func transformLayoutAttributes(_ attributes: AnimatedCollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes { 26 | guard let collectionView = self.collectionView else { return attributes } 27 | 28 | let attrs = attributes 29 | 30 | let distance: CGFloat 31 | let itemOffset: CGFloat 32 | 33 | if scrollDirection == .horizontal { 34 | distance = collectionView.frame.width 35 | itemOffset = attrs.center.x - collectionView.contentOffset.x 36 | attrs.startOffset = (attrs.frame.origin.x - collectionView.contentOffset.x) / attrs.frame.width 37 | attrs.endOffset = (attrs.frame.origin.x - collectionView.contentOffset.x - collectionView.frame.width) / attrs.frame.width 38 | } else { 39 | distance = collectionView.frame.height 40 | itemOffset = attrs.center.y - collectionView.contentOffset.y 41 | attrs.startOffset = (attrs.frame.origin.y - collectionView.contentOffset.y) / attrs.frame.height 42 | attrs.endOffset = (attrs.frame.origin.y - collectionView.contentOffset.y - collectionView.frame.height) / attrs.frame.height 43 | } 44 | 45 | attrs.scrollDirection = scrollDirection 46 | attrs.middleOffset = itemOffset / distance - 0.5 47 | 48 | if attrs.contentView == nil, 49 | let c = collectionView.cellForItem(at: attributes.indexPath)?.contentView { 50 | attrs.contentView = c 51 | } 52 | 53 | animator?.animate(collectionView: collectionView, attributes: attrs) 54 | 55 | return attrs 56 | } 57 | 58 | } 59 | 60 | public class AnimatedCollectionViewLayoutAttributes: UICollectionViewLayoutAttributes { 61 | 62 | var contentView: UIView? 63 | var scrollDirection: UICollectionView.ScrollDirection = .vertical 64 | 65 | var startOffset: CGFloat = 0 66 | var middleOffset: CGFloat = 0 67 | var endOffset: CGFloat = 0 68 | 69 | public override func copy(with zone: NSZone? = nil) -> Any { 70 | let copy = super.copy(with: zone) as! AnimatedCollectionViewLayoutAttributes 71 | copy.contentView = contentView 72 | copy.scrollDirection = scrollDirection 73 | copy.startOffset = startOffset 74 | copy.middleOffset = middleOffset 75 | copy.endOffset = endOffset 76 | return copy 77 | } 78 | 79 | public override func isEqual(_ object: Any?) -> Bool { 80 | guard let o = object as? AnimatedCollectionViewLayoutAttributes else { return false } 81 | 82 | return super.isEqual(o) 83 | && o.contentView == contentView 84 | && o.scrollDirection == scrollDirection 85 | && o.startOffset == startOffset 86 | && o.middleOffset == middleOffset 87 | && o.endOffset == endOffset 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/navigation-toolbar/6d917775fb4f72fea8f2706a4bb0ba0db4787332/header.png -------------------------------------------------------------------------------- /iOS-Navigation-Toolbar-1x.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ramotion/navigation-toolbar/6d917775fb4f72fea8f2706a4bb0ba0db4787332/iOS-Navigation-Toolbar-1x.gif --------------------------------------------------------------------------------