├── .gitignore ├── .travis.yml ├── Example ├── FluidTabBarController.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── xcshareddata │ │ └── xcschemes │ │ └── FluidTabBarController-Example.xcscheme ├── FluidTabBarController.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── FluidTabBarController │ ├── AppDelegate.swift │ ├── Base.lproj │ │ └── LaunchScreen.xib │ ├── Images.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── Contents.json │ │ ├── events.imageset │ │ │ ├── Contents.json │ │ │ └── events.pdf │ │ ├── members.imageset │ │ │ ├── Contents.json │ │ │ └── members.pdf │ │ ├── news.imageset │ │ │ ├── Contents.json │ │ │ └── news.pdf │ │ ├── profile.imageset │ │ │ ├── Contents.json │ │ │ └── profile.pdf │ │ └── requests.imageset │ │ │ ├── Contents.json │ │ │ └── requests.pdf │ └── Info.plist ├── Podfile ├── Podfile.lock ├── Pods │ ├── Local Podspecs │ │ └── FluidTabBarController.podspec.json │ ├── Manifest.lock │ ├── Pods.xcodeproj │ │ └── project.pbxproj │ └── Target Support Files │ │ ├── FluidTabBarController │ │ ├── FluidTabBarController-dummy.m │ │ ├── FluidTabBarController-prefix.pch │ │ ├── FluidTabBarController-umbrella.h │ │ ├── FluidTabBarController.modulemap │ │ ├── FluidTabBarController.xcconfig │ │ └── Info.plist │ │ ├── Pods-FluidTabBarController_Example │ │ ├── Info.plist │ │ ├── Pods-FluidTabBarController_Example-acknowledgements.markdown │ │ ├── Pods-FluidTabBarController_Example-acknowledgements.plist │ │ ├── Pods-FluidTabBarController_Example-dummy.m │ │ ├── Pods-FluidTabBarController_Example-frameworks.sh │ │ ├── Pods-FluidTabBarController_Example-resources.sh │ │ ├── Pods-FluidTabBarController_Example-umbrella.h │ │ ├── Pods-FluidTabBarController_Example.debug.xcconfig │ │ ├── Pods-FluidTabBarController_Example.modulemap │ │ └── Pods-FluidTabBarController_Example.release.xcconfig │ │ └── Pods-FluidTabBarController_Tests │ │ ├── Info.plist │ │ ├── Pods-FluidTabBarController_Tests-acknowledgements.markdown │ │ ├── Pods-FluidTabBarController_Tests-acknowledgements.plist │ │ ├── Pods-FluidTabBarController_Tests-dummy.m │ │ ├── Pods-FluidTabBarController_Tests-frameworks.sh │ │ ├── Pods-FluidTabBarController_Tests-resources.sh │ │ ├── Pods-FluidTabBarController_Tests-umbrella.h │ │ ├── Pods-FluidTabBarController_Tests.debug.xcconfig │ │ ├── Pods-FluidTabBarController_Tests.modulemap │ │ └── Pods-FluidTabBarController_Tests.release.xcconfig └── Tests │ ├── Info.plist │ └── Tests.swift ├── FluidTabBarController.podspec ├── FluidTabBarController ├── Animation │ ├── ContainerAnimator.swift │ ├── FluidTabBarItemAnimator.swift │ ├── FluidTabBarItemAnimatorDefault.swift │ ├── IconAnimator.swift │ ├── LabelAnimator.swift │ ├── Layers │ │ ├── CurveLayer.swift │ │ └── StretchyCircleLayer.swift │ └── TimingFunctions.swift ├── FluidTabBar.swift ├── FluidTabBarController.swift ├── FluidTabBarItem.swift ├── FluidTabBarItemContainer.swift ├── FluidTabBarItemContentView.swift └── FluidTabBarMoreItemContentView.swift ├── LICENSE ├── README.md ├── Static ├── example.gif └── tint_color_example.png └── _Pods.xcodeproj /.gitignore: -------------------------------------------------------------------------------- 1 | # OS X 2 | .DS_Store 3 | 4 | # Xcode 5 | build/ 6 | *.pbxuser 7 | !default.pbxuser 8 | *.mode1v3 9 | !default.mode1v3 10 | *.mode2v3 11 | !default.mode2v3 12 | *.perspectivev3 13 | !default.perspectivev3 14 | xcuserdata/ 15 | *.xccheckout 16 | profile 17 | *.moved-aside 18 | DerivedData 19 | *.hmap 20 | *.ipa 21 | 22 | # Bundler 23 | .bundle 24 | 25 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 26 | # Carthage/Checkouts 27 | 28 | Carthage/Build 29 | 30 | # We recommend against adding the Pods directory to your .gitignore. However 31 | # you should judge for yourself, the pros and cons are mentioned at: 32 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 33 | # 34 | # Note: if you ignore the Pods directory, make sure to uncomment 35 | # `pod install` in .travis.yml 36 | # 37 | # Pods/ 38 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # references: 2 | # * https://www.objc.io/issues/6-build-tools/travis-ci/ 3 | # * https://github.com/supermarin/xcpretty#usage 4 | 5 | osx_image: xcode7.3 6 | language: objective-c 7 | # cache: cocoapods 8 | # podfile: Example/Podfile 9 | # before_install: 10 | # - gem install cocoapods # Since Travis is not always on latest version 11 | # - pod install --project-directory=Example 12 | script: 13 | - set -o pipefail && xcodebuild test -enableCodeCoverage YES -workspace Example/FluidTabBarController.xcworkspace -scheme FluidTabBarController-Example -sdk iphonesimulator9.3 ONLY_ACTIVE_ARCH=NO | xcpretty 14 | - pod lib lint 15 | -------------------------------------------------------------------------------- /Example/FluidTabBarController.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 34331F2894CEA5B4577A79D3 /* Pods_FluidTabBarController_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B2E858E515219FD0562920B2 /* Pods_FluidTabBarController_Example.framework */; }; 11 | 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD51AFB9204008FA782 /* AppDelegate.swift */; }; 12 | 607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDC1AFB9204008FA782 /* Images.xcassets */; }; 13 | 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */; }; 14 | 607FACEC1AFB9204008FA782 /* Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACEB1AFB9204008FA782 /* Tests.swift */; }; 15 | AC598638B809333B0A6F7B03 /* Pods_FluidTabBarController_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9ECD2692904F2C0E16F7407F /* Pods_FluidTabBarController_Tests.framework */; }; 16 | /* End PBXBuildFile section */ 17 | 18 | /* Begin PBXContainerItemProxy section */ 19 | 607FACE61AFB9204008FA782 /* PBXContainerItemProxy */ = { 20 | isa = PBXContainerItemProxy; 21 | containerPortal = 607FACC81AFB9204008FA782 /* Project object */; 22 | proxyType = 1; 23 | remoteGlobalIDString = 607FACCF1AFB9204008FA782; 24 | remoteInfo = FluidTabBarController; 25 | }; 26 | /* End PBXContainerItemProxy section */ 27 | 28 | /* Begin PBXFileReference section */ 29 | 0E62B798518D91E72053D78E /* Pods-FluidTabBarController_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FluidTabBarController_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-FluidTabBarController_Example/Pods-FluidTabBarController_Example.release.xcconfig"; sourceTree = ""; }; 30 | 44F30B183E03C6C3117F123F /* FluidTabBarController.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = FluidTabBarController.podspec; path = ../FluidTabBarController.podspec; sourceTree = ""; }; 31 | 607FACD01AFB9204008FA782 /* FluidTabBarController_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FluidTabBarController_Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 32 | 607FACD41AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 33 | 607FACD51AFB9204008FA782 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 34 | 607FACDC1AFB9204008FA782 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 35 | 607FACDF1AFB9204008FA782 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 36 | 607FACE51AFB9204008FA782 /* FluidTabBarController_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = FluidTabBarController_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 37 | 607FACEA1AFB9204008FA782 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 38 | 607FACEB1AFB9204008FA782 /* Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tests.swift; sourceTree = ""; }; 39 | 63450F4FA0E93114746DAB27 /* Pods-FluidTabBarController_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FluidTabBarController_Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-FluidTabBarController_Example/Pods-FluidTabBarController_Example.debug.xcconfig"; sourceTree = ""; }; 40 | 9ECD2692904F2C0E16F7407F /* Pods_FluidTabBarController_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_FluidTabBarController_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 41 | B04B228CB197BE561E6722A2 /* Pods-FluidTabBarController_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FluidTabBarController_Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-FluidTabBarController_Tests/Pods-FluidTabBarController_Tests.debug.xcconfig"; sourceTree = ""; }; 42 | B2E858E515219FD0562920B2 /* Pods_FluidTabBarController_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_FluidTabBarController_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 43 | B561BA7C7626374B563A6662 /* Pods-FluidTabBarController_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FluidTabBarController_Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-FluidTabBarController_Tests/Pods-FluidTabBarController_Tests.release.xcconfig"; sourceTree = ""; }; 44 | C4F08D95D54A32FCCFA781DC /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; }; 45 | FBBF192B28206C7E4DEB7AAF /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; 46 | /* End PBXFileReference section */ 47 | 48 | /* Begin PBXFrameworksBuildPhase section */ 49 | 607FACCD1AFB9204008FA782 /* Frameworks */ = { 50 | isa = PBXFrameworksBuildPhase; 51 | buildActionMask = 2147483647; 52 | files = ( 53 | 34331F2894CEA5B4577A79D3 /* Pods_FluidTabBarController_Example.framework in Frameworks */, 54 | ); 55 | runOnlyForDeploymentPostprocessing = 0; 56 | }; 57 | 607FACE21AFB9204008FA782 /* Frameworks */ = { 58 | isa = PBXFrameworksBuildPhase; 59 | buildActionMask = 2147483647; 60 | files = ( 61 | AC598638B809333B0A6F7B03 /* Pods_FluidTabBarController_Tests.framework in Frameworks */, 62 | ); 63 | runOnlyForDeploymentPostprocessing = 0; 64 | }; 65 | /* End PBXFrameworksBuildPhase section */ 66 | 67 | /* Begin PBXGroup section */ 68 | 607FACC71AFB9204008FA782 = { 69 | isa = PBXGroup; 70 | children = ( 71 | 607FACF51AFB993E008FA782 /* Podspec Metadata */, 72 | 607FACD21AFB9204008FA782 /* Example for FluidTabBarController */, 73 | 607FACE81AFB9204008FA782 /* Tests */, 74 | 607FACD11AFB9204008FA782 /* Products */, 75 | BE17BDAFD67A787C52B63146 /* Pods */, 76 | BEA061AFD451B28F1C1B8E69 /* Frameworks */, 77 | ); 78 | sourceTree = ""; 79 | }; 80 | 607FACD11AFB9204008FA782 /* Products */ = { 81 | isa = PBXGroup; 82 | children = ( 83 | 607FACD01AFB9204008FA782 /* FluidTabBarController_Example.app */, 84 | 607FACE51AFB9204008FA782 /* FluidTabBarController_Tests.xctest */, 85 | ); 86 | name = Products; 87 | sourceTree = ""; 88 | }; 89 | 607FACD21AFB9204008FA782 /* Example for FluidTabBarController */ = { 90 | isa = PBXGroup; 91 | children = ( 92 | 607FACD51AFB9204008FA782 /* AppDelegate.swift */, 93 | 607FACDC1AFB9204008FA782 /* Images.xcassets */, 94 | 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */, 95 | 607FACD31AFB9204008FA782 /* Supporting Files */, 96 | ); 97 | name = "Example for FluidTabBarController"; 98 | path = FluidTabBarController; 99 | sourceTree = ""; 100 | }; 101 | 607FACD31AFB9204008FA782 /* Supporting Files */ = { 102 | isa = PBXGroup; 103 | children = ( 104 | 607FACD41AFB9204008FA782 /* Info.plist */, 105 | ); 106 | name = "Supporting Files"; 107 | sourceTree = ""; 108 | }; 109 | 607FACE81AFB9204008FA782 /* Tests */ = { 110 | isa = PBXGroup; 111 | children = ( 112 | 607FACEB1AFB9204008FA782 /* Tests.swift */, 113 | 607FACE91AFB9204008FA782 /* Supporting Files */, 114 | ); 115 | path = Tests; 116 | sourceTree = ""; 117 | }; 118 | 607FACE91AFB9204008FA782 /* Supporting Files */ = { 119 | isa = PBXGroup; 120 | children = ( 121 | 607FACEA1AFB9204008FA782 /* Info.plist */, 122 | ); 123 | name = "Supporting Files"; 124 | sourceTree = ""; 125 | }; 126 | 607FACF51AFB993E008FA782 /* Podspec Metadata */ = { 127 | isa = PBXGroup; 128 | children = ( 129 | 44F30B183E03C6C3117F123F /* FluidTabBarController.podspec */, 130 | FBBF192B28206C7E4DEB7AAF /* README.md */, 131 | C4F08D95D54A32FCCFA781DC /* LICENSE */, 132 | ); 133 | name = "Podspec Metadata"; 134 | sourceTree = ""; 135 | }; 136 | BE17BDAFD67A787C52B63146 /* Pods */ = { 137 | isa = PBXGroup; 138 | children = ( 139 | 63450F4FA0E93114746DAB27 /* Pods-FluidTabBarController_Example.debug.xcconfig */, 140 | 0E62B798518D91E72053D78E /* Pods-FluidTabBarController_Example.release.xcconfig */, 141 | B04B228CB197BE561E6722A2 /* Pods-FluidTabBarController_Tests.debug.xcconfig */, 142 | B561BA7C7626374B563A6662 /* Pods-FluidTabBarController_Tests.release.xcconfig */, 143 | ); 144 | name = Pods; 145 | sourceTree = ""; 146 | }; 147 | BEA061AFD451B28F1C1B8E69 /* Frameworks */ = { 148 | isa = PBXGroup; 149 | children = ( 150 | B2E858E515219FD0562920B2 /* Pods_FluidTabBarController_Example.framework */, 151 | 9ECD2692904F2C0E16F7407F /* Pods_FluidTabBarController_Tests.framework */, 152 | ); 153 | name = Frameworks; 154 | sourceTree = ""; 155 | }; 156 | /* End PBXGroup section */ 157 | 158 | /* Begin PBXNativeTarget section */ 159 | 607FACCF1AFB9204008FA782 /* FluidTabBarController_Example */ = { 160 | isa = PBXNativeTarget; 161 | buildConfigurationList = 607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "FluidTabBarController_Example" */; 162 | buildPhases = ( 163 | 93C54D7D3EC86F712492E7A5 /* [CP] Check Pods Manifest.lock */, 164 | 607FACCC1AFB9204008FA782 /* Sources */, 165 | 607FACCD1AFB9204008FA782 /* Frameworks */, 166 | 607FACCE1AFB9204008FA782 /* Resources */, 167 | 5510A34EE56DCF8E59CA95DD /* [CP] Embed Pods Frameworks */, 168 | ); 169 | buildRules = ( 170 | ); 171 | dependencies = ( 172 | ); 173 | name = FluidTabBarController_Example; 174 | productName = FluidTabBarController; 175 | productReference = 607FACD01AFB9204008FA782 /* FluidTabBarController_Example.app */; 176 | productType = "com.apple.product-type.application"; 177 | }; 178 | 607FACE41AFB9204008FA782 /* FluidTabBarController_Tests */ = { 179 | isa = PBXNativeTarget; 180 | buildConfigurationList = 607FACF21AFB9204008FA782 /* Build configuration list for PBXNativeTarget "FluidTabBarController_Tests" */; 181 | buildPhases = ( 182 | AEB41FE2FBE5E7405A90BC19 /* [CP] Check Pods Manifest.lock */, 183 | 607FACE11AFB9204008FA782 /* Sources */, 184 | 607FACE21AFB9204008FA782 /* Frameworks */, 185 | 607FACE31AFB9204008FA782 /* Resources */, 186 | ); 187 | buildRules = ( 188 | ); 189 | dependencies = ( 190 | 607FACE71AFB9204008FA782 /* PBXTargetDependency */, 191 | ); 192 | name = FluidTabBarController_Tests; 193 | productName = Tests; 194 | productReference = 607FACE51AFB9204008FA782 /* FluidTabBarController_Tests.xctest */; 195 | productType = "com.apple.product-type.bundle.unit-test"; 196 | }; 197 | /* End PBXNativeTarget section */ 198 | 199 | /* Begin PBXProject section */ 200 | 607FACC81AFB9204008FA782 /* Project object */ = { 201 | isa = PBXProject; 202 | attributes = { 203 | LastSwiftUpdateCheck = 0830; 204 | LastUpgradeCheck = 0830; 205 | ORGANIZATIONNAME = CocoaPods; 206 | TargetAttributes = { 207 | 607FACCF1AFB9204008FA782 = { 208 | CreatedOnToolsVersion = 6.3.1; 209 | DevelopmentTeam = MKQBB98QZG; 210 | LastSwiftMigration = 0900; 211 | ProvisioningStyle = Automatic; 212 | }; 213 | 607FACE41AFB9204008FA782 = { 214 | CreatedOnToolsVersion = 6.3.1; 215 | LastSwiftMigration = 0900; 216 | TestTargetID = 607FACCF1AFB9204008FA782; 217 | }; 218 | }; 219 | }; 220 | buildConfigurationList = 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "FluidTabBarController" */; 221 | compatibilityVersion = "Xcode 3.2"; 222 | developmentRegion = English; 223 | hasScannedForEncodings = 0; 224 | knownRegions = ( 225 | en, 226 | Base, 227 | ); 228 | mainGroup = 607FACC71AFB9204008FA782; 229 | productRefGroup = 607FACD11AFB9204008FA782 /* Products */; 230 | projectDirPath = ""; 231 | projectRoot = ""; 232 | targets = ( 233 | 607FACCF1AFB9204008FA782 /* FluidTabBarController_Example */, 234 | 607FACE41AFB9204008FA782 /* FluidTabBarController_Tests */, 235 | ); 236 | }; 237 | /* End PBXProject section */ 238 | 239 | /* Begin PBXResourcesBuildPhase section */ 240 | 607FACCE1AFB9204008FA782 /* Resources */ = { 241 | isa = PBXResourcesBuildPhase; 242 | buildActionMask = 2147483647; 243 | files = ( 244 | 607FACE01AFB9204008FA782 /* LaunchScreen.xib in Resources */, 245 | 607FACDD1AFB9204008FA782 /* Images.xcassets in Resources */, 246 | ); 247 | runOnlyForDeploymentPostprocessing = 0; 248 | }; 249 | 607FACE31AFB9204008FA782 /* Resources */ = { 250 | isa = PBXResourcesBuildPhase; 251 | buildActionMask = 2147483647; 252 | files = ( 253 | ); 254 | runOnlyForDeploymentPostprocessing = 0; 255 | }; 256 | /* End PBXResourcesBuildPhase section */ 257 | 258 | /* Begin PBXShellScriptBuildPhase section */ 259 | 5510A34EE56DCF8E59CA95DD /* [CP] Embed Pods Frameworks */ = { 260 | isa = PBXShellScriptBuildPhase; 261 | buildActionMask = 2147483647; 262 | files = ( 263 | ); 264 | inputPaths = ( 265 | "${SRCROOT}/Pods/Target Support Files/Pods-FluidTabBarController_Example/Pods-FluidTabBarController_Example-frameworks.sh", 266 | "${BUILT_PRODUCTS_DIR}/FluidTabBarController/FluidTabBarController.framework", 267 | ); 268 | name = "[CP] Embed Pods Frameworks"; 269 | outputPaths = ( 270 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FluidTabBarController.framework", 271 | ); 272 | runOnlyForDeploymentPostprocessing = 0; 273 | shellPath = /bin/sh; 274 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-FluidTabBarController_Example/Pods-FluidTabBarController_Example-frameworks.sh\"\n"; 275 | showEnvVarsInLog = 0; 276 | }; 277 | 93C54D7D3EC86F712492E7A5 /* [CP] Check Pods Manifest.lock */ = { 278 | isa = PBXShellScriptBuildPhase; 279 | buildActionMask = 2147483647; 280 | files = ( 281 | ); 282 | inputPaths = ( 283 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 284 | "${PODS_ROOT}/Manifest.lock", 285 | ); 286 | name = "[CP] Check Pods Manifest.lock"; 287 | outputPaths = ( 288 | "$(DERIVED_FILE_DIR)/Pods-FluidTabBarController_Example-checkManifestLockResult.txt", 289 | ); 290 | runOnlyForDeploymentPostprocessing = 0; 291 | shellPath = /bin/sh; 292 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 293 | showEnvVarsInLog = 0; 294 | }; 295 | AEB41FE2FBE5E7405A90BC19 /* [CP] Check Pods Manifest.lock */ = { 296 | isa = PBXShellScriptBuildPhase; 297 | buildActionMask = 2147483647; 298 | files = ( 299 | ); 300 | inputPaths = ( 301 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 302 | "${PODS_ROOT}/Manifest.lock", 303 | ); 304 | name = "[CP] Check Pods Manifest.lock"; 305 | outputPaths = ( 306 | "$(DERIVED_FILE_DIR)/Pods-FluidTabBarController_Tests-checkManifestLockResult.txt", 307 | ); 308 | runOnlyForDeploymentPostprocessing = 0; 309 | shellPath = /bin/sh; 310 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 311 | showEnvVarsInLog = 0; 312 | }; 313 | /* End PBXShellScriptBuildPhase section */ 314 | 315 | /* Begin PBXSourcesBuildPhase section */ 316 | 607FACCC1AFB9204008FA782 /* Sources */ = { 317 | isa = PBXSourcesBuildPhase; 318 | buildActionMask = 2147483647; 319 | files = ( 320 | 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */, 321 | ); 322 | runOnlyForDeploymentPostprocessing = 0; 323 | }; 324 | 607FACE11AFB9204008FA782 /* Sources */ = { 325 | isa = PBXSourcesBuildPhase; 326 | buildActionMask = 2147483647; 327 | files = ( 328 | 607FACEC1AFB9204008FA782 /* Tests.swift in Sources */, 329 | ); 330 | runOnlyForDeploymentPostprocessing = 0; 331 | }; 332 | /* End PBXSourcesBuildPhase section */ 333 | 334 | /* Begin PBXTargetDependency section */ 335 | 607FACE71AFB9204008FA782 /* PBXTargetDependency */ = { 336 | isa = PBXTargetDependency; 337 | target = 607FACCF1AFB9204008FA782 /* FluidTabBarController_Example */; 338 | targetProxy = 607FACE61AFB9204008FA782 /* PBXContainerItemProxy */; 339 | }; 340 | /* End PBXTargetDependency section */ 341 | 342 | /* Begin PBXVariantGroup section */ 343 | 607FACDE1AFB9204008FA782 /* LaunchScreen.xib */ = { 344 | isa = PBXVariantGroup; 345 | children = ( 346 | 607FACDF1AFB9204008FA782 /* Base */, 347 | ); 348 | name = LaunchScreen.xib; 349 | sourceTree = ""; 350 | }; 351 | /* End PBXVariantGroup section */ 352 | 353 | /* Begin XCBuildConfiguration section */ 354 | 607FACED1AFB9204008FA782 /* Debug */ = { 355 | isa = XCBuildConfiguration; 356 | buildSettings = { 357 | ALWAYS_SEARCH_USER_PATHS = NO; 358 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 359 | CLANG_CXX_LIBRARY = "libc++"; 360 | CLANG_ENABLE_MODULES = YES; 361 | CLANG_ENABLE_OBJC_ARC = YES; 362 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 363 | CLANG_WARN_BOOL_CONVERSION = YES; 364 | CLANG_WARN_COMMA = YES; 365 | CLANG_WARN_CONSTANT_CONVERSION = YES; 366 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 367 | CLANG_WARN_EMPTY_BODY = YES; 368 | CLANG_WARN_ENUM_CONVERSION = YES; 369 | CLANG_WARN_INFINITE_RECURSION = YES; 370 | CLANG_WARN_INT_CONVERSION = YES; 371 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 372 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 373 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 374 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 375 | CLANG_WARN_STRICT_PROTOTYPES = YES; 376 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 377 | CLANG_WARN_UNREACHABLE_CODE = YES; 378 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 379 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 380 | COPY_PHASE_STRIP = NO; 381 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 382 | ENABLE_STRICT_OBJC_MSGSEND = YES; 383 | ENABLE_TESTABILITY = YES; 384 | GCC_C_LANGUAGE_STANDARD = gnu99; 385 | GCC_DYNAMIC_NO_PIC = NO; 386 | GCC_NO_COMMON_BLOCKS = YES; 387 | GCC_OPTIMIZATION_LEVEL = 0; 388 | GCC_PREPROCESSOR_DEFINITIONS = ( 389 | "DEBUG=1", 390 | "$(inherited)", 391 | ); 392 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 393 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 394 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 395 | GCC_WARN_UNDECLARED_SELECTOR = YES; 396 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 397 | GCC_WARN_UNUSED_FUNCTION = YES; 398 | GCC_WARN_UNUSED_VARIABLE = YES; 399 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 400 | MTL_ENABLE_DEBUG_INFO = YES; 401 | ONLY_ACTIVE_ARCH = YES; 402 | SDKROOT = iphoneos; 403 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 404 | }; 405 | name = Debug; 406 | }; 407 | 607FACEE1AFB9204008FA782 /* Release */ = { 408 | isa = XCBuildConfiguration; 409 | buildSettings = { 410 | ALWAYS_SEARCH_USER_PATHS = NO; 411 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 412 | CLANG_CXX_LIBRARY = "libc++"; 413 | CLANG_ENABLE_MODULES = YES; 414 | CLANG_ENABLE_OBJC_ARC = YES; 415 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 416 | CLANG_WARN_BOOL_CONVERSION = YES; 417 | CLANG_WARN_COMMA = YES; 418 | CLANG_WARN_CONSTANT_CONVERSION = YES; 419 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 420 | CLANG_WARN_EMPTY_BODY = YES; 421 | CLANG_WARN_ENUM_CONVERSION = YES; 422 | CLANG_WARN_INFINITE_RECURSION = YES; 423 | CLANG_WARN_INT_CONVERSION = YES; 424 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 425 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 426 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 427 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 428 | CLANG_WARN_STRICT_PROTOTYPES = YES; 429 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 430 | CLANG_WARN_UNREACHABLE_CODE = YES; 431 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 432 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 433 | COPY_PHASE_STRIP = NO; 434 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 435 | ENABLE_NS_ASSERTIONS = NO; 436 | ENABLE_STRICT_OBJC_MSGSEND = YES; 437 | GCC_C_LANGUAGE_STANDARD = gnu99; 438 | GCC_NO_COMMON_BLOCKS = YES; 439 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 440 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 441 | GCC_WARN_UNDECLARED_SELECTOR = YES; 442 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 443 | GCC_WARN_UNUSED_FUNCTION = YES; 444 | GCC_WARN_UNUSED_VARIABLE = YES; 445 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 446 | MTL_ENABLE_DEBUG_INFO = NO; 447 | SDKROOT = iphoneos; 448 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 449 | VALIDATE_PRODUCT = YES; 450 | }; 451 | name = Release; 452 | }; 453 | 607FACF01AFB9204008FA782 /* Debug */ = { 454 | isa = XCBuildConfiguration; 455 | baseConfigurationReference = 63450F4FA0E93114746DAB27 /* Pods-FluidTabBarController_Example.debug.xcconfig */; 456 | buildSettings = { 457 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 458 | CODE_SIGN_IDENTITY = "iPhone Developer"; 459 | CODE_SIGN_STYLE = Automatic; 460 | DEVELOPMENT_TEAM = MKQBB98QZG; 461 | INFOPLIST_FILE = FluidTabBarController/Info.plist; 462 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 463 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 464 | MODULE_NAME = ExampleApp; 465 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)"; 466 | PRODUCT_NAME = "$(TARGET_NAME)"; 467 | PROVISIONING_PROFILE_SPECIFIER = ""; 468 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 469 | SWIFT_VERSION = 4.0; 470 | }; 471 | name = Debug; 472 | }; 473 | 607FACF11AFB9204008FA782 /* Release */ = { 474 | isa = XCBuildConfiguration; 475 | baseConfigurationReference = 0E62B798518D91E72053D78E /* Pods-FluidTabBarController_Example.release.xcconfig */; 476 | buildSettings = { 477 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 478 | CODE_SIGN_IDENTITY = "iPhone Developer"; 479 | CODE_SIGN_STYLE = Automatic; 480 | DEVELOPMENT_TEAM = MKQBB98QZG; 481 | INFOPLIST_FILE = FluidTabBarController/Info.plist; 482 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 483 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 484 | MODULE_NAME = ExampleApp; 485 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)"; 486 | PRODUCT_NAME = "$(TARGET_NAME)"; 487 | PROVISIONING_PROFILE_SPECIFIER = ""; 488 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 489 | SWIFT_VERSION = 4.0; 490 | }; 491 | name = Release; 492 | }; 493 | 607FACF31AFB9204008FA782 /* Debug */ = { 494 | isa = XCBuildConfiguration; 495 | baseConfigurationReference = B04B228CB197BE561E6722A2 /* Pods-FluidTabBarController_Tests.debug.xcconfig */; 496 | buildSettings = { 497 | FRAMEWORK_SEARCH_PATHS = ( 498 | "$(SDKROOT)/Developer/Library/Frameworks", 499 | "$(inherited)", 500 | ); 501 | GCC_PREPROCESSOR_DEFINITIONS = ( 502 | "DEBUG=1", 503 | "$(inherited)", 504 | ); 505 | INFOPLIST_FILE = Tests/Info.plist; 506 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 507 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 508 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)"; 509 | PRODUCT_NAME = "$(TARGET_NAME)"; 510 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 511 | SWIFT_VERSION = 4.0; 512 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/FluidTabBarController_Example.app/FluidTabBarController_Example"; 513 | }; 514 | name = Debug; 515 | }; 516 | 607FACF41AFB9204008FA782 /* Release */ = { 517 | isa = XCBuildConfiguration; 518 | baseConfigurationReference = B561BA7C7626374B563A6662 /* Pods-FluidTabBarController_Tests.release.xcconfig */; 519 | buildSettings = { 520 | FRAMEWORK_SEARCH_PATHS = ( 521 | "$(SDKROOT)/Developer/Library/Frameworks", 522 | "$(inherited)", 523 | ); 524 | INFOPLIST_FILE = Tests/Info.plist; 525 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 526 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 527 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)"; 528 | PRODUCT_NAME = "$(TARGET_NAME)"; 529 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 530 | SWIFT_VERSION = 4.0; 531 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/FluidTabBarController_Example.app/FluidTabBarController_Example"; 532 | }; 533 | name = Release; 534 | }; 535 | /* End XCBuildConfiguration section */ 536 | 537 | /* Begin XCConfigurationList section */ 538 | 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "FluidTabBarController" */ = { 539 | isa = XCConfigurationList; 540 | buildConfigurations = ( 541 | 607FACED1AFB9204008FA782 /* Debug */, 542 | 607FACEE1AFB9204008FA782 /* Release */, 543 | ); 544 | defaultConfigurationIsVisible = 0; 545 | defaultConfigurationName = Release; 546 | }; 547 | 607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "FluidTabBarController_Example" */ = { 548 | isa = XCConfigurationList; 549 | buildConfigurations = ( 550 | 607FACF01AFB9204008FA782 /* Debug */, 551 | 607FACF11AFB9204008FA782 /* Release */, 552 | ); 553 | defaultConfigurationIsVisible = 0; 554 | defaultConfigurationName = Release; 555 | }; 556 | 607FACF21AFB9204008FA782 /* Build configuration list for PBXNativeTarget "FluidTabBarController_Tests" */ = { 557 | isa = XCConfigurationList; 558 | buildConfigurations = ( 559 | 607FACF31AFB9204008FA782 /* Debug */, 560 | 607FACF41AFB9204008FA782 /* Release */, 561 | ); 562 | defaultConfigurationIsVisible = 0; 563 | defaultConfigurationName = Release; 564 | }; 565 | /* End XCConfigurationList section */ 566 | }; 567 | rootObject = 607FACC81AFB9204008FA782 /* Project object */; 568 | } 569 | -------------------------------------------------------------------------------- /Example/FluidTabBarController.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/FluidTabBarController.xcodeproj/xcshareddata/xcschemes/FluidTabBarController-Example.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 45 | 46 | 48 | 54 | 55 | 56 | 57 | 58 | 64 | 65 | 66 | 67 | 68 | 69 | 80 | 82 | 88 | 89 | 90 | 91 | 92 | 93 | 99 | 101 | 107 | 108 | 109 | 110 | 112 | 113 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /Example/FluidTabBarController.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Example/FluidTabBarController.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Example/FluidTabBarController/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // FluidTabBarController 4 | // 5 | // Created by Hubert Kuczyński on 07/23/2018. 6 | // Copyright © 2018 10Clouds Sp. z o.o. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | // 26 | 27 | import UIKit 28 | import FluidTabBarController 29 | 30 | @UIApplicationMain 31 | class AppDelegate: UIResponder, UIApplicationDelegate { 32 | 33 | var window: UIWindow? 34 | 35 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 36 | window = UIWindow(frame: UIScreen.main.bounds) 37 | window?.rootViewController = createTabBarController() 38 | window?.makeKeyAndVisible() 39 | return true 40 | } 41 | 42 | private func createTabBarController() -> UITabBarController { 43 | let tabBarController = FluidTabBarController() 44 | tabBarController.tabBar.tintColor = UIColor(red: 0.2431372549, green: 0.4235294118, blue: 1, alpha: 1) 45 | let viewControllers = [ 46 | ("News", #imageLiteral(resourceName: "news")), 47 | ("Requests", #imageLiteral(resourceName: "requests")), 48 | ("Events", #imageLiteral(resourceName: "events")), 49 | ("Members", #imageLiteral(resourceName: "members")), 50 | ("Account", #imageLiteral(resourceName: "profile")) 51 | ].map(createSampleViewController) 52 | tabBarController.setViewControllers(viewControllers, animated: true) 53 | return tabBarController 54 | } 55 | 56 | private func createSampleViewController(title: String, icon: UIImage) -> UIViewController { 57 | let viewController = UIViewController() 58 | viewController.view.backgroundColor = #colorLiteral(red: 0.9490196078, green: 0.9529411765, blue: 0.968627451, alpha: 1) 59 | let item = FluidTabBarItem(title: title, image: icon, tag: 0) 60 | item.imageColor = #colorLiteral(red: 0.7960784314, green: 0.8078431373, blue: 0.8588235294, alpha: 1) 61 | viewController.tabBarItem = item 62 | return viewController 63 | } 64 | } 65 | 66 | -------------------------------------------------------------------------------- /Example/FluidTabBarController/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 25 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /Example/FluidTabBarController/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ios-marketing", 45 | "size" : "1024x1024", 46 | "scale" : "1x" 47 | } 48 | ], 49 | "info" : { 50 | "version" : 1, 51 | "author" : "xcode" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Example/FluidTabBarController/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Example/FluidTabBarController/Images.xcassets/events.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "events.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Example/FluidTabBarController/Images.xcassets/events.imageset/events.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/10clouds/FluidBottomNavigation-ios/13e62068e8f7b361866c60d45bfd05fd89850d43/Example/FluidTabBarController/Images.xcassets/events.imageset/events.pdf -------------------------------------------------------------------------------- /Example/FluidTabBarController/Images.xcassets/members.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "members.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Example/FluidTabBarController/Images.xcassets/members.imageset/members.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/10clouds/FluidBottomNavigation-ios/13e62068e8f7b361866c60d45bfd05fd89850d43/Example/FluidTabBarController/Images.xcassets/members.imageset/members.pdf -------------------------------------------------------------------------------- /Example/FluidTabBarController/Images.xcassets/news.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "news.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Example/FluidTabBarController/Images.xcassets/news.imageset/news.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/10clouds/FluidBottomNavigation-ios/13e62068e8f7b361866c60d45bfd05fd89850d43/Example/FluidTabBarController/Images.xcassets/news.imageset/news.pdf -------------------------------------------------------------------------------- /Example/FluidTabBarController/Images.xcassets/profile.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "profile.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Example/FluidTabBarController/Images.xcassets/profile.imageset/profile.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/10clouds/FluidBottomNavigation-ios/13e62068e8f7b361866c60d45bfd05fd89850d43/Example/FluidTabBarController/Images.xcassets/profile.imageset/profile.pdf -------------------------------------------------------------------------------- /Example/FluidTabBarController/Images.xcassets/requests.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "requests.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Example/FluidTabBarController/Images.xcassets/requests.imageset/requests.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/10clouds/FluidBottomNavigation-ios/13e62068e8f7b361866c60d45bfd05fd89850d43/Example/FluidTabBarController/Images.xcassets/requests.imageset/requests.pdf -------------------------------------------------------------------------------- /Example/FluidTabBarController/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 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 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /Example/Podfile: -------------------------------------------------------------------------------- 1 | use_frameworks! 2 | 3 | target 'FluidTabBarController_Example' do 4 | pod 'FluidTabBarController', :path => '../' 5 | 6 | target 'FluidTabBarController_Tests' do 7 | inherit! :search_paths 8 | 9 | 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /Example/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - FluidTabBarController (0.5.3) 3 | 4 | DEPENDENCIES: 5 | - FluidTabBarController (from `../`) 6 | 7 | EXTERNAL SOURCES: 8 | FluidTabBarController: 9 | :path: "../" 10 | 11 | SPEC CHECKSUMS: 12 | FluidTabBarController: c8742965327287e15678eab6f89af777744e3f15 13 | 14 | PODFILE CHECKSUM: 33665f8fb2d934c7bdc0fab4d0a4f3392c71609c 15 | 16 | COCOAPODS: 1.5.3 17 | -------------------------------------------------------------------------------- /Example/Pods/Local Podspecs/FluidTabBarController.podspec.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "FluidTabBarController", 3 | "version": "0.5.3", 4 | "summary": "Animated version of UITabBarController", 5 | "description": "Animated version of UITabBarController with fluid-like animation of selecting item", 6 | "homepage": "https://github.com/10clouds/FluidBottomNavigation-ios", 7 | "license": { 8 | "type": "MIT", 9 | "file": "LICENSE" 10 | }, 11 | "authors": { 12 | "Hubert Kuczyński": "hubert.kuczynski@10clouds.com" 13 | }, 14 | "source": { 15 | "git": "https://github.com/10clouds/FluidBottomNavigation-ios.git", 16 | "tag": "0.5.3" 17 | }, 18 | "platforms": { 19 | "ios": "10.0" 20 | }, 21 | "swift_version": "4.0", 22 | "source_files": "FluidTabBarController/**/*" 23 | } 24 | -------------------------------------------------------------------------------- /Example/Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - FluidTabBarController (0.5.3) 3 | 4 | DEPENDENCIES: 5 | - FluidTabBarController (from `../`) 6 | 7 | EXTERNAL SOURCES: 8 | FluidTabBarController: 9 | :path: "../" 10 | 11 | SPEC CHECKSUMS: 12 | FluidTabBarController: c8742965327287e15678eab6f89af777744e3f15 13 | 14 | PODFILE CHECKSUM: 33665f8fb2d934c7bdc0fab4d0a4f3392c71609c 15 | 16 | COCOAPODS: 1.5.3 17 | -------------------------------------------------------------------------------- /Example/Pods/Pods.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 0520AB19E071479BFD028F2FA0D75A4E /* ContainerAnimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5978C9708CA706E4217E6613A241E69F /* ContainerAnimator.swift */; }; 11 | 0B1F0539B7999D6169BF688AC7B54240 /* FluidTabBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDEC12D2E8923A6DD70D5C03AE23CC58 /* FluidTabBarController.swift */; }; 12 | 2D635F1E5A4A1477D802FFC613C58184 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A16F4CFC63FAC439D7A04994F579A03 /* Foundation.framework */; }; 13 | 425AF297CB914EF9E911A2D333B5A45B /* FluidTabBarItemContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = ACDEA08F2D44DC744697D7DAD9C6BC81 /* FluidTabBarItemContainer.swift */; }; 14 | 4766B395686FEA7499F5AE7EB1EFA1B9 /* FluidTabBarItemContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EB5D8424915CE83EE79BE34AB1BE5A2 /* FluidTabBarItemContentView.swift */; }; 15 | 613D24075C4CB1E4ED849340AB4D8576 /* Pods-FluidTabBarController_Example-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 745D436053872E68358596D3ABCAF94A /* Pods-FluidTabBarController_Example-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 16 | 636250104B276B935B77BC4DBB22F5CB /* LabelAnimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1B9183D9D4DDF97A270BE916C15F262 /* LabelAnimator.swift */; }; 17 | 692CE27FD2206558C841B3D8276AC5DE /* FluidTabBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB4696875811A4EC6DA3E7D3C03A505B /* FluidTabBarItem.swift */; }; 18 | 74A7F8814957871E1FFF990A759BD2F2 /* CurveLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F8D86766A77DDF1CFFDB50E0C2191B4 /* CurveLayer.swift */; }; 19 | 7F64864ADE6DC17B5402DB67D8E1D5D4 /* TimingFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E597C67D6B6B6746B1E81EFE90DC3024 /* TimingFunctions.swift */; }; 20 | 8006B5576446A0D56D8C22BDBABDD1BA /* Pods-FluidTabBarController_Tests-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = D39F6DEB29B543C0C576452E1092B277 /* Pods-FluidTabBarController_Tests-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 21 | 89BF3B821F5F7837B18565AB1BF85928 /* FluidTabBarItemAnimatorDefault.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A93D92FAEBA146FD999F188CF62A18B /* FluidTabBarItemAnimatorDefault.swift */; }; 22 | A84759A177B53ABFA8F3AD9E917BE8FF /* Pods-FluidTabBarController_Example-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = A3E5A513BAC50BEE8ECF25277C566FBA /* Pods-FluidTabBarController_Example-dummy.m */; }; 23 | A883DBE23C8208E21A16723199BAD423 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A16F4CFC63FAC439D7A04994F579A03 /* Foundation.framework */; }; 24 | AFBAC65776D99EC64819CE48B1D0C833 /* FluidTabBarController-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 32B2E845BFF1C9ACE7C73E361F3492E8 /* FluidTabBarController-dummy.m */; }; 25 | BA33BD3B687B899B3993769003F520AE /* FluidTabBarController-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 498DBE68E9BB09DDBFA76AB4D196F32E /* FluidTabBarController-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 26 | C98886D5B7DDF1F66FC58FF4493DA594 /* FluidTabBarItemAnimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 496BDCB06CCA719645BF586538CBC3F2 /* FluidTabBarItemAnimator.swift */; }; 27 | D7490A559C127F953C4591AB9FAB2990 /* FluidTabBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC0DC020A93E53CE5184EA00DE7D3B92 /* FluidTabBar.swift */; }; 28 | DACDA9C7CCE63CB8D48C0E1444710198 /* FluidTabBarMoreItemContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B407CCF41583F7F10BE322A7110038E /* FluidTabBarMoreItemContentView.swift */; }; 29 | DFC8478E4DCBE160D96B4D62C31FB26D /* IconAnimator.swift in Sources */ = {isa = PBXBuildFile; fileRef = FF0B8D429785E514EAEB10DAFB2982A1 /* IconAnimator.swift */; }; 30 | E48589489A897E3EAE6C488DD62F6A52 /* StretchyCircleLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AEE5C1134B81A075B6695F7730679EB /* StretchyCircleLayer.swift */; }; 31 | E7AE1E8C0DC51BFDF7DBAC14C33D6467 /* Pods-FluidTabBarController_Tests-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 7EAC612F3C069E7A49A61A35A3D2E65E /* Pods-FluidTabBarController_Tests-dummy.m */; }; 32 | F48398C2DD1EF961858E01FA14454857 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A16F4CFC63FAC439D7A04994F579A03 /* Foundation.framework */; }; 33 | /* End PBXBuildFile section */ 34 | 35 | /* Begin PBXContainerItemProxy section */ 36 | 3C2D4DDD18318441169D6EC43955F5D3 /* PBXContainerItemProxy */ = { 37 | isa = PBXContainerItemProxy; 38 | containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; 39 | proxyType = 1; 40 | remoteGlobalIDString = 96943AA21EE3CC32E63B715D44F90957; 41 | remoteInfo = FluidTabBarController; 42 | }; 43 | A1324DEF938DCCD26DA1464546D3E4E5 /* PBXContainerItemProxy */ = { 44 | isa = PBXContainerItemProxy; 45 | containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; 46 | proxyType = 1; 47 | remoteGlobalIDString = 2A02742A4410537EE3ABE117065CE8A8; 48 | remoteInfo = "Pods-FluidTabBarController_Example"; 49 | }; 50 | /* End PBXContainerItemProxy section */ 51 | 52 | /* Begin PBXFileReference section */ 53 | 0E226E523223118452C5EC0D9CA25A57 /* FluidTabBarController-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FluidTabBarController-prefix.pch"; sourceTree = ""; }; 54 | 0ECAD5A7047F26053BC9FD2AC8984994 /* Pods-FluidTabBarController_Tests-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-FluidTabBarController_Tests-acknowledgements.markdown"; sourceTree = ""; }; 55 | 0F8D86766A77DDF1CFFDB50E0C2191B4 /* CurveLayer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = CurveLayer.swift; sourceTree = ""; }; 56 | 119FBF08464A264BE49A050F1A75FE86 /* Pods-FluidTabBarController_Example-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-FluidTabBarController_Example-acknowledgements.markdown"; sourceTree = ""; }; 57 | 23EC30CF5C00FE768A00B9DA45DA8E84 /* FluidTabBarController.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = FluidTabBarController.xcconfig; sourceTree = ""; }; 58 | 25680C716B10497C3D1C7985E3D872F9 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; path = LICENSE; sourceTree = ""; }; 59 | 2A93D92FAEBA146FD999F188CF62A18B /* FluidTabBarItemAnimatorDefault.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = FluidTabBarItemAnimatorDefault.swift; sourceTree = ""; }; 60 | 3238989CCF4729E455BC6D4F57F583DD /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; path = README.md; sourceTree = ""; }; 61 | 32B2E845BFF1C9ACE7C73E361F3492E8 /* FluidTabBarController-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "FluidTabBarController-dummy.m"; sourceTree = ""; }; 62 | 3AEE5C1134B81A075B6695F7730679EB /* StretchyCircleLayer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StretchyCircleLayer.swift; sourceTree = ""; }; 63 | 454651873D2525924464CF5A3E48F7F1 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 64 | 496BDCB06CCA719645BF586538CBC3F2 /* FluidTabBarItemAnimator.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = FluidTabBarItemAnimator.swift; sourceTree = ""; }; 65 | 498DBE68E9BB09DDBFA76AB4D196F32E /* FluidTabBarController-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "FluidTabBarController-umbrella.h"; sourceTree = ""; }; 66 | 4A73298F292EC288D3238246BC536EE0 /* Pods-FluidTabBarController_Tests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-FluidTabBarController_Tests.modulemap"; sourceTree = ""; }; 67 | 5978C9708CA706E4217E6613A241E69F /* ContainerAnimator.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = ContainerAnimator.swift; sourceTree = ""; }; 68 | 5A16F4CFC63FAC439D7A04994F579A03 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS11.3.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; 69 | 5C6ED937BA200BD65DC30AA805EBD7AD /* FluidTabBarController.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; lastKnownFileType = text; path = FluidTabBarController.podspec; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 70 | 6EE2C5EB2592816E4297A088E84B4202 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 71 | 745D436053872E68358596D3ABCAF94A /* Pods-FluidTabBarController_Example-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-FluidTabBarController_Example-umbrella.h"; sourceTree = ""; }; 72 | 7B3DDB0A6D32177D723489375765CC98 /* Pods-FluidTabBarController_Example.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-FluidTabBarController_Example.modulemap"; sourceTree = ""; }; 73 | 7B407CCF41583F7F10BE322A7110038E /* FluidTabBarMoreItemContentView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = FluidTabBarMoreItemContentView.swift; path = FluidTabBarController/FluidTabBarMoreItemContentView.swift; sourceTree = ""; }; 74 | 7EAC612F3C069E7A49A61A35A3D2E65E /* Pods-FluidTabBarController_Tests-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-FluidTabBarController_Tests-dummy.m"; sourceTree = ""; }; 75 | 7F9C67E5593E3E88EA5B9ED204660720 /* Pods-FluidTabBarController_Tests-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-FluidTabBarController_Tests-resources.sh"; sourceTree = ""; }; 76 | 837052763325C201E31A33FC0DDCA725 /* Pods-FluidTabBarController_Tests-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-FluidTabBarController_Tests-frameworks.sh"; sourceTree = ""; }; 77 | 8E091F81614D27D3387A5D5334D933D7 /* Pods-FluidTabBarController_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-FluidTabBarController_Example.debug.xcconfig"; sourceTree = ""; }; 78 | 8E331568F170C269FA2EBD5CA12F825C /* Pods_FluidTabBarController_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_FluidTabBarController_Tests.framework; path = "Pods-FluidTabBarController_Tests.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; 79 | 920C452635DBEA76C048B3F5A779DA1E /* Pods-FluidTabBarController_Example-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-FluidTabBarController_Example-acknowledgements.plist"; sourceTree = ""; }; 80 | 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 81 | 96226C8997E8C01C0D013AA0AA1CFC01 /* FluidTabBarController.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = FluidTabBarController.modulemap; sourceTree = ""; }; 82 | 9EB5D8424915CE83EE79BE34AB1BE5A2 /* FluidTabBarItemContentView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = FluidTabBarItemContentView.swift; path = FluidTabBarController/FluidTabBarItemContentView.swift; sourceTree = ""; }; 83 | A3E5A513BAC50BEE8ECF25277C566FBA /* Pods-FluidTabBarController_Example-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-FluidTabBarController_Example-dummy.m"; sourceTree = ""; }; 84 | ACDEA08F2D44DC744697D7DAD9C6BC81 /* FluidTabBarItemContainer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = FluidTabBarItemContainer.swift; path = FluidTabBarController/FluidTabBarItemContainer.swift; sourceTree = ""; }; 85 | BAF77020E0C1C0D6376060F1E17E83C3 /* Pods-FluidTabBarController_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-FluidTabBarController_Tests.release.xcconfig"; sourceTree = ""; }; 86 | BB4696875811A4EC6DA3E7D3C03A505B /* FluidTabBarItem.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = FluidTabBarItem.swift; path = FluidTabBarController/FluidTabBarItem.swift; sourceTree = ""; }; 87 | BFE8AEF10475CD8E42F3AD5C408A44FC /* Pods-FluidTabBarController_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-FluidTabBarController_Example.release.xcconfig"; sourceTree = ""; }; 88 | C105199DA1EFFC93E1B9CBC445150B9D /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 89 | CDEC12D2E8923A6DD70D5C03AE23CC58 /* FluidTabBarController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = FluidTabBarController.swift; path = FluidTabBarController/FluidTabBarController.swift; sourceTree = ""; }; 90 | D0CA82B984886177A41906826B549F65 /* Pods-FluidTabBarController_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-FluidTabBarController_Tests.debug.xcconfig"; sourceTree = ""; }; 91 | D39F6DEB29B543C0C576452E1092B277 /* Pods-FluidTabBarController_Tests-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-FluidTabBarController_Tests-umbrella.h"; sourceTree = ""; }; 92 | E597C67D6B6B6746B1E81EFE90DC3024 /* TimingFunctions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = TimingFunctions.swift; sourceTree = ""; }; 93 | EC0DC020A93E53CE5184EA00DE7D3B92 /* FluidTabBar.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = FluidTabBar.swift; path = FluidTabBarController/FluidTabBar.swift; sourceTree = ""; }; 94 | EE59ADB778DE88993D177A1BB7117829 /* Pods-FluidTabBarController_Example-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-FluidTabBarController_Example-frameworks.sh"; sourceTree = ""; }; 95 | EEBE573934CAD9CF73F1050ADFDF2D6D /* Pods_FluidTabBarController_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_FluidTabBarController_Example.framework; path = "Pods-FluidTabBarController_Example.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; 96 | EF0CCD4F1AF8CD7B1AC2232F9EC92B29 /* FluidTabBarController.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = FluidTabBarController.framework; path = FluidTabBarController.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 97 | F1B9183D9D4DDF97A270BE916C15F262 /* LabelAnimator.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = LabelAnimator.swift; sourceTree = ""; }; 98 | F9948198FE5043DF6B34220C9EDA916A /* Pods-FluidTabBarController_Tests-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-FluidTabBarController_Tests-acknowledgements.plist"; sourceTree = ""; }; 99 | FF0B8D429785E514EAEB10DAFB2982A1 /* IconAnimator.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = IconAnimator.swift; sourceTree = ""; }; 100 | FF86D2F62C71DBB5CB5F7B4ED5A1733E /* Pods-FluidTabBarController_Example-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-FluidTabBarController_Example-resources.sh"; sourceTree = ""; }; 101 | /* End PBXFileReference section */ 102 | 103 | /* Begin PBXFrameworksBuildPhase section */ 104 | 263C1E6ADE7D4E5547F513C6C49ADE8E /* Frameworks */ = { 105 | isa = PBXFrameworksBuildPhase; 106 | buildActionMask = 2147483647; 107 | files = ( 108 | A883DBE23C8208E21A16723199BAD423 /* Foundation.framework in Frameworks */, 109 | ); 110 | runOnlyForDeploymentPostprocessing = 0; 111 | }; 112 | 58783EF80F55C821542E29ED6ABD1A78 /* Frameworks */ = { 113 | isa = PBXFrameworksBuildPhase; 114 | buildActionMask = 2147483647; 115 | files = ( 116 | F48398C2DD1EF961858E01FA14454857 /* Foundation.framework in Frameworks */, 117 | ); 118 | runOnlyForDeploymentPostprocessing = 0; 119 | }; 120 | C9DD33D47F1C56602C5F554CA4485E2A /* Frameworks */ = { 121 | isa = PBXFrameworksBuildPhase; 122 | buildActionMask = 2147483647; 123 | files = ( 124 | 2D635F1E5A4A1477D802FFC613C58184 /* Foundation.framework in Frameworks */, 125 | ); 126 | runOnlyForDeploymentPostprocessing = 0; 127 | }; 128 | /* End PBXFrameworksBuildPhase section */ 129 | 130 | /* Begin PBXGroup section */ 131 | 0C787CEFDFAB48AF1A29A502F737B696 /* FluidTabBarController */ = { 132 | isa = PBXGroup; 133 | children = ( 134 | EC0DC020A93E53CE5184EA00DE7D3B92 /* FluidTabBar.swift */, 135 | CDEC12D2E8923A6DD70D5C03AE23CC58 /* FluidTabBarController.swift */, 136 | BB4696875811A4EC6DA3E7D3C03A505B /* FluidTabBarItem.swift */, 137 | ACDEA08F2D44DC744697D7DAD9C6BC81 /* FluidTabBarItemContainer.swift */, 138 | 9EB5D8424915CE83EE79BE34AB1BE5A2 /* FluidTabBarItemContentView.swift */, 139 | 7B407CCF41583F7F10BE322A7110038E /* FluidTabBarMoreItemContentView.swift */, 140 | 8B3BCFD2B2041739970C6786180340CB /* Animation */, 141 | 8DCCF32DBF2DF74AD7305C60BB7ADF75 /* Pod */, 142 | F5255E7922DE4C08E9C057BE7DA03ED7 /* Support Files */, 143 | ); 144 | name = FluidTabBarController; 145 | path = ../..; 146 | sourceTree = ""; 147 | }; 148 | 2ECEA531061859086A66F56CDA3F0E3C /* Layers */ = { 149 | isa = PBXGroup; 150 | children = ( 151 | 0F8D86766A77DDF1CFFDB50E0C2191B4 /* CurveLayer.swift */, 152 | 3AEE5C1134B81A075B6695F7730679EB /* StretchyCircleLayer.swift */, 153 | ); 154 | name = Layers; 155 | path = Layers; 156 | sourceTree = ""; 157 | }; 158 | 34C882E65EFEA612CAEED0CC328658F2 /* Pods-FluidTabBarController_Tests */ = { 159 | isa = PBXGroup; 160 | children = ( 161 | 454651873D2525924464CF5A3E48F7F1 /* Info.plist */, 162 | 4A73298F292EC288D3238246BC536EE0 /* Pods-FluidTabBarController_Tests.modulemap */, 163 | 0ECAD5A7047F26053BC9FD2AC8984994 /* Pods-FluidTabBarController_Tests-acknowledgements.markdown */, 164 | F9948198FE5043DF6B34220C9EDA916A /* Pods-FluidTabBarController_Tests-acknowledgements.plist */, 165 | 7EAC612F3C069E7A49A61A35A3D2E65E /* Pods-FluidTabBarController_Tests-dummy.m */, 166 | 837052763325C201E31A33FC0DDCA725 /* Pods-FluidTabBarController_Tests-frameworks.sh */, 167 | 7F9C67E5593E3E88EA5B9ED204660720 /* Pods-FluidTabBarController_Tests-resources.sh */, 168 | D39F6DEB29B543C0C576452E1092B277 /* Pods-FluidTabBarController_Tests-umbrella.h */, 169 | D0CA82B984886177A41906826B549F65 /* Pods-FluidTabBarController_Tests.debug.xcconfig */, 170 | BAF77020E0C1C0D6376060F1E17E83C3 /* Pods-FluidTabBarController_Tests.release.xcconfig */, 171 | ); 172 | name = "Pods-FluidTabBarController_Tests"; 173 | path = "Target Support Files/Pods-FluidTabBarController_Tests"; 174 | sourceTree = ""; 175 | }; 176 | 5E0D919E635D23B70123790B8308F8EF /* iOS */ = { 177 | isa = PBXGroup; 178 | children = ( 179 | 5A16F4CFC63FAC439D7A04994F579A03 /* Foundation.framework */, 180 | ); 181 | name = iOS; 182 | sourceTree = ""; 183 | }; 184 | 799267640DE800ABD124EEC655277CE7 /* Products */ = { 185 | isa = PBXGroup; 186 | children = ( 187 | EF0CCD4F1AF8CD7B1AC2232F9EC92B29 /* FluidTabBarController.framework */, 188 | EEBE573934CAD9CF73F1050ADFDF2D6D /* Pods_FluidTabBarController_Example.framework */, 189 | 8E331568F170C269FA2EBD5CA12F825C /* Pods_FluidTabBarController_Tests.framework */, 190 | ); 191 | name = Products; 192 | sourceTree = ""; 193 | }; 194 | 7DB346D0F39D3F0E887471402A8071AB = { 195 | isa = PBXGroup; 196 | children = ( 197 | 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */, 198 | E2FC9F6BE0AA7AB09A5D07F57E9A510F /* Development Pods */, 199 | BC3CA7F9E30CC8F7E2DD044DD34432FC /* Frameworks */, 200 | 799267640DE800ABD124EEC655277CE7 /* Products */, 201 | 9CEC472F539BD55EEFAA1F75AC7250C6 /* Targets Support Files */, 202 | ); 203 | sourceTree = ""; 204 | }; 205 | 8B3BCFD2B2041739970C6786180340CB /* Animation */ = { 206 | isa = PBXGroup; 207 | children = ( 208 | 5978C9708CA706E4217E6613A241E69F /* ContainerAnimator.swift */, 209 | 496BDCB06CCA719645BF586538CBC3F2 /* FluidTabBarItemAnimator.swift */, 210 | 2A93D92FAEBA146FD999F188CF62A18B /* FluidTabBarItemAnimatorDefault.swift */, 211 | FF0B8D429785E514EAEB10DAFB2982A1 /* IconAnimator.swift */, 212 | F1B9183D9D4DDF97A270BE916C15F262 /* LabelAnimator.swift */, 213 | E597C67D6B6B6746B1E81EFE90DC3024 /* TimingFunctions.swift */, 214 | 2ECEA531061859086A66F56CDA3F0E3C /* Layers */, 215 | ); 216 | name = Animation; 217 | path = FluidTabBarController/Animation; 218 | sourceTree = ""; 219 | }; 220 | 8DCCF32DBF2DF74AD7305C60BB7ADF75 /* Pod */ = { 221 | isa = PBXGroup; 222 | children = ( 223 | 5C6ED937BA200BD65DC30AA805EBD7AD /* FluidTabBarController.podspec */, 224 | 25680C716B10497C3D1C7985E3D872F9 /* LICENSE */, 225 | 3238989CCF4729E455BC6D4F57F583DD /* README.md */, 226 | ); 227 | name = Pod; 228 | sourceTree = ""; 229 | }; 230 | 9CEC472F539BD55EEFAA1F75AC7250C6 /* Targets Support Files */ = { 231 | isa = PBXGroup; 232 | children = ( 233 | CAB834D63970BAD4734028174642C90C /* Pods-FluidTabBarController_Example */, 234 | 34C882E65EFEA612CAEED0CC328658F2 /* Pods-FluidTabBarController_Tests */, 235 | ); 236 | name = "Targets Support Files"; 237 | sourceTree = ""; 238 | }; 239 | BC3CA7F9E30CC8F7E2DD044DD34432FC /* Frameworks */ = { 240 | isa = PBXGroup; 241 | children = ( 242 | 5E0D919E635D23B70123790B8308F8EF /* iOS */, 243 | ); 244 | name = Frameworks; 245 | sourceTree = ""; 246 | }; 247 | CAB834D63970BAD4734028174642C90C /* Pods-FluidTabBarController_Example */ = { 248 | isa = PBXGroup; 249 | children = ( 250 | C105199DA1EFFC93E1B9CBC445150B9D /* Info.plist */, 251 | 7B3DDB0A6D32177D723489375765CC98 /* Pods-FluidTabBarController_Example.modulemap */, 252 | 119FBF08464A264BE49A050F1A75FE86 /* Pods-FluidTabBarController_Example-acknowledgements.markdown */, 253 | 920C452635DBEA76C048B3F5A779DA1E /* Pods-FluidTabBarController_Example-acknowledgements.plist */, 254 | A3E5A513BAC50BEE8ECF25277C566FBA /* Pods-FluidTabBarController_Example-dummy.m */, 255 | EE59ADB778DE88993D177A1BB7117829 /* Pods-FluidTabBarController_Example-frameworks.sh */, 256 | FF86D2F62C71DBB5CB5F7B4ED5A1733E /* Pods-FluidTabBarController_Example-resources.sh */, 257 | 745D436053872E68358596D3ABCAF94A /* Pods-FluidTabBarController_Example-umbrella.h */, 258 | 8E091F81614D27D3387A5D5334D933D7 /* Pods-FluidTabBarController_Example.debug.xcconfig */, 259 | BFE8AEF10475CD8E42F3AD5C408A44FC /* Pods-FluidTabBarController_Example.release.xcconfig */, 260 | ); 261 | name = "Pods-FluidTabBarController_Example"; 262 | path = "Target Support Files/Pods-FluidTabBarController_Example"; 263 | sourceTree = ""; 264 | }; 265 | E2FC9F6BE0AA7AB09A5D07F57E9A510F /* Development Pods */ = { 266 | isa = PBXGroup; 267 | children = ( 268 | 0C787CEFDFAB48AF1A29A502F737B696 /* FluidTabBarController */, 269 | ); 270 | name = "Development Pods"; 271 | sourceTree = ""; 272 | }; 273 | F5255E7922DE4C08E9C057BE7DA03ED7 /* Support Files */ = { 274 | isa = PBXGroup; 275 | children = ( 276 | 96226C8997E8C01C0D013AA0AA1CFC01 /* FluidTabBarController.modulemap */, 277 | 23EC30CF5C00FE768A00B9DA45DA8E84 /* FluidTabBarController.xcconfig */, 278 | 32B2E845BFF1C9ACE7C73E361F3492E8 /* FluidTabBarController-dummy.m */, 279 | 0E226E523223118452C5EC0D9CA25A57 /* FluidTabBarController-prefix.pch */, 280 | 498DBE68E9BB09DDBFA76AB4D196F32E /* FluidTabBarController-umbrella.h */, 281 | 6EE2C5EB2592816E4297A088E84B4202 /* Info.plist */, 282 | ); 283 | name = "Support Files"; 284 | path = "Example/Pods/Target Support Files/FluidTabBarController"; 285 | sourceTree = ""; 286 | }; 287 | /* End PBXGroup section */ 288 | 289 | /* Begin PBXHeadersBuildPhase section */ 290 | 053C63A24E4A3A87A866F994A7B4213E /* Headers */ = { 291 | isa = PBXHeadersBuildPhase; 292 | buildActionMask = 2147483647; 293 | files = ( 294 | 8006B5576446A0D56D8C22BDBABDD1BA /* Pods-FluidTabBarController_Tests-umbrella.h in Headers */, 295 | ); 296 | runOnlyForDeploymentPostprocessing = 0; 297 | }; 298 | 273C65499CFA54469ABFA7594A63D01A /* Headers */ = { 299 | isa = PBXHeadersBuildPhase; 300 | buildActionMask = 2147483647; 301 | files = ( 302 | BA33BD3B687B899B3993769003F520AE /* FluidTabBarController-umbrella.h in Headers */, 303 | ); 304 | runOnlyForDeploymentPostprocessing = 0; 305 | }; 306 | B8EAAD423E007BB0D0335B791B1F97FC /* Headers */ = { 307 | isa = PBXHeadersBuildPhase; 308 | buildActionMask = 2147483647; 309 | files = ( 310 | 613D24075C4CB1E4ED849340AB4D8576 /* Pods-FluidTabBarController_Example-umbrella.h in Headers */, 311 | ); 312 | runOnlyForDeploymentPostprocessing = 0; 313 | }; 314 | /* End PBXHeadersBuildPhase section */ 315 | 316 | /* Begin PBXNativeTarget section */ 317 | 2A02742A4410537EE3ABE117065CE8A8 /* Pods-FluidTabBarController_Example */ = { 318 | isa = PBXNativeTarget; 319 | buildConfigurationList = 7A220494BBBF86A6EB09A4A7CC1BA2CF /* Build configuration list for PBXNativeTarget "Pods-FluidTabBarController_Example" */; 320 | buildPhases = ( 321 | 4A053434CD02D40F32B4DAD8CB56A734 /* Sources */, 322 | 58783EF80F55C821542E29ED6ABD1A78 /* Frameworks */, 323 | B8EAAD423E007BB0D0335B791B1F97FC /* Headers */, 324 | ); 325 | buildRules = ( 326 | ); 327 | dependencies = ( 328 | D9C7E75CA6FABD91274017FE1F8ABFF1 /* PBXTargetDependency */, 329 | ); 330 | name = "Pods-FluidTabBarController_Example"; 331 | productName = "Pods-FluidTabBarController_Example"; 332 | productReference = EEBE573934CAD9CF73F1050ADFDF2D6D /* Pods_FluidTabBarController_Example.framework */; 333 | productType = "com.apple.product-type.framework"; 334 | }; 335 | 4A0878EDF364FE77F4DC8A9A693B3838 /* Pods-FluidTabBarController_Tests */ = { 336 | isa = PBXNativeTarget; 337 | buildConfigurationList = A63413E5A63C15D2081A1613195E4A68 /* Build configuration list for PBXNativeTarget "Pods-FluidTabBarController_Tests" */; 338 | buildPhases = ( 339 | 7C398D33012EAE621198A1722C4ED032 /* Sources */, 340 | 263C1E6ADE7D4E5547F513C6C49ADE8E /* Frameworks */, 341 | 053C63A24E4A3A87A866F994A7B4213E /* Headers */, 342 | ); 343 | buildRules = ( 344 | ); 345 | dependencies = ( 346 | 3E1282BCDB34DC220957A1D0411D454C /* PBXTargetDependency */, 347 | ); 348 | name = "Pods-FluidTabBarController_Tests"; 349 | productName = "Pods-FluidTabBarController_Tests"; 350 | productReference = 8E331568F170C269FA2EBD5CA12F825C /* Pods_FluidTabBarController_Tests.framework */; 351 | productType = "com.apple.product-type.framework"; 352 | }; 353 | 96943AA21EE3CC32E63B715D44F90957 /* FluidTabBarController */ = { 354 | isa = PBXNativeTarget; 355 | buildConfigurationList = 208B3B57BDE9F6F8548326F21BEBED88 /* Build configuration list for PBXNativeTarget "FluidTabBarController" */; 356 | buildPhases = ( 357 | 9E2A0CBB5102BA31463B443960943C69 /* Sources */, 358 | C9DD33D47F1C56602C5F554CA4485E2A /* Frameworks */, 359 | 273C65499CFA54469ABFA7594A63D01A /* Headers */, 360 | ); 361 | buildRules = ( 362 | ); 363 | dependencies = ( 364 | ); 365 | name = FluidTabBarController; 366 | productName = FluidTabBarController; 367 | productReference = EF0CCD4F1AF8CD7B1AC2232F9EC92B29 /* FluidTabBarController.framework */; 368 | productType = "com.apple.product-type.framework"; 369 | }; 370 | /* End PBXNativeTarget section */ 371 | 372 | /* Begin PBXProject section */ 373 | D41D8CD98F00B204E9800998ECF8427E /* Project object */ = { 374 | isa = PBXProject; 375 | attributes = { 376 | LastSwiftUpdateCheck = 0930; 377 | LastUpgradeCheck = 0930; 378 | }; 379 | buildConfigurationList = 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */; 380 | compatibilityVersion = "Xcode 3.2"; 381 | developmentRegion = English; 382 | hasScannedForEncodings = 0; 383 | knownRegions = ( 384 | en, 385 | ); 386 | mainGroup = 7DB346D0F39D3F0E887471402A8071AB; 387 | productRefGroup = 799267640DE800ABD124EEC655277CE7 /* Products */; 388 | projectDirPath = ""; 389 | projectRoot = ""; 390 | targets = ( 391 | 96943AA21EE3CC32E63B715D44F90957 /* FluidTabBarController */, 392 | 2A02742A4410537EE3ABE117065CE8A8 /* Pods-FluidTabBarController_Example */, 393 | 4A0878EDF364FE77F4DC8A9A693B3838 /* Pods-FluidTabBarController_Tests */, 394 | ); 395 | }; 396 | /* End PBXProject section */ 397 | 398 | /* Begin PBXSourcesBuildPhase section */ 399 | 4A053434CD02D40F32B4DAD8CB56A734 /* Sources */ = { 400 | isa = PBXSourcesBuildPhase; 401 | buildActionMask = 2147483647; 402 | files = ( 403 | A84759A177B53ABFA8F3AD9E917BE8FF /* Pods-FluidTabBarController_Example-dummy.m in Sources */, 404 | ); 405 | runOnlyForDeploymentPostprocessing = 0; 406 | }; 407 | 7C398D33012EAE621198A1722C4ED032 /* Sources */ = { 408 | isa = PBXSourcesBuildPhase; 409 | buildActionMask = 2147483647; 410 | files = ( 411 | E7AE1E8C0DC51BFDF7DBAC14C33D6467 /* Pods-FluidTabBarController_Tests-dummy.m in Sources */, 412 | ); 413 | runOnlyForDeploymentPostprocessing = 0; 414 | }; 415 | 9E2A0CBB5102BA31463B443960943C69 /* Sources */ = { 416 | isa = PBXSourcesBuildPhase; 417 | buildActionMask = 2147483647; 418 | files = ( 419 | 0520AB19E071479BFD028F2FA0D75A4E /* ContainerAnimator.swift in Sources */, 420 | 74A7F8814957871E1FFF990A759BD2F2 /* CurveLayer.swift in Sources */, 421 | D7490A559C127F953C4591AB9FAB2990 /* FluidTabBar.swift in Sources */, 422 | AFBAC65776D99EC64819CE48B1D0C833 /* FluidTabBarController-dummy.m in Sources */, 423 | 0B1F0539B7999D6169BF688AC7B54240 /* FluidTabBarController.swift in Sources */, 424 | 692CE27FD2206558C841B3D8276AC5DE /* FluidTabBarItem.swift in Sources */, 425 | C98886D5B7DDF1F66FC58FF4493DA594 /* FluidTabBarItemAnimator.swift in Sources */, 426 | 89BF3B821F5F7837B18565AB1BF85928 /* FluidTabBarItemAnimatorDefault.swift in Sources */, 427 | 425AF297CB914EF9E911A2D333B5A45B /* FluidTabBarItemContainer.swift in Sources */, 428 | 4766B395686FEA7499F5AE7EB1EFA1B9 /* FluidTabBarItemContentView.swift in Sources */, 429 | DACDA9C7CCE63CB8D48C0E1444710198 /* FluidTabBarMoreItemContentView.swift in Sources */, 430 | DFC8478E4DCBE160D96B4D62C31FB26D /* IconAnimator.swift in Sources */, 431 | 636250104B276B935B77BC4DBB22F5CB /* LabelAnimator.swift in Sources */, 432 | E48589489A897E3EAE6C488DD62F6A52 /* StretchyCircleLayer.swift in Sources */, 433 | 7F64864ADE6DC17B5402DB67D8E1D5D4 /* TimingFunctions.swift in Sources */, 434 | ); 435 | runOnlyForDeploymentPostprocessing = 0; 436 | }; 437 | /* End PBXSourcesBuildPhase section */ 438 | 439 | /* Begin PBXTargetDependency section */ 440 | 3E1282BCDB34DC220957A1D0411D454C /* PBXTargetDependency */ = { 441 | isa = PBXTargetDependency; 442 | name = "Pods-FluidTabBarController_Example"; 443 | target = 2A02742A4410537EE3ABE117065CE8A8 /* Pods-FluidTabBarController_Example */; 444 | targetProxy = A1324DEF938DCCD26DA1464546D3E4E5 /* PBXContainerItemProxy */; 445 | }; 446 | D9C7E75CA6FABD91274017FE1F8ABFF1 /* PBXTargetDependency */ = { 447 | isa = PBXTargetDependency; 448 | name = FluidTabBarController; 449 | target = 96943AA21EE3CC32E63B715D44F90957 /* FluidTabBarController */; 450 | targetProxy = 3C2D4DDD18318441169D6EC43955F5D3 /* PBXContainerItemProxy */; 451 | }; 452 | /* End PBXTargetDependency section */ 453 | 454 | /* Begin XCBuildConfiguration section */ 455 | 081113F1788D5D43C83B93FFF28F4F8E /* Release */ = { 456 | isa = XCBuildConfiguration; 457 | baseConfigurationReference = BFE8AEF10475CD8E42F3AD5C408A44FC /* Pods-FluidTabBarController_Example.release.xcconfig */; 458 | buildSettings = { 459 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; 460 | CLANG_ENABLE_OBJC_WEAK = NO; 461 | CODE_SIGN_IDENTITY = ""; 462 | "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; 463 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 464 | "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; 465 | CURRENT_PROJECT_VERSION = 1; 466 | DEFINES_MODULE = YES; 467 | DYLIB_COMPATIBILITY_VERSION = 1; 468 | DYLIB_CURRENT_VERSION = 1; 469 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 470 | INFOPLIST_FILE = "Target Support Files/Pods-FluidTabBarController_Example/Info.plist"; 471 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 472 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 473 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 474 | MACH_O_TYPE = staticlib; 475 | MODULEMAP_FILE = "Target Support Files/Pods-FluidTabBarController_Example/Pods-FluidTabBarController_Example.modulemap"; 476 | OTHER_LDFLAGS = ""; 477 | OTHER_LIBTOOLFLAGS = ""; 478 | PODS_ROOT = "$(SRCROOT)"; 479 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; 480 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 481 | SDKROOT = iphoneos; 482 | SKIP_INSTALL = YES; 483 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 484 | TARGETED_DEVICE_FAMILY = "1,2"; 485 | VALIDATE_PRODUCT = YES; 486 | VERSIONING_SYSTEM = "apple-generic"; 487 | VERSION_INFO_PREFIX = ""; 488 | }; 489 | name = Release; 490 | }; 491 | 19420BF9FEFB05F3F4E3ADFEB09CBC06 /* Debug */ = { 492 | isa = XCBuildConfiguration; 493 | baseConfigurationReference = 23EC30CF5C00FE768A00B9DA45DA8E84 /* FluidTabBarController.xcconfig */; 494 | buildSettings = { 495 | CLANG_ENABLE_OBJC_WEAK = NO; 496 | CODE_SIGN_IDENTITY = ""; 497 | "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; 498 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 499 | "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; 500 | CURRENT_PROJECT_VERSION = 1; 501 | DEFINES_MODULE = YES; 502 | DYLIB_COMPATIBILITY_VERSION = 1; 503 | DYLIB_CURRENT_VERSION = 1; 504 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 505 | GCC_PREFIX_HEADER = "Target Support Files/FluidTabBarController/FluidTabBarController-prefix.pch"; 506 | INFOPLIST_FILE = "Target Support Files/FluidTabBarController/Info.plist"; 507 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 508 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 509 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 510 | MODULEMAP_FILE = "Target Support Files/FluidTabBarController/FluidTabBarController.modulemap"; 511 | PRODUCT_MODULE_NAME = FluidTabBarController; 512 | PRODUCT_NAME = FluidTabBarController; 513 | SDKROOT = iphoneos; 514 | SKIP_INSTALL = YES; 515 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; 516 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 517 | SWIFT_VERSION = 4.0; 518 | TARGETED_DEVICE_FAMILY = "1,2"; 519 | VERSIONING_SYSTEM = "apple-generic"; 520 | VERSION_INFO_PREFIX = ""; 521 | }; 522 | name = Debug; 523 | }; 524 | 2772B8C9EFDC40AD8A074AE40CB903C3 /* Release */ = { 525 | isa = XCBuildConfiguration; 526 | baseConfigurationReference = 23EC30CF5C00FE768A00B9DA45DA8E84 /* FluidTabBarController.xcconfig */; 527 | buildSettings = { 528 | CLANG_ENABLE_OBJC_WEAK = NO; 529 | CODE_SIGN_IDENTITY = ""; 530 | "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; 531 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 532 | "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; 533 | CURRENT_PROJECT_VERSION = 1; 534 | DEFINES_MODULE = YES; 535 | DYLIB_COMPATIBILITY_VERSION = 1; 536 | DYLIB_CURRENT_VERSION = 1; 537 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 538 | GCC_PREFIX_HEADER = "Target Support Files/FluidTabBarController/FluidTabBarController-prefix.pch"; 539 | INFOPLIST_FILE = "Target Support Files/FluidTabBarController/Info.plist"; 540 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 541 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 542 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 543 | MODULEMAP_FILE = "Target Support Files/FluidTabBarController/FluidTabBarController.modulemap"; 544 | PRODUCT_MODULE_NAME = FluidTabBarController; 545 | PRODUCT_NAME = FluidTabBarController; 546 | SDKROOT = iphoneos; 547 | SKIP_INSTALL = YES; 548 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; 549 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 550 | SWIFT_VERSION = 4.0; 551 | TARGETED_DEVICE_FAMILY = "1,2"; 552 | VALIDATE_PRODUCT = YES; 553 | VERSIONING_SYSTEM = "apple-generic"; 554 | VERSION_INFO_PREFIX = ""; 555 | }; 556 | name = Release; 557 | }; 558 | 3D523DF606590281EAAAB8C035E25492 /* Release */ = { 559 | isa = XCBuildConfiguration; 560 | baseConfigurationReference = BAF77020E0C1C0D6376060F1E17E83C3 /* Pods-FluidTabBarController_Tests.release.xcconfig */; 561 | buildSettings = { 562 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; 563 | CLANG_ENABLE_OBJC_WEAK = NO; 564 | CODE_SIGN_IDENTITY = ""; 565 | "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; 566 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 567 | "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; 568 | CURRENT_PROJECT_VERSION = 1; 569 | DEFINES_MODULE = YES; 570 | DYLIB_COMPATIBILITY_VERSION = 1; 571 | DYLIB_CURRENT_VERSION = 1; 572 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 573 | INFOPLIST_FILE = "Target Support Files/Pods-FluidTabBarController_Tests/Info.plist"; 574 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 575 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 576 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 577 | MACH_O_TYPE = staticlib; 578 | MODULEMAP_FILE = "Target Support Files/Pods-FluidTabBarController_Tests/Pods-FluidTabBarController_Tests.modulemap"; 579 | OTHER_LDFLAGS = ""; 580 | OTHER_LIBTOOLFLAGS = ""; 581 | PODS_ROOT = "$(SRCROOT)"; 582 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; 583 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 584 | SDKROOT = iphoneos; 585 | SKIP_INSTALL = YES; 586 | TARGETED_DEVICE_FAMILY = "1,2"; 587 | VALIDATE_PRODUCT = YES; 588 | VERSIONING_SYSTEM = "apple-generic"; 589 | VERSION_INFO_PREFIX = ""; 590 | }; 591 | name = Release; 592 | }; 593 | 553022A828EE1991F07D2D73F565AEF8 /* Debug */ = { 594 | isa = XCBuildConfiguration; 595 | buildSettings = { 596 | ALWAYS_SEARCH_USER_PATHS = NO; 597 | CLANG_ANALYZER_NONNULL = YES; 598 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 599 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 600 | CLANG_CXX_LIBRARY = "libc++"; 601 | CLANG_ENABLE_MODULES = YES; 602 | CLANG_ENABLE_OBJC_ARC = YES; 603 | CLANG_ENABLE_OBJC_WEAK = YES; 604 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 605 | CLANG_WARN_BOOL_CONVERSION = YES; 606 | CLANG_WARN_COMMA = YES; 607 | CLANG_WARN_CONSTANT_CONVERSION = YES; 608 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 609 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 610 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 611 | CLANG_WARN_EMPTY_BODY = YES; 612 | CLANG_WARN_ENUM_CONVERSION = YES; 613 | CLANG_WARN_INFINITE_RECURSION = YES; 614 | CLANG_WARN_INT_CONVERSION = YES; 615 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 616 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 617 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 618 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 619 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 620 | CLANG_WARN_STRICT_PROTOTYPES = YES; 621 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 622 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 623 | CLANG_WARN_UNREACHABLE_CODE = YES; 624 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 625 | CODE_SIGNING_ALLOWED = NO; 626 | CODE_SIGNING_REQUIRED = NO; 627 | COPY_PHASE_STRIP = NO; 628 | DEBUG_INFORMATION_FORMAT = dwarf; 629 | ENABLE_STRICT_OBJC_MSGSEND = YES; 630 | ENABLE_TESTABILITY = YES; 631 | GCC_C_LANGUAGE_STANDARD = gnu11; 632 | GCC_DYNAMIC_NO_PIC = NO; 633 | GCC_NO_COMMON_BLOCKS = YES; 634 | GCC_OPTIMIZATION_LEVEL = 0; 635 | GCC_PREPROCESSOR_DEFINITIONS = ( 636 | "POD_CONFIGURATION_DEBUG=1", 637 | "DEBUG=1", 638 | "$(inherited)", 639 | ); 640 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 641 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 642 | GCC_WARN_UNDECLARED_SELECTOR = YES; 643 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 644 | GCC_WARN_UNUSED_FUNCTION = YES; 645 | GCC_WARN_UNUSED_VARIABLE = YES; 646 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 647 | MTL_ENABLE_DEBUG_INFO = YES; 648 | ONLY_ACTIVE_ARCH = YES; 649 | PRODUCT_NAME = "$(TARGET_NAME)"; 650 | STRIP_INSTALLED_PRODUCT = NO; 651 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 652 | SYMROOT = "${SRCROOT}/../build"; 653 | }; 654 | name = Debug; 655 | }; 656 | 58CE816B060A41D32CEC095441D0E3E0 /* Release */ = { 657 | isa = XCBuildConfiguration; 658 | buildSettings = { 659 | ALWAYS_SEARCH_USER_PATHS = NO; 660 | CLANG_ANALYZER_NONNULL = YES; 661 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 662 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 663 | CLANG_CXX_LIBRARY = "libc++"; 664 | CLANG_ENABLE_MODULES = YES; 665 | CLANG_ENABLE_OBJC_ARC = YES; 666 | CLANG_ENABLE_OBJC_WEAK = YES; 667 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 668 | CLANG_WARN_BOOL_CONVERSION = YES; 669 | CLANG_WARN_COMMA = YES; 670 | CLANG_WARN_CONSTANT_CONVERSION = YES; 671 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 672 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 673 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 674 | CLANG_WARN_EMPTY_BODY = YES; 675 | CLANG_WARN_ENUM_CONVERSION = YES; 676 | CLANG_WARN_INFINITE_RECURSION = YES; 677 | CLANG_WARN_INT_CONVERSION = YES; 678 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 679 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 680 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 681 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 682 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 683 | CLANG_WARN_STRICT_PROTOTYPES = YES; 684 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 685 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 686 | CLANG_WARN_UNREACHABLE_CODE = YES; 687 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 688 | CODE_SIGNING_ALLOWED = NO; 689 | CODE_SIGNING_REQUIRED = NO; 690 | COPY_PHASE_STRIP = NO; 691 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 692 | ENABLE_NS_ASSERTIONS = NO; 693 | ENABLE_STRICT_OBJC_MSGSEND = YES; 694 | GCC_C_LANGUAGE_STANDARD = gnu11; 695 | GCC_NO_COMMON_BLOCKS = YES; 696 | GCC_PREPROCESSOR_DEFINITIONS = ( 697 | "POD_CONFIGURATION_RELEASE=1", 698 | "$(inherited)", 699 | ); 700 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 701 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 702 | GCC_WARN_UNDECLARED_SELECTOR = YES; 703 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 704 | GCC_WARN_UNUSED_FUNCTION = YES; 705 | GCC_WARN_UNUSED_VARIABLE = YES; 706 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 707 | MTL_ENABLE_DEBUG_INFO = NO; 708 | PRODUCT_NAME = "$(TARGET_NAME)"; 709 | STRIP_INSTALLED_PRODUCT = NO; 710 | SYMROOT = "${SRCROOT}/../build"; 711 | }; 712 | name = Release; 713 | }; 714 | A403E38CC53DEEB849CB23D0BCF38892 /* Debug */ = { 715 | isa = XCBuildConfiguration; 716 | baseConfigurationReference = D0CA82B984886177A41906826B549F65 /* Pods-FluidTabBarController_Tests.debug.xcconfig */; 717 | buildSettings = { 718 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; 719 | CLANG_ENABLE_OBJC_WEAK = NO; 720 | CODE_SIGN_IDENTITY = ""; 721 | "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; 722 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 723 | "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; 724 | CURRENT_PROJECT_VERSION = 1; 725 | DEFINES_MODULE = YES; 726 | DYLIB_COMPATIBILITY_VERSION = 1; 727 | DYLIB_CURRENT_VERSION = 1; 728 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 729 | INFOPLIST_FILE = "Target Support Files/Pods-FluidTabBarController_Tests/Info.plist"; 730 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 731 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 732 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 733 | MACH_O_TYPE = staticlib; 734 | MODULEMAP_FILE = "Target Support Files/Pods-FluidTabBarController_Tests/Pods-FluidTabBarController_Tests.modulemap"; 735 | OTHER_LDFLAGS = ""; 736 | OTHER_LIBTOOLFLAGS = ""; 737 | PODS_ROOT = "$(SRCROOT)"; 738 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; 739 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 740 | SDKROOT = iphoneos; 741 | SKIP_INSTALL = YES; 742 | TARGETED_DEVICE_FAMILY = "1,2"; 743 | VERSIONING_SYSTEM = "apple-generic"; 744 | VERSION_INFO_PREFIX = ""; 745 | }; 746 | name = Debug; 747 | }; 748 | BBD9177A9BF3B539ED3EF54BB041B71E /* Debug */ = { 749 | isa = XCBuildConfiguration; 750 | baseConfigurationReference = 8E091F81614D27D3387A5D5334D933D7 /* Pods-FluidTabBarController_Example.debug.xcconfig */; 751 | buildSettings = { 752 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; 753 | CLANG_ENABLE_OBJC_WEAK = NO; 754 | CODE_SIGN_IDENTITY = ""; 755 | "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; 756 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 757 | "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; 758 | CURRENT_PROJECT_VERSION = 1; 759 | DEFINES_MODULE = YES; 760 | DYLIB_COMPATIBILITY_VERSION = 1; 761 | DYLIB_CURRENT_VERSION = 1; 762 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 763 | INFOPLIST_FILE = "Target Support Files/Pods-FluidTabBarController_Example/Info.plist"; 764 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 765 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 766 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 767 | MACH_O_TYPE = staticlib; 768 | MODULEMAP_FILE = "Target Support Files/Pods-FluidTabBarController_Example/Pods-FluidTabBarController_Example.modulemap"; 769 | OTHER_LDFLAGS = ""; 770 | OTHER_LIBTOOLFLAGS = ""; 771 | PODS_ROOT = "$(SRCROOT)"; 772 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; 773 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 774 | SDKROOT = iphoneos; 775 | SKIP_INSTALL = YES; 776 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 777 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 778 | TARGETED_DEVICE_FAMILY = "1,2"; 779 | VERSIONING_SYSTEM = "apple-generic"; 780 | VERSION_INFO_PREFIX = ""; 781 | }; 782 | name = Debug; 783 | }; 784 | /* End XCBuildConfiguration section */ 785 | 786 | /* Begin XCConfigurationList section */ 787 | 208B3B57BDE9F6F8548326F21BEBED88 /* Build configuration list for PBXNativeTarget "FluidTabBarController" */ = { 788 | isa = XCConfigurationList; 789 | buildConfigurations = ( 790 | 19420BF9FEFB05F3F4E3ADFEB09CBC06 /* Debug */, 791 | 2772B8C9EFDC40AD8A074AE40CB903C3 /* Release */, 792 | ); 793 | defaultConfigurationIsVisible = 0; 794 | defaultConfigurationName = Release; 795 | }; 796 | 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */ = { 797 | isa = XCConfigurationList; 798 | buildConfigurations = ( 799 | 553022A828EE1991F07D2D73F565AEF8 /* Debug */, 800 | 58CE816B060A41D32CEC095441D0E3E0 /* Release */, 801 | ); 802 | defaultConfigurationIsVisible = 0; 803 | defaultConfigurationName = Release; 804 | }; 805 | 7A220494BBBF86A6EB09A4A7CC1BA2CF /* Build configuration list for PBXNativeTarget "Pods-FluidTabBarController_Example" */ = { 806 | isa = XCConfigurationList; 807 | buildConfigurations = ( 808 | BBD9177A9BF3B539ED3EF54BB041B71E /* Debug */, 809 | 081113F1788D5D43C83B93FFF28F4F8E /* Release */, 810 | ); 811 | defaultConfigurationIsVisible = 0; 812 | defaultConfigurationName = Release; 813 | }; 814 | A63413E5A63C15D2081A1613195E4A68 /* Build configuration list for PBXNativeTarget "Pods-FluidTabBarController_Tests" */ = { 815 | isa = XCConfigurationList; 816 | buildConfigurations = ( 817 | A403E38CC53DEEB849CB23D0BCF38892 /* Debug */, 818 | 3D523DF606590281EAAAB8C035E25492 /* Release */, 819 | ); 820 | defaultConfigurationIsVisible = 0; 821 | defaultConfigurationName = Release; 822 | }; 823 | /* End XCConfigurationList section */ 824 | }; 825 | rootObject = D41D8CD98F00B204E9800998ECF8427E /* Project object */; 826 | } 827 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/FluidTabBarController/FluidTabBarController-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_FluidTabBarController : NSObject 3 | @end 4 | @implementation PodsDummy_FluidTabBarController 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/FluidTabBarController/FluidTabBarController-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/FluidTabBarController/FluidTabBarController-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double FluidTabBarControllerVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char FluidTabBarControllerVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/FluidTabBarController/FluidTabBarController.modulemap: -------------------------------------------------------------------------------- 1 | framework module FluidTabBarController { 2 | umbrella header "FluidTabBarController-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/FluidTabBarController/FluidTabBarController.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/FluidTabBarController 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 4 | PODS_BUILD_DIR = ${BUILD_DIR} 5 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 6 | PODS_ROOT = ${SRCROOT} 7 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../.. 8 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 9 | SKIP_INSTALL = YES 10 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/FluidTabBarController/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 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 | 0.5.3 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-FluidTabBarController_Example/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 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.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-FluidTabBarController_Example/Pods-FluidTabBarController_Example-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## FluidTabBarController 5 | 6 | Copyright (c) 2018 Hubert Kuczyński 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in 16 | all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | THE SOFTWARE. 25 | 26 | Generated by CocoaPods - https://cocoapods.org 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-FluidTabBarController_Example/Pods-FluidTabBarController_Example-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | Copyright (c) 2018 Hubert Kuczyński <hubert.kuczynski@10clouds.com> 18 | 19 | Permission is hereby granted, free of charge, to any person obtaining a copy 20 | of this software and associated documentation files (the "Software"), to deal 21 | in the Software without restriction, including without limitation the rights 22 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 23 | copies of the Software, and to permit persons to whom the Software is 24 | furnished to do so, subject to the following conditions: 25 | 26 | The above copyright notice and this permission notice shall be included in 27 | all copies or substantial portions of the Software. 28 | 29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 30 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 31 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 32 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 33 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 34 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 35 | THE SOFTWARE. 36 | 37 | License 38 | MIT 39 | Title 40 | FluidTabBarController 41 | Type 42 | PSGroupSpecifier 43 | 44 | 45 | FooterText 46 | Generated by CocoaPods - https://cocoapods.org 47 | Title 48 | 49 | Type 50 | PSGroupSpecifier 51 | 52 | 53 | StringsTable 54 | Acknowledgements 55 | Title 56 | Acknowledgements 57 | 58 | 59 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-FluidTabBarController_Example/Pods-FluidTabBarController_Example-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_FluidTabBarController_Example : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_FluidTabBarController_Example 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-FluidTabBarController_Example/Pods-FluidTabBarController_Example-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | set -o pipefail 5 | 6 | if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then 7 | # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy 8 | # frameworks to, so exit 0 (signalling the script phase was successful). 9 | exit 0 10 | fi 11 | 12 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 13 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 14 | 15 | COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" 16 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 17 | 18 | # Used as a return value for each invocation of `strip_invalid_archs` function. 19 | STRIP_BINARY_RETVAL=0 20 | 21 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 22 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 23 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 24 | 25 | # Copies and strips a vendored framework 26 | install_framework() 27 | { 28 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 29 | local source="${BUILT_PRODUCTS_DIR}/$1" 30 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 31 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 32 | elif [ -r "$1" ]; then 33 | local source="$1" 34 | fi 35 | 36 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 37 | 38 | if [ -L "${source}" ]; then 39 | echo "Symlinked..." 40 | source="$(readlink "${source}")" 41 | fi 42 | 43 | # Use filter instead of exclude so missing patterns don't throw errors. 44 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 45 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 46 | 47 | local basename 48 | basename="$(basename -s .framework "$1")" 49 | binary="${destination}/${basename}.framework/${basename}" 50 | if ! [ -r "$binary" ]; then 51 | binary="${destination}/${basename}" 52 | fi 53 | 54 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 55 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 56 | strip_invalid_archs "$binary" 57 | fi 58 | 59 | # Resign the code if required by the build settings to avoid unstable apps 60 | code_sign_if_enabled "${destination}/$(basename "$1")" 61 | 62 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 63 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 64 | local swift_runtime_libs 65 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 66 | for lib in $swift_runtime_libs; do 67 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 68 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 69 | code_sign_if_enabled "${destination}/${lib}" 70 | done 71 | fi 72 | } 73 | 74 | # Copies and strips a vendored dSYM 75 | install_dsym() { 76 | local source="$1" 77 | if [ -r "$source" ]; then 78 | # Copy the dSYM into a the targets temp dir. 79 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" 80 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" 81 | 82 | local basename 83 | basename="$(basename -s .framework.dSYM "$source")" 84 | binary="${DERIVED_FILES_DIR}/${basename}.framework.dSYM/Contents/Resources/DWARF/${basename}" 85 | 86 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 87 | if [[ "$(file "$binary")" == *"Mach-O dSYM companion"* ]]; then 88 | strip_invalid_archs "$binary" 89 | fi 90 | 91 | if [[ $STRIP_BINARY_RETVAL == 1 ]]; then 92 | # Move the stripped file into its final destination. 93 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" 94 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.framework.dSYM" "${DWARF_DSYM_FOLDER_PATH}" 95 | else 96 | # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. 97 | touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.framework.dSYM" 98 | fi 99 | fi 100 | } 101 | 102 | # Signs a framework with the provided identity 103 | code_sign_if_enabled() { 104 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 105 | # Use the current code_sign_identitiy 106 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 107 | local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" 108 | 109 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 110 | code_sign_cmd="$code_sign_cmd &" 111 | fi 112 | echo "$code_sign_cmd" 113 | eval "$code_sign_cmd" 114 | fi 115 | } 116 | 117 | # Strip invalid architectures 118 | strip_invalid_archs() { 119 | binary="$1" 120 | # Get architectures for current target binary 121 | binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" 122 | # Intersect them with the architectures we are building for 123 | intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" 124 | # If there are no archs supported by this binary then warn the user 125 | if [[ -z "$intersected_archs" ]]; then 126 | echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." 127 | STRIP_BINARY_RETVAL=0 128 | return 129 | fi 130 | stripped="" 131 | for arch in $binary_archs; do 132 | if ! [[ "${ARCHS}" == *"$arch"* ]]; then 133 | # Strip non-valid architectures in-place 134 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 135 | stripped="$stripped $arch" 136 | fi 137 | done 138 | if [[ "$stripped" ]]; then 139 | echo "Stripped $binary of architectures:$stripped" 140 | fi 141 | STRIP_BINARY_RETVAL=1 142 | } 143 | 144 | 145 | if [[ "$CONFIGURATION" == "Debug" ]]; then 146 | install_framework "${BUILT_PRODUCTS_DIR}/FluidTabBarController/FluidTabBarController.framework" 147 | fi 148 | if [[ "$CONFIGURATION" == "Release" ]]; then 149 | install_framework "${BUILT_PRODUCTS_DIR}/FluidTabBarController/FluidTabBarController.framework" 150 | fi 151 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 152 | wait 153 | fi 154 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-FluidTabBarController_Example/Pods-FluidTabBarController_Example-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | set -o pipefail 5 | 6 | if [ -z ${UNLOCALIZED_RESOURCES_FOLDER_PATH+x} ]; then 7 | # If UNLOCALIZED_RESOURCES_FOLDER_PATH is not set, then there's nowhere for us to copy 8 | # resources to, so exit 0 (signalling the script phase was successful). 9 | exit 0 10 | fi 11 | 12 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 13 | 14 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 15 | > "$RESOURCES_TO_COPY" 16 | 17 | XCASSET_FILES=() 18 | 19 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 20 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 21 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 22 | 23 | case "${TARGETED_DEVICE_FAMILY:-}" in 24 | 1,2) 25 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 26 | ;; 27 | 1) 28 | TARGET_DEVICE_ARGS="--target-device iphone" 29 | ;; 30 | 2) 31 | TARGET_DEVICE_ARGS="--target-device ipad" 32 | ;; 33 | 3) 34 | TARGET_DEVICE_ARGS="--target-device tv" 35 | ;; 36 | 4) 37 | TARGET_DEVICE_ARGS="--target-device watch" 38 | ;; 39 | *) 40 | TARGET_DEVICE_ARGS="--target-device mac" 41 | ;; 42 | esac 43 | 44 | install_resource() 45 | { 46 | if [[ "$1" = /* ]] ; then 47 | RESOURCE_PATH="$1" 48 | else 49 | RESOURCE_PATH="${PODS_ROOT}/$1" 50 | fi 51 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 52 | cat << EOM 53 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 54 | EOM 55 | exit 1 56 | fi 57 | case $RESOURCE_PATH in 58 | *.storyboard) 59 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 60 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 61 | ;; 62 | *.xib) 63 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 64 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 65 | ;; 66 | *.framework) 67 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 68 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 69 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 70 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 71 | ;; 72 | *.xcdatamodel) 73 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true 74 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 75 | ;; 76 | *.xcdatamodeld) 77 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true 78 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 79 | ;; 80 | *.xcmappingmodel) 81 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true 82 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 83 | ;; 84 | *.xcassets) 85 | ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" 86 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 87 | ;; 88 | *) 89 | echo "$RESOURCE_PATH" || true 90 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 91 | ;; 92 | esac 93 | } 94 | 95 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 96 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 97 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 98 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 99 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 100 | fi 101 | rm -f "$RESOURCES_TO_COPY" 102 | 103 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "${XCASSET_FILES:-}" ] 104 | then 105 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 106 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 107 | while read line; do 108 | if [[ $line != "${PODS_ROOT}*" ]]; then 109 | XCASSET_FILES+=("$line") 110 | fi 111 | done <<<"$OTHER_XCASSETS" 112 | 113 | if [ -z ${ASSETCATALOG_COMPILER_APPICON_NAME+x} ]; then 114 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 115 | else 116 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${TARGET_TEMP_DIR}/assetcatalog_generated_info_cocoapods.plist" 117 | fi 118 | fi 119 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-FluidTabBarController_Example/Pods-FluidTabBarController_Example-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double Pods_FluidTabBarController_ExampleVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char Pods_FluidTabBarController_ExampleVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-FluidTabBarController_Example/Pods-FluidTabBarController_Example.debug.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FluidTabBarController" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 5 | OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/FluidTabBarController/FluidTabBarController.framework/Headers" 6 | OTHER_LDFLAGS = $(inherited) -framework "FluidTabBarController" 7 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 8 | PODS_BUILD_DIR = ${BUILD_DIR} 9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 11 | PODS_ROOT = ${SRCROOT}/Pods 12 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-FluidTabBarController_Example/Pods-FluidTabBarController_Example.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_FluidTabBarController_Example { 2 | umbrella header "Pods-FluidTabBarController_Example-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-FluidTabBarController_Example/Pods-FluidTabBarController_Example.release.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FluidTabBarController" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 5 | OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/FluidTabBarController/FluidTabBarController.framework/Headers" 6 | OTHER_LDFLAGS = $(inherited) -framework "FluidTabBarController" 7 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 8 | PODS_BUILD_DIR = ${BUILD_DIR} 9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 11 | PODS_ROOT = ${SRCROOT}/Pods 12 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-FluidTabBarController_Tests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 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.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-FluidTabBarController_Tests/Pods-FluidTabBarController_Tests-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | Generated by CocoaPods - https://cocoapods.org 4 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-FluidTabBarController_Tests/Pods-FluidTabBarController_Tests-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | Generated by CocoaPods - https://cocoapods.org 18 | Title 19 | 20 | Type 21 | PSGroupSpecifier 22 | 23 | 24 | StringsTable 25 | Acknowledgements 26 | Title 27 | Acknowledgements 28 | 29 | 30 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-FluidTabBarController_Tests/Pods-FluidTabBarController_Tests-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_FluidTabBarController_Tests : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_FluidTabBarController_Tests 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-FluidTabBarController_Tests/Pods-FluidTabBarController_Tests-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | set -o pipefail 5 | 6 | if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then 7 | # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy 8 | # frameworks to, so exit 0 (signalling the script phase was successful). 9 | exit 0 10 | fi 11 | 12 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 13 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 14 | 15 | COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" 16 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 17 | 18 | # Used as a return value for each invocation of `strip_invalid_archs` function. 19 | STRIP_BINARY_RETVAL=0 20 | 21 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 22 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 23 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 24 | 25 | # Copies and strips a vendored framework 26 | install_framework() 27 | { 28 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 29 | local source="${BUILT_PRODUCTS_DIR}/$1" 30 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 31 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 32 | elif [ -r "$1" ]; then 33 | local source="$1" 34 | fi 35 | 36 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 37 | 38 | if [ -L "${source}" ]; then 39 | echo "Symlinked..." 40 | source="$(readlink "${source}")" 41 | fi 42 | 43 | # Use filter instead of exclude so missing patterns don't throw errors. 44 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 45 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 46 | 47 | local basename 48 | basename="$(basename -s .framework "$1")" 49 | binary="${destination}/${basename}.framework/${basename}" 50 | if ! [ -r "$binary" ]; then 51 | binary="${destination}/${basename}" 52 | fi 53 | 54 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 55 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 56 | strip_invalid_archs "$binary" 57 | fi 58 | 59 | # Resign the code if required by the build settings to avoid unstable apps 60 | code_sign_if_enabled "${destination}/$(basename "$1")" 61 | 62 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 63 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 64 | local swift_runtime_libs 65 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 66 | for lib in $swift_runtime_libs; do 67 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 68 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 69 | code_sign_if_enabled "${destination}/${lib}" 70 | done 71 | fi 72 | } 73 | 74 | # Copies and strips a vendored dSYM 75 | install_dsym() { 76 | local source="$1" 77 | if [ -r "$source" ]; then 78 | # Copy the dSYM into a the targets temp dir. 79 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" 80 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" 81 | 82 | local basename 83 | basename="$(basename -s .framework.dSYM "$source")" 84 | binary="${DERIVED_FILES_DIR}/${basename}.framework.dSYM/Contents/Resources/DWARF/${basename}" 85 | 86 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 87 | if [[ "$(file "$binary")" == *"Mach-O dSYM companion"* ]]; then 88 | strip_invalid_archs "$binary" 89 | fi 90 | 91 | if [[ $STRIP_BINARY_RETVAL == 1 ]]; then 92 | # Move the stripped file into its final destination. 93 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" 94 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.framework.dSYM" "${DWARF_DSYM_FOLDER_PATH}" 95 | else 96 | # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. 97 | touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.framework.dSYM" 98 | fi 99 | fi 100 | } 101 | 102 | # Signs a framework with the provided identity 103 | code_sign_if_enabled() { 104 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 105 | # Use the current code_sign_identitiy 106 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 107 | local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" 108 | 109 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 110 | code_sign_cmd="$code_sign_cmd &" 111 | fi 112 | echo "$code_sign_cmd" 113 | eval "$code_sign_cmd" 114 | fi 115 | } 116 | 117 | # Strip invalid architectures 118 | strip_invalid_archs() { 119 | binary="$1" 120 | # Get architectures for current target binary 121 | binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" 122 | # Intersect them with the architectures we are building for 123 | intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" 124 | # If there are no archs supported by this binary then warn the user 125 | if [[ -z "$intersected_archs" ]]; then 126 | echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." 127 | STRIP_BINARY_RETVAL=0 128 | return 129 | fi 130 | stripped="" 131 | for arch in $binary_archs; do 132 | if ! [[ "${ARCHS}" == *"$arch"* ]]; then 133 | # Strip non-valid architectures in-place 134 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 135 | stripped="$stripped $arch" 136 | fi 137 | done 138 | if [[ "$stripped" ]]; then 139 | echo "Stripped $binary of architectures:$stripped" 140 | fi 141 | STRIP_BINARY_RETVAL=1 142 | } 143 | 144 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 145 | wait 146 | fi 147 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-FluidTabBarController_Tests/Pods-FluidTabBarController_Tests-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | set -o pipefail 5 | 6 | if [ -z ${UNLOCALIZED_RESOURCES_FOLDER_PATH+x} ]; then 7 | # If UNLOCALIZED_RESOURCES_FOLDER_PATH is not set, then there's nowhere for us to copy 8 | # resources to, so exit 0 (signalling the script phase was successful). 9 | exit 0 10 | fi 11 | 12 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 13 | 14 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 15 | > "$RESOURCES_TO_COPY" 16 | 17 | XCASSET_FILES=() 18 | 19 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 20 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 21 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 22 | 23 | case "${TARGETED_DEVICE_FAMILY:-}" in 24 | 1,2) 25 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 26 | ;; 27 | 1) 28 | TARGET_DEVICE_ARGS="--target-device iphone" 29 | ;; 30 | 2) 31 | TARGET_DEVICE_ARGS="--target-device ipad" 32 | ;; 33 | 3) 34 | TARGET_DEVICE_ARGS="--target-device tv" 35 | ;; 36 | 4) 37 | TARGET_DEVICE_ARGS="--target-device watch" 38 | ;; 39 | *) 40 | TARGET_DEVICE_ARGS="--target-device mac" 41 | ;; 42 | esac 43 | 44 | install_resource() 45 | { 46 | if [[ "$1" = /* ]] ; then 47 | RESOURCE_PATH="$1" 48 | else 49 | RESOURCE_PATH="${PODS_ROOT}/$1" 50 | fi 51 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 52 | cat << EOM 53 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 54 | EOM 55 | exit 1 56 | fi 57 | case $RESOURCE_PATH in 58 | *.storyboard) 59 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 60 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 61 | ;; 62 | *.xib) 63 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 64 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 65 | ;; 66 | *.framework) 67 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 68 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 69 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 70 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 71 | ;; 72 | *.xcdatamodel) 73 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true 74 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 75 | ;; 76 | *.xcdatamodeld) 77 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true 78 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 79 | ;; 80 | *.xcmappingmodel) 81 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true 82 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 83 | ;; 84 | *.xcassets) 85 | ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" 86 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 87 | ;; 88 | *) 89 | echo "$RESOURCE_PATH" || true 90 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 91 | ;; 92 | esac 93 | } 94 | 95 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 96 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 97 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 98 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 99 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 100 | fi 101 | rm -f "$RESOURCES_TO_COPY" 102 | 103 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "${XCASSET_FILES:-}" ] 104 | then 105 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 106 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 107 | while read line; do 108 | if [[ $line != "${PODS_ROOT}*" ]]; then 109 | XCASSET_FILES+=("$line") 110 | fi 111 | done <<<"$OTHER_XCASSETS" 112 | 113 | if [ -z ${ASSETCATALOG_COMPILER_APPICON_NAME+x} ]; then 114 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 115 | else 116 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${TARGET_TEMP_DIR}/assetcatalog_generated_info_cocoapods.plist" 117 | fi 118 | fi 119 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-FluidTabBarController_Tests/Pods-FluidTabBarController_Tests-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double Pods_FluidTabBarController_TestsVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char Pods_FluidTabBarController_TestsVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-FluidTabBarController_Tests/Pods-FluidTabBarController_Tests.debug.xcconfig: -------------------------------------------------------------------------------- 1 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FluidTabBarController" 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 4 | OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/FluidTabBarController/FluidTabBarController.framework/Headers" 5 | PODS_BUILD_DIR = ${BUILD_DIR} 6 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 8 | PODS_ROOT = ${SRCROOT}/Pods 9 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-FluidTabBarController_Tests/Pods-FluidTabBarController_Tests.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_FluidTabBarController_Tests { 2 | umbrella header "Pods-FluidTabBarController_Tests-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-FluidTabBarController_Tests/Pods-FluidTabBarController_Tests.release.xcconfig: -------------------------------------------------------------------------------- 1 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/FluidTabBarController" 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 4 | OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/FluidTabBarController/FluidTabBarController.framework/Headers" 5 | PODS_BUILD_DIR = ${BUILD_DIR} 6 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 8 | PODS_ROOT = ${SRCROOT}/Pods 9 | -------------------------------------------------------------------------------- /Example/Tests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Example/Tests/Tests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import FluidTabBarController 3 | 4 | class Tests: XCTestCase { 5 | 6 | override func setUp() { 7 | super.setUp() 8 | // Put setup code here. This method is called before the invocation of each test method in the class. 9 | } 10 | 11 | override func tearDown() { 12 | // Put teardown code here. This method is called after the invocation of each test method in the class. 13 | super.tearDown() 14 | } 15 | 16 | func testExample() { 17 | // This is an example of a functional test case. 18 | XCTAssert(true, "Pass") 19 | } 20 | 21 | func testPerformanceExample() { 22 | // This is an example of a performance test case. 23 | self.measure() { 24 | // Put the code you want to measure the time of here. 25 | } 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /FluidTabBarController.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod lib lint FluidTabBarController.podspec' to ensure this is a 3 | # valid spec before submitting. 4 | # 5 | # Any lines starting with a # are optional, but their use is encouraged 6 | # To learn more about a Podspec see https://guides.cocoapods.org/syntax/podspec.html 7 | # 8 | 9 | Pod::Spec.new do |s| 10 | s.name = 'FluidTabBarController' 11 | s.version = '0.5.3' 12 | s.summary = 'Animated version of UITabBarController' 13 | 14 | # This description is used to generate tags and improve search results. 15 | # * Think: What does it do? Why did you write it? What is the focus? 16 | # * Try to keep it short, snappy and to the point. 17 | # * Write the description between the DESC delimiters below. 18 | # * Finally, don't worry about the indent, CocoaPods strips it! 19 | 20 | s.description = <<-DESC 21 | Animated version of UITabBarController with fluid-like animation of selecting item 22 | DESC 23 | 24 | s.homepage = 'https://github.com/10clouds/FluidBottomNavigation-ios' 25 | # s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2' 26 | s.license = { :type => 'MIT', :file => 'LICENSE' } 27 | s.author = { 'Hubert Kuczyński' => 'hubert.kuczynski@10clouds.com' } 28 | s.source = { :git => 'https://github.com/10clouds/FluidBottomNavigation-ios.git', :tag => s.version.to_s } 29 | # s.social_media_url = 'https://twitter.com/' 30 | 31 | s.ios.deployment_target = '10.0' 32 | s.swift_version = '4.0' 33 | 34 | s.source_files = 'FluidTabBarController/**/*' 35 | 36 | # s.resource_bundles = { 37 | # 'FluidTabBarController' => ['FluidTabBarController/Assets/*.png'] 38 | # } 39 | 40 | # s.public_header_files = 'Pod/Classes/**/*.h' 41 | # s.frameworks = 'UIKit', 'MapKit' 42 | # s.dependency 'AFNetworking', '~> 2.3' 43 | end 44 | -------------------------------------------------------------------------------- /FluidTabBarController/Animation/ContainerAnimator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContainerAnimator.swift 3 | // FluidTabBarController 4 | // 5 | // Created by Hubert Kuczyński on 19/07/2018. 6 | // Copyright © 2018 10Clouds Sp. z o.o. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | // 26 | 27 | import UIKit 28 | 29 | final class ContainerAnimator: NSObject { 30 | 31 | private struct Constants { 32 | static let positionAnimationDelta: CGFloat = 0.2 33 | struct Keys { 34 | static let moveDown = "move_down" 35 | static let moveUp = "move_up" 36 | } 37 | } 38 | 39 | // MARK: Public properties 40 | 41 | var onMoveUpAnimationStart: (() -> Void)? 42 | var onMoveDownAnimationStart: (() -> Void)? 43 | 44 | // MARK: Private properties 45 | 46 | private let layer: CALayer 47 | 48 | // MARK: Initializers 49 | 50 | init(layer: CALayer) { 51 | self.layer = layer 52 | super.init() 53 | } 54 | 55 | // MARK: Public methods 56 | 57 | func animateMoveDown(offset: CGFloat, beginTime: CFTimeInterval, duration: CFTimeInterval) { 58 | let positionAnimation = CAKeyframeAnimation(keyPath: "position.y") 59 | let delta = offset * Constants.positionAnimationDelta 60 | 61 | positionAnimation.values = [layer.position.y, layer.position.y - delta, layer.position.y + offset] 62 | positionAnimation.keyTimes = [0.0, 1.0 / 4.0, 1.0].map { NSNumber(value: $0) } 63 | positionAnimation.timingFunctions = [TimingFunctions.values[3], TimingFunctions.values[0]] 64 | positionAnimation.fillMode = kCAFillModeBackwards 65 | positionAnimation.beginTime = beginTime 66 | positionAnimation.duration = duration 67 | positionAnimation.delegate = self 68 | 69 | layer.add(positionAnimation, forKey: Constants.Keys.moveDown) 70 | layer.position.y += offset 71 | } 72 | 73 | func animateMoveUp(offset: CGFloat, beginTime: CFTimeInterval, duration: CFTimeInterval) { 74 | let positionAnimation = createPositionAnimation(startValue: layer.position.y, endValue: layer.position.y + offset) 75 | positionAnimation.beginTime = beginTime 76 | positionAnimation.duration = duration 77 | positionAnimation.delegate = self 78 | layer.add(positionAnimation, forKey: Constants.Keys.moveUp) 79 | layer.position.y += offset 80 | } 81 | 82 | // MARK: Private methods 83 | 84 | private func createPositionAnimation(startValue: CGFloat, endValue: CGFloat) -> CAAnimation { 85 | let animation = CAKeyframeAnimation(keyPath: "position.y") 86 | let delta = (endValue - startValue) * Constants.positionAnimationDelta 87 | let easeIn = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn) 88 | let easeOut = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut) 89 | animation.timingFunctions = [easeOut, easeIn, easeOut] 90 | animation.values = [startValue, endValue + delta, endValue - delta / 2, endValue] 91 | animation.fillMode = kCAFillModeBackwards 92 | return animation 93 | } 94 | } 95 | 96 | extension ContainerAnimator: CAAnimationDelegate { 97 | func animationDidStart(_ anim: CAAnimation) { 98 | if anim == layer.animation(forKey: Constants.Keys.moveDown) { 99 | onMoveDownAnimationStart?() 100 | } else if anim == layer.animation(forKey: Constants.Keys.moveUp) { 101 | onMoveUpAnimationStart?() 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /FluidTabBarController/Animation/FluidTabBarItemAnimator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FluidTabBarItemAnimator.swift 3 | // FluidTabBarController 4 | // 5 | // Created by Hubert Kuczyński on 10/07/2018. 6 | // Copyright © 2018 10Clouds Sp. z o.o. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | // 26 | 27 | import Foundation 28 | 29 | public protocol FluidTabBarItemAnimator { 30 | var allowsLandscapeIconsArrangement: Bool { get } 31 | func initialize() 32 | func selectAnimation(animated: Bool, completion: (() -> ())?) 33 | func deselectAnimation(animated: Bool, completion: (() -> ())?) 34 | func reselectAnimation(animated: Bool, completion: (() -> ())?) 35 | func highlightAnimation(animated: Bool, completion: (() -> ())?) 36 | func dehighlightAnimation(animated: Bool, completion: (() -> ())?) 37 | } 38 | 39 | extension FluidTabBarItemAnimator { 40 | var allowsLandscapeIconsArrangement: Bool { 41 | return true 42 | } 43 | 44 | func selectAnimation(animated: Bool, completion: (() -> ())?) { 45 | completion?() 46 | } 47 | 48 | func deselectAnimation(animated: Bool, completion: (() -> ())?) { 49 | completion?() 50 | } 51 | 52 | func reselectAnimation(animated: Bool, completion: (() -> ())?) { 53 | completion?() 54 | } 55 | 56 | func highlightAnimation(animated: Bool, completion: (() -> ())?) { 57 | completion?() 58 | } 59 | 60 | func dehighlightAnimation(animated: Bool, completion: (() -> ())?) { 61 | completion?() 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /FluidTabBarController/Animation/FluidTabBarItemAnimatorDefault.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FluidTabBarItemAnimatorDefault.swift 3 | // FluidTabBarController 4 | // 5 | // Created by Hubert Kuczyński on 19/07/2018. 6 | // Copyright © 2018 10Clouds Sp. z o.o. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | // 26 | 27 | import UIKit 28 | 29 | final class FluidTabBarItemAnimatorDefault: NSObject, FluidTabBarItemAnimator { 30 | 31 | private struct Constants { 32 | static let scaleDuration = 0.95 33 | static let positionDuration = 0.2 34 | } 35 | 36 | // MARK: Public properties 37 | 38 | var allowsLandscapeIconsArrangement: Bool { 39 | return false 40 | } 41 | 42 | weak var contentView: FluidTabBarItemContentView? 43 | 44 | // MARK: Private properties 45 | 46 | private lazy var containerAnimator: ContainerAnimator? = { 47 | guard let contentView = contentView else { return nil } 48 | let animator = ContainerAnimator(layer: contentView.imageViewContainer.layer) 49 | 50 | animator.onMoveUpAnimationStart = { [weak self] in 51 | self?.circleLayer.animateMovement() 52 | } 53 | animator.onMoveDownAnimationStart = { [weak self] in 54 | Timer.scheduledTimer(withTimeInterval: 0.1, repeats: false) { _ in 55 | self?.circleLayer.animateMovement() 56 | } 57 | } 58 | 59 | return animator 60 | }() 61 | 62 | private lazy var labelAnimator: LabelAnimator? = { 63 | guard let contentView = contentView else { return nil } 64 | return LabelAnimator(layer: contentView.titleLabel.layer) 65 | }() 66 | 67 | private lazy var iconAnimator: IconAnimator? = { 68 | guard let contentView = contentView else { return nil } 69 | return IconAnimator(layer: contentView.titleLabel.layer) 70 | }() 71 | 72 | private var circleFillColor: UIColor? { 73 | return contentView?.tintColor 74 | } 75 | 76 | private var imageViewAnimationOffset: CGFloat = 0 77 | 78 | private var circleRect: CGRect { 79 | let inset: CGFloat = -10 80 | return contentView?.imageViewContainer.bounds.insetBy(dx: inset, dy: inset) ?? .zero 81 | } 82 | 83 | private lazy var titleLabelAnimationOffset: CGFloat = 60 84 | private let circleCenterOffset: CGFloat = 5 85 | private let curveLayer = CurveLayer() 86 | 87 | private lazy var circleLayer: StretchyCircleLayer = { 88 | let layer = StretchyCircleLayer() 89 | layer.movementDuration = Constants.scaleDuration / 6 90 | return layer 91 | }() 92 | 93 | // MARK: Public methods 94 | 95 | func initialize() { 96 | guard let contentView = contentView else { return } 97 | contentView.imageViewContainer.layer.position.y = contentView.center.y 98 | contentView.titleLabel.layer.position.y = calculateLabelPosition(forStateSelected: false) 99 | contentView.highlightImageColor = .white 100 | contentView.imageViewContainer.layer.insertSublayer(circleLayer, at: 0) 101 | contentView.layer.insertSublayer(curveLayer, at: 0) 102 | imageViewAnimationOffset = contentView.imageViewContainer.frame.midY - contentView.frame.minY + circleCenterOffset 103 | } 104 | 105 | func selectAnimation(animated: Bool, completion: (() -> ())?) { 106 | guard contentView?.frame != .zero else { return } 107 | CATransaction.begin() 108 | CATransaction.setCompletionBlock(completion) 109 | CATransaction.setDisableActions(!animated) 110 | drawCircle(inRect: circleRect) 111 | drawCurve(inRect: circleRect) 112 | animateMoveUp() 113 | CATransaction.commit() 114 | } 115 | 116 | func deselectAnimation(animated: Bool, completion: (() -> ())?) { 117 | CATransaction.begin() 118 | CATransaction.setCompletionBlock(completion) 119 | CATransaction.setDisableActions(!animated) 120 | animateMoveDown() 121 | CATransaction.commit() 122 | } 123 | 124 | // MARK: Private methods 125 | 126 | private func animateMoveUp() { 127 | let time = CACurrentMediaTime() 128 | let positionAnimationBeginTime = time + Constants.scaleDuration / 2 129 | 130 | curveLayer.animateShow( 131 | beginTime: positionAnimationBeginTime, 132 | duration: Constants.scaleDuration / 2 133 | ) 134 | 135 | circleLayer.animateShow( 136 | beginTime: time, 137 | duration: Constants.scaleDuration 138 | ) 139 | 140 | containerAnimator?.animateMoveUp( 141 | offset: -imageViewAnimationOffset, 142 | beginTime: positionAnimationBeginTime, 143 | duration: Constants.scaleDuration / 2 144 | ) 145 | 146 | labelAnimator?.animatePosition( 147 | beginTime: time + Constants.scaleDuration - 0.3, 148 | duration: Constants.positionDuration, 149 | toValue: calculateLabelPosition(forStateSelected: true) 150 | ) 151 | 152 | iconAnimator?.animateScale( 153 | beginTime: time, 154 | duration: Constants.scaleDuration, 155 | reversed: false 156 | ) 157 | } 158 | 159 | private func animateMoveDown() { 160 | let time = CACurrentMediaTime() 161 | 162 | curveLayer.animateHide( 163 | beginTime: time, 164 | duration: Constants.scaleDuration / 2 165 | ) 166 | 167 | circleLayer.animateHide( 168 | beginTime: time, 169 | duration: Constants.scaleDuration 170 | ) 171 | 172 | containerAnimator?.animateMoveDown( 173 | offset: imageViewAnimationOffset, 174 | beginTime: time + Constants.scaleDuration / 30.0, 175 | duration: Constants.scaleDuration / 2 176 | ) 177 | 178 | labelAnimator?.animatePosition( 179 | beginTime: time + 0.05, 180 | duration: Constants.positionDuration, 181 | toValue: calculateLabelPosition(forStateSelected: false) 182 | ) 183 | 184 | iconAnimator?.animateScale( 185 | beginTime: time, 186 | duration: Constants.scaleDuration, 187 | reversed: true 188 | ) 189 | 190 | contentView?.imageView.tintColor = contentView?.highlightImageColor 191 | UIView.animate(withDuration: Constants.scaleDuration) { 192 | self.contentView?.imageView.tintColor = self.contentView?.imageColor 193 | } 194 | } 195 | 196 | private func calculateLabelPosition(forStateSelected selected: Bool) -> CGFloat { 197 | guard let contentView = contentView else { return 0 } 198 | if selected { 199 | return circleRect.maxY + (contentView.frame.maxY - circleRect.maxY - imageViewAnimationOffset) / 2.0 + 3 200 | } else { 201 | return contentView.frame.height * 2 202 | } 203 | } 204 | 205 | private func drawCircle(inRect rect: CGRect) { 206 | circleLayer.frame = rect 207 | circleLayer.fillColor = circleFillColor?.cgColor 208 | } 209 | 210 | private func drawCurve(inRect rect: CGRect) { 211 | let curveMargin: CGFloat = 2 212 | let size = CGSize( 213 | width: circleRect.width * 2, 214 | height: circleRect.height / 2 + circleCenterOffset + curveMargin 215 | ) 216 | 217 | curveLayer.frame.size = size 218 | curveLayer.fillColor = contentView?.backgroundColor?.cgColor ?? UIColor.white.cgColor 219 | curveLayer.anchorPoint = CGPoint(x: 0.5, y: 1.0) 220 | curveLayer.position = CGPoint(x: contentView!.frame.midX, y: contentView!.frame.minY - 1) 221 | curveLayer.updatePath(centerOffset: -circleCenterOffset) 222 | } 223 | } 224 | -------------------------------------------------------------------------------- /FluidTabBarController/Animation/IconAnimator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // IconAnimator.swift 3 | // FluidTabBarController 4 | // 5 | // Created by Hubert Kuczyński on 19/07/2018. 6 | // Copyright © 2018 10Clouds Sp. z o.o. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | // 26 | 27 | import UIKit 28 | 29 | final class IconAnimator { 30 | 31 | // MARK: Private properties 32 | 33 | private let layer: CALayer 34 | 35 | // MARK: Initializers 36 | 37 | init(layer: CALayer) { 38 | self.layer = layer 39 | } 40 | 41 | // MARK: Public methods 42 | 43 | func animateScale(beginTime: CFTimeInterval, duration: CFTimeInterval, reversed: Bool) { 44 | let iconScaleAnimation = CAKeyframeAnimation(keyPath: "transform.scale") 45 | iconScaleAnimation.values = [1.0, 0.94, 1.1, 1.0] 46 | iconScaleAnimation.keyTimes = [0.0, 4.0 / 15.0, 8.0 / 15.0, 1.0].map { NSNumber(value: $0) } 47 | iconScaleAnimation.timingFunctions = [ 48 | TimingFunctions.values[3], 49 | TimingFunctions.values[0], 50 | TimingFunctions.values[0] 51 | ] 52 | iconScaleAnimation.calculationMode = kCAAnimationCubic 53 | iconScaleAnimation.duration = duration 54 | iconScaleAnimation.beginTime = beginTime 55 | 56 | if reversed { 57 | iconScaleAnimation.values?.reverse() 58 | iconScaleAnimation.keyTimes?.reverse() 59 | iconScaleAnimation.timingFunctions?.reverse() 60 | } 61 | layer.add(iconScaleAnimation, forKey: "scale") 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /FluidTabBarController/Animation/LabelAnimator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LabelAnimator.swift 3 | // FluidTabBarController 4 | // 5 | // Created by Hubert Kuczyński on 19/07/2018. 6 | // Copyright © 2018 10Clouds Sp. z o.o. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | // 26 | 27 | import UIKit 28 | 29 | final class LabelAnimator { 30 | 31 | // MARK: Private properties 32 | 33 | private let layer: CALayer 34 | 35 | // MARK: Initializers 36 | 37 | init(layer: CALayer) { 38 | self.layer = layer 39 | } 40 | 41 | // MARK: Public methods 42 | 43 | func animatePosition(beginTime: CFTimeInterval, duration: CFTimeInterval, toValue: CGFloat) { 44 | let animation = CAKeyframeAnimation(keyPath: "position.y") 45 | let startValue = layer.position.y 46 | let easeIn = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn) 47 | let easeOut = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut) 48 | animation.timingFunctions = [easeOut, easeIn, easeOut] 49 | animation.values = [startValue, toValue - toValue * 0.2, toValue + toValue * 0.1, toValue] 50 | animation.fillMode = kCAFillModeBackwards 51 | animation.beginTime = beginTime 52 | animation.duration = duration 53 | 54 | layer.add(animation, forKey: "position.y") 55 | layer.position.y = toValue 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /FluidTabBarController/Animation/Layers/CurveLayer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CurveLayer.swift 3 | // FluidTabBarController 4 | // 5 | // Created by Hubert Kuczyński on 11/07/2018. 6 | // Copyright © 2018 10Clouds Sp. z o.o. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | // 26 | 27 | import UIKit 28 | 29 | final class CurveLayer: CAShapeLayer { 30 | 31 | // MARK: Public methods 32 | 33 | func animateShow(beginTime: CFTimeInterval, duration: CFTimeInterval) { 34 | let curveScaleAnimation = CAKeyframeAnimation(keyPath: "transform.scale") 35 | curveScaleAnimation.values = [0.0, 1.2, 0.9, 1.0] 36 | curveScaleAnimation.keyTimes = [0.0, 1.4 / 4.0, 2.9 / 4.0, 1.0].map { NSNumber(value: $0) } 37 | curveScaleAnimation.beginTime = beginTime 38 | curveScaleAnimation.duration = duration 39 | curveScaleAnimation.fillMode = kCAFillModeBackwards 40 | transform = CATransform3DIdentity 41 | add(curveScaleAnimation, forKey: "scale_up") 42 | } 43 | 44 | func animateHide(beginTime: CFTimeInterval, duration: CFTimeInterval) { 45 | let curveScaleAnimation = CAKeyframeAnimation(keyPath: "transform.scale") 46 | curveScaleAnimation.values = [1.0, 1.2, 0.0] 47 | curveScaleAnimation.keyTimes = [0.0, 1.4 / 4.0, 1.0].map { NSNumber(value: $0) } 48 | curveScaleAnimation.duration = duration 49 | curveScaleAnimation.fillMode = kCAFillModeBackwards 50 | transform = CATransform3DMakeScale(0, 0, 0) 51 | add(curveScaleAnimation, forKey: "scale_down") 52 | } 53 | 54 | func updatePath(centerOffset: CGFloat) { 55 | let path = UIBezierPath() 56 | path.move(to: CGPoint(x: bounds.minX, y: bounds.maxY)) 57 | 58 | let topOffset: CGFloat = bounds.width / 3.3 59 | let bottomOffset: CGFloat = bounds.width / 3.5 60 | 61 | path.addCurve( 62 | to: CGPoint(x: bounds.midX, y: bounds.minY), 63 | controlPoint1: CGPoint(x: bounds.minX + bottomOffset, y: bounds.maxY), 64 | controlPoint2: CGPoint(x: bounds.midX - topOffset, y: bounds.minY) 65 | ) 66 | 67 | path.addCurve( 68 | to: CGPoint(x: bounds.maxX, y: bounds.maxY), 69 | controlPoint1: CGPoint(x: bounds.midX + topOffset, y: bounds.minY), 70 | controlPoint2: CGPoint(x: bounds.maxX - bottomOffset, y: bounds.maxY) 71 | ) 72 | 73 | path.addLine(to: CGPoint(x: bounds.minX, y: bounds.maxY)) 74 | self.path = path.cgPath 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /FluidTabBarController/Animation/Layers/StretchyCircleLayer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StretchyCircleLayer.swift 3 | // FluidTabBarController 4 | // 5 | // Created by Hubert Kuczyński on 12/07/2018. 6 | // Copyright © 2018 10Clouds Sp. z o.o. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | // 26 | 27 | import UIKit 28 | 29 | final class StretchyCircleLayer: CAShapeLayer { 30 | 31 | // MARK: Public properties 32 | 33 | override var frame: CGRect { 34 | didSet { 35 | path = UIBezierPath(roundedRect: bounds, cornerRadius: radius).cgPath 36 | } 37 | } 38 | 39 | var movementDuration: CFTimeInterval = 2.5 40 | 41 | // MARK: Private properties 42 | 43 | private var radius: CGFloat { 44 | return bounds.size.width / 2.0 45 | } 46 | 47 | private var yOffsetMax: CGFloat { 48 | return bounds.size.width * 1.3 49 | } 50 | 51 | private var displayLink: CADisplayLink? 52 | private var startTime: CFAbsoluteTime? 53 | 54 | private let yOffset: CGFloat = 30.0 55 | 56 | private let timingFunctions: [CAMediaTimingFunction] = [ 57 | TimingFunctions.values[0], 58 | TimingFunctions.values[2], 59 | TimingFunctions.values[1], 60 | TimingFunctions.values[1], 61 | TimingFunctions.values[1] 62 | ] 63 | 64 | // MARK: Public functions 65 | 66 | func animateShow(beginTime: CFTimeInterval, duration: CFTimeInterval) { 67 | removeAllAnimations() 68 | let scaleAnimation = CAKeyframeAnimation(keyPath: "transform.scale") 69 | scaleAnimation.values = [0.0, 1.0, 23.0 / 52.0, 57.0 / 52.0, 49.0 / 52.0, 1.0] 70 | scaleAnimation.keyTimes = [0, 7.0 / 24.0, 11.0 / 24.0, 18.0 / 24.0, 21.0 / 24.0, 1.0].map { NSNumber(value: $0) } 71 | scaleAnimation.duration = duration 72 | scaleAnimation.beginTime = beginTime 73 | scaleAnimation.timingFunctions = timingFunctions 74 | add(scaleAnimation, forKey: "show") 75 | } 76 | 77 | func animateHide(beginTime: CFTimeInterval, duration: CFTimeInterval) { 78 | removeAllAnimations() 79 | let scaleAnimation = CAKeyframeAnimation(keyPath: "transform.scale") 80 | scaleAnimation.values = [1.0, 49.0 / 52.0, 59.0 / 52.0, 18.0 / 52.0, 1.0, 0.0] 81 | scaleAnimation.keyTimes = [0, 6.0 / 60.0, 12.0 / 60.0, 37.0 / 60.0, 47.0 / 60.0, 1].map { NSNumber(value: $0) } 82 | scaleAnimation.duration = duration 83 | scaleAnimation.beginTime = beginTime 84 | scaleAnimation.fillMode = kCAFillModeForwards 85 | scaleAnimation.isRemovedOnCompletion = false 86 | scaleAnimation.timingFunctions = timingFunctions 87 | add(scaleAnimation, forKey: "hide") 88 | } 89 | 90 | func animateMovement() { 91 | displayLink = CADisplayLink(target: self, selector: #selector(handleMovement(displayLink:))) 92 | startTime = CFAbsoluteTimeGetCurrent() 93 | displayLink?.add(to: RunLoop.main, forMode: RunLoopMode.commonModes) 94 | } 95 | 96 | // MARK: Private functions 97 | 98 | private func invalidateDisplayLink() { 99 | displayLink?.invalidate() 100 | displayLink = nil 101 | } 102 | 103 | @objc private func handleMovement(displayLink: CADisplayLink) { 104 | guard let startTime = startTime else { 105 | invalidateDisplayLink() 106 | return 107 | } 108 | let percent = CGFloat(CFAbsoluteTimeGetCurrent() - startTime) / CGFloat(movementDuration) 109 | if percent < 1.0 { 110 | let offset = yOffset * sin(percent * CGFloat.pi) 111 | updatePath(withOffset: offset) 112 | } else { 113 | updatePath(withOffset: 0) 114 | invalidateDisplayLink() 115 | } 116 | } 117 | 118 | private func updatePath(withOffset offset: CGFloat) { 119 | let pullDownCenter = CGPoint(x: bounds.size.width / 2.0, y: bounds.size.width / 2.0) 120 | path = stretchyCirclePathWithCenter(center: pullDownCenter, radius: radius, yOffset: offset).cgPath 121 | } 122 | 123 | private func stretchyCirclePathWithCenter(center: CGPoint, radius: CGFloat, yOffset: CGFloat = 0.0) -> UIBezierPath { 124 | guard yOffset != 0 else { 125 | return UIBezierPath(arcCenter: center, radius: radius, startAngle: 0, endAngle: 2.0 * CGFloat.pi, clockwise: true) 126 | } 127 | 128 | let lowerRadius = radius * (1 - yOffset / yOffsetMax) 129 | let yOffsetTop = yOffset / 4 130 | let yOffsetBottom = yOffset / 2.5 131 | let path = UIBezierPath(arcCenter: center, radius: radius, startAngle: CGFloat.pi, endAngle: 0, clockwise: true) 132 | 133 | path.addCurve( 134 | to: CGPoint( 135 | x: center.x + lowerRadius, 136 | y: center.y + yOffset 137 | ), 138 | controlPoint1: CGPoint( 139 | x: center.x + radius, 140 | y: center.y + yOffsetTop 141 | ), 142 | controlPoint2: CGPoint( 143 | x: center.x + lowerRadius, 144 | y: center.y + yOffset - yOffsetBottom 145 | ) 146 | ) 147 | path.addArc( 148 | withCenter: CGPoint( 149 | x: center.x, 150 | y: center.y + yOffset 151 | ), 152 | radius: lowerRadius, 153 | startAngle: 0, 154 | endAngle: CGFloat.pi, 155 | clockwise: true 156 | ) 157 | path.addCurve( 158 | to: CGPoint( 159 | x: center.x - radius, 160 | y: center.y 161 | ), 162 | controlPoint1: CGPoint( 163 | x: center.x - lowerRadius, 164 | y: center.y + yOffset - yOffsetBottom 165 | ), 166 | controlPoint2: CGPoint( 167 | x: center.x - radius, 168 | y: center.y + yOffsetTop 169 | ) 170 | ) 171 | return path 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /FluidTabBarController/Animation/TimingFunctions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TimingFunctions.swift 3 | // FluidTabBarController 4 | // 5 | // Created by Hubert Kuczyński on 17/07/2018. 6 | // Copyright © 2018 10Clouds Sp. z o.o. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | // 26 | 27 | import QuartzCore 28 | 29 | internal struct TimingFunctions { 30 | static let values: [CAMediaTimingFunction] = [ 31 | CAMediaTimingFunction(controlPoints: 0.25, 0, 0.00, 1), 32 | CAMediaTimingFunction(controlPoints: 0.20, 0, 0.80, 1), 33 | CAMediaTimingFunction(controlPoints: 0.42, 0, 0.58, 1), 34 | CAMediaTimingFunction(controlPoints: 0.27, 0, 0.00, 1), 35 | CAMediaTimingFunction(controlPoints: 0.50, 0, 0.50, 1), 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /FluidTabBarController/FluidTabBar.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FluidTabBar.swift 3 | // FluidTabBarController 4 | // 5 | // Created by Vincent Li on 2017/2/8. 6 | // Copyright (c) 2013-2018 ESTabBarController (https://github.com/eggswift/ESTabBarController) 7 | // 8 | // Modified by Hubert Kuczyński on 09/07/2018. 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining a copy 11 | // of this software and associated documentation files (the "Software"), to deal 12 | // in the Software without restriction, including without limitation the rights 13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | // copies of the Software, and to permit persons to whom the Software is 15 | // furnished to do so, subject to the following conditions: 16 | // 17 | // The above copyright notice and this permission notice shall be included in 18 | // all copies or substantial portions of the Software. 19 | // 20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | // THE SOFTWARE. 27 | // 28 | 29 | import UIKit 30 | 31 | final class FluidTabBar: UITabBar { 32 | 33 | // MARK: Public properties 34 | 35 | override var items: [UITabBarItem]? { 36 | didSet { 37 | self.reload() 38 | } 39 | } 40 | 41 | override var barTintColor: UIColor? { 42 | didSet { 43 | updateTopLineColor() 44 | } 45 | } 46 | 47 | weak var tabBarController: UITabBarController? 48 | 49 | // MARK: Private properties 50 | 51 | private var containers = [FluidTabBarItemContainer]() 52 | 53 | private var moreContentView: FluidTabBarItemContentView? = FluidTabBarItemMoreContentView() { 54 | didSet { self.reload() } 55 | } 56 | 57 | // MARK: Initializers 58 | 59 | override init(frame: CGRect) { 60 | super.init(frame: frame) 61 | updateTopLineColor() 62 | isTranslucent = false 63 | configureBackground() 64 | } 65 | 66 | required init?(coder aDecoder: NSCoder) { 67 | fatalError("init(coder:) has not been implemented") 68 | } 69 | 70 | // MARK: Public methods 71 | 72 | override func layoutSubviews() { 73 | super.layoutSubviews() 74 | updateLayout() 75 | } 76 | 77 | override func setItems(_ items: [UITabBarItem]?, animated: Bool) { 78 | super.setItems(items, animated: animated) 79 | reload() 80 | } 81 | 82 | override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { 83 | var superPointInside = super.point(inside: point, with: event) 84 | if !superPointInside { 85 | for container in containers { 86 | if container.point(inside: CGPoint.init(x: point.x - container.frame.origin.x, y: point.y - container.frame.origin.y), with: event) { 87 | superPointInside = true 88 | } 89 | } 90 | } 91 | return superPointInside 92 | } 93 | 94 | // MARK: Private methods 95 | 96 | private func updateTopLineColor() { 97 | let color = barTintColor ?? .white 98 | shadowImage = UIImage.colorForNavBar(color: color) 99 | backgroundImage = UIImage.colorForNavBar(color: color) 100 | } 101 | 102 | private func configureBackground() { 103 | if #available(iOS 13.0, *) { 104 | let tabBarAppearance = UITabBarAppearance() 105 | tabBarAppearance.configureWithDefaultBackground() 106 | tabBarAppearance.backgroundColor = barTintColor ?? .white 107 | UITabBar.appearance().standardAppearance = tabBarAppearance 108 | 109 | if #available(iOS 15.0, *) { 110 | UITabBar.appearance().scrollEdgeAppearance = tabBarAppearance 111 | } 112 | } 113 | } 114 | } 115 | 116 | extension FluidTabBar { 117 | func updateLayout() { 118 | guard let tabBarItems = self.items else { return } 119 | 120 | let tabBarButtons = subviews 121 | .filter { subview -> Bool in 122 | if let cls = NSClassFromString("UITabBarButton") { 123 | return subview.isKind(of: cls) 124 | } 125 | return false 126 | } 127 | .sorted { (subview1, subview2) -> Bool in 128 | return subview1.frame.origin.x < subview2.frame.origin.x 129 | } 130 | 131 | for (idx, item) in tabBarItems.enumerated() { 132 | if let _ = item as? FluidTabBarItem { 133 | tabBarButtons[idx].isHidden = true 134 | } else { 135 | tabBarButtons[idx].isHidden = false 136 | } 137 | if isMoreItem(idx), let _ = moreContentView { 138 | tabBarButtons[idx].isHidden = true 139 | } 140 | } 141 | for (_, container) in containers.enumerated(){ 142 | container.isHidden = false 143 | } 144 | 145 | for (idx, container) in containers.enumerated(){ 146 | container.frame = tabBarButtons[idx].frame 147 | } 148 | } 149 | } 150 | 151 | extension FluidTabBar { 152 | func isMoreItem(_ index: Int) -> Bool { 153 | return FluidTabBarController.isShowingMore(tabBarController) && (index == (items?.count ?? 0) - 1) 154 | } 155 | 156 | private func removeAll() { 157 | for container in containers { 158 | container.removeFromSuperview() 159 | } 160 | containers.removeAll() 161 | } 162 | 163 | private func reload() { 164 | removeAll() 165 | guard let tabBarItems = self.items else { 166 | return 167 | } 168 | for (idx, item) in tabBarItems.enumerated() { 169 | let container = FluidTabBarItemContainer(self, tag: 1000 + idx) 170 | self.addSubview(container) 171 | self.containers.append(container) 172 | 173 | if let item = item as? FluidTabBarItem { 174 | item.contentView.backgroundColor = barTintColor 175 | item.contentView.tintColor = tintColor 176 | container.addSubview(item.contentView) 177 | } 178 | if isMoreItem(idx), let moreContentView = moreContentView { 179 | container.addSubview(moreContentView) 180 | } 181 | } 182 | 183 | self.setNeedsLayout() 184 | } 185 | 186 | @objc internal func highlightAction(_ sender: AnyObject?) { 187 | guard let container = sender as? FluidTabBarItemContainer else { 188 | return 189 | } 190 | let newIndex = max(0, container.tag - 1000) 191 | guard newIndex < items?.count ?? 0, let item = self.items?[newIndex], item.isEnabled == true else { 192 | return 193 | } 194 | 195 | if let item = item as? FluidTabBarItem { 196 | item.contentView.highlight(animated: true, completion: nil) 197 | } else if isMoreItem(newIndex) { 198 | moreContentView?.highlight(animated: true, completion: nil) 199 | } 200 | } 201 | 202 | @objc internal func dehighlightAction(_ sender: AnyObject?) { 203 | guard let container = sender as? FluidTabBarItemContainer else { 204 | return 205 | } 206 | let newIndex = max(0, container.tag - 1000) 207 | guard newIndex < items?.count ?? 0, let item = self.items?[newIndex], item.isEnabled == true else { 208 | return 209 | } 210 | 211 | if let item = item as? FluidTabBarItem { 212 | item.contentView.dehighlight(animated: true, completion: nil) 213 | } else if isMoreItem(newIndex) { 214 | moreContentView?.dehighlight(animated: true, completion: nil) 215 | } 216 | } 217 | 218 | @objc internal func selectAction(_ sender: AnyObject?) { 219 | guard let container = sender as? FluidTabBarItemContainer else { 220 | return 221 | } 222 | 223 | select(itemAtIndex: container.tag - 1000, animated: true) 224 | } 225 | 226 | @objc internal func select(itemAtIndex idx: Int, animated: Bool) { 227 | let newIndex = max(0, idx) 228 | let currentIndex = (selectedItem != nil) ? (items?.index(of: selectedItem!) ?? -1) : -1 229 | guard newIndex < items?.count ?? 0, let item = self.items?[newIndex], item.isEnabled else { 230 | return 231 | } 232 | 233 | if currentIndex != newIndex { 234 | if currentIndex != -1 && currentIndex < items?.count ?? 0 { 235 | if let currentItem = items?[currentIndex] as? FluidTabBarItem { 236 | currentItem.contentView.deselect(animated: animated, completion: nil) 237 | } else if isMoreItem(currentIndex) { 238 | moreContentView?.deselect(animated: animated, completion: nil) 239 | } 240 | } 241 | if let item = item as? FluidTabBarItem { 242 | item.contentView.select(animated: animated, completion: nil) 243 | } else if isMoreItem(newIndex) { 244 | moreContentView?.select(animated: animated, completion: nil) 245 | } 246 | delegate?.tabBar?(self, didSelect: item) 247 | } else if currentIndex == newIndex { 248 | if let item = item as? FluidTabBarItem { 249 | item.contentView.reselect(animated: animated, completion: nil) 250 | } else if self.isMoreItem(newIndex) { 251 | moreContentView?.reselect(animated: animated, completion: nil) 252 | } 253 | 254 | if let tabBarController = tabBarController { 255 | var navVC: UINavigationController? 256 | if let navigationController = tabBarController.selectedViewController as? UINavigationController { 257 | navVC = navigationController 258 | } else if let tabBarController = tabBarController.selectedViewController?.navigationController { 259 | navVC = tabBarController 260 | } 261 | 262 | if let navVC = navVC { 263 | if navVC.viewControllers.contains(tabBarController) { 264 | if navVC.viewControllers.count > 1 && navVC.viewControllers.last != tabBarController { 265 | navVC.popToViewController(tabBarController, animated: true); 266 | } 267 | } else { 268 | if navVC.viewControllers.count > 1 { 269 | navVC.popToRootViewController(animated: animated) 270 | } 271 | } 272 | } 273 | } 274 | } 275 | } 276 | } 277 | 278 | private extension UIImage { 279 | class func colorForNavBar(color: UIColor) -> UIImage { 280 | let rect = CGRect(x: 0.0, y: 0.0, width: 1.0, height: 1.0) 281 | UIGraphicsBeginImageContext(rect.size) 282 | let context = UIGraphicsGetCurrentContext() 283 | context!.setFillColor(color.cgColor) 284 | context!.fill(rect) 285 | let image = UIGraphicsGetImageFromCurrentImageContext() 286 | UIGraphicsEndImageContext() 287 | return image! 288 | } 289 | } 290 | -------------------------------------------------------------------------------- /FluidTabBarController/FluidTabBarController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FluidTabBarController.swift 3 | // FluidTabBarController 4 | // 5 | // Created by Vincent Li on 2017/2/8. 6 | // Copyright (c) 2013-2018 ESTabBarController (https://github.com/eggswift/ESTabBarController) 7 | // 8 | // Modified by Hubert Kuczyński on 09/07/2018. 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining a copy 11 | // of this software and associated documentation files (the "Software"), to deal 12 | // in the Software without restriction, including without limitation the rights 13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | // copies of the Software, and to permit persons to whom the Software is 15 | // furnished to do so, subject to the following conditions: 16 | // 17 | // The above copyright notice and this permission notice shall be included in 18 | // all copies or substantial portions of the Software. 19 | // 20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | // THE SOFTWARE. 27 | // 28 | 29 | import UIKit 30 | 31 | open class FluidTabBarController: UITabBarController { 32 | 33 | // MARK: UIViewController lifecycle 34 | 35 | open override func viewDidLoad() { 36 | super.viewDidLoad() 37 | let tabBar = { () -> FluidTabBar in 38 | let tabBar = FluidTabBar() 39 | tabBar.delegate = self 40 | tabBar.tabBarController = self 41 | return tabBar 42 | }() 43 | self.setValue(tabBar, forKey: "tabBar") 44 | } 45 | 46 | // MARK: Public properties 47 | 48 | open override var selectedViewController: UIViewController? { 49 | willSet { 50 | guard let newValue = newValue else { 51 | return 52 | } 53 | guard !ignoreNextSelection else { 54 | ignoreNextSelection = false 55 | return 56 | } 57 | guard 58 | let tabBar = self.tabBar as? FluidTabBar, 59 | let items = tabBar.items, 60 | let index = viewControllers?.index(of: newValue) 61 | else { return } 62 | let value = (FluidTabBarController.isShowingMore(self) && index > items.count - 1) ? items.count - 1 : index 63 | tabBar.select(itemAtIndex: value, animated: false) 64 | } 65 | } 66 | 67 | open override var selectedIndex: Int { 68 | willSet { 69 | guard !ignoreNextSelection else { 70 | ignoreNextSelection = false 71 | return 72 | } 73 | guard let tabBar = self.tabBar as? FluidTabBar, let items = tabBar.items else { 74 | return 75 | } 76 | let value = (FluidTabBarController.isShowingMore(self) && newValue > items.count - 1) ? items.count - 1 : newValue 77 | tabBar.select(itemAtIndex: value, animated: false) 78 | } 79 | } 80 | 81 | // MARK: Private properties 82 | 83 | fileprivate var ignoreNextSelection = false 84 | 85 | // MARK: Public functions 86 | 87 | open static func isShowingMore(_ tabBarController: UITabBarController?) -> Bool { 88 | return tabBarController?.moreNavigationController.parent != nil 89 | } 90 | 91 | open override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) { 92 | guard let idx = tabBar.items?.index(of: item) else { 93 | return 94 | } 95 | if idx == tabBar.items!.count - 1, FluidTabBarController.isShowingMore(self) { 96 | ignoreNextSelection = true 97 | selectedViewController = moreNavigationController 98 | return; 99 | } 100 | if let vc = viewControllers?[idx] { 101 | ignoreNextSelection = true 102 | selectedIndex = idx 103 | delegate?.tabBarController?(self, didSelect: vc) 104 | } 105 | } 106 | 107 | open override func setViewControllers(_ viewControllers: [UIViewController]?, animated: Bool) { 108 | super.setViewControllers(viewControllers, animated: animated) 109 | // Changing the order of view controllers is not supported 110 | customizableViewControllers = nil 111 | } 112 | 113 | open func tabBar(_ tabBar: UITabBar, shouldSelect item: UITabBarItem) -> Bool { 114 | if let idx = tabBar.items?.index(of: item), let vc = viewControllers?[idx] { 115 | return delegate?.tabBarController?(self, shouldSelect: vc) ?? true 116 | } 117 | return true 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /FluidTabBarController/FluidTabBarItem.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FluidTabBarItem.swift 3 | // FluidTabBarController 4 | // 5 | // Created by Vincent Li on 2017/2/8. 6 | // Copyright (c) 2013-2018 ESTabBarController (https://github.com/eggswift/ESTabBarController) 7 | // 8 | // Modified by Hubert Kuczyński on 09/07/2018. 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining a copy 11 | // of this software and associated documentation files (the "Software"), to deal 12 | // in the Software without restriction, including without limitation the rights 13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | // copies of the Software, and to permit persons to whom the Software is 15 | // furnished to do so, subject to the following conditions: 16 | // 17 | // The above copyright notice and this permission notice shall be included in 18 | // all copies or substantial portions of the Software. 19 | // 20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | // THE SOFTWARE. 27 | // 28 | 29 | import UIKit 30 | 31 | open class FluidTabBarItem: UITabBarItem { 32 | 33 | // MARK: Public properties 34 | 35 | open override var title: String? { 36 | didSet { self.contentView.title = title } 37 | } 38 | 39 | open var textColor: UIColor { 40 | get { return contentView.textColor } 41 | set { contentView.textColor = newValue } 42 | } 43 | 44 | open var highlightTextColor: UIColor { 45 | get { return contentView.highlightTextColor } 46 | set { contentView.highlightTextColor = newValue } 47 | } 48 | 49 | open var imageColor: UIColor { 50 | get { return contentView.imageColor } 51 | set { contentView.imageColor = newValue } 52 | } 53 | 54 | open var highlightImageColor: UIColor { 55 | get { return contentView.highlightImageColor } 56 | set { contentView.highlightImageColor = newValue } 57 | } 58 | 59 | open override var image: UIImage? { 60 | didSet { self.contentView.image = image } 61 | } 62 | 63 | open override var selectedImage: UIImage? { 64 | didSet { self.contentView.selectedImage = selectedImage } 65 | } 66 | 67 | open override var tag: Int { 68 | didSet { self.contentView.tag = tag } 69 | } 70 | 71 | let contentView: FluidTabBarItemContentView 72 | 73 | // MARK: Initializers 74 | 75 | public init( 76 | _ contentView: FluidTabBarItemContentView = FluidTabBarItemContentView(), 77 | title: String? = nil, 78 | image: UIImage? = nil, 79 | selectedImage: UIImage? = nil, 80 | tag: Int = 0 81 | ) { 82 | self.contentView = contentView 83 | super.init() 84 | self.setTitle(title, image: image, selectedImage: selectedImage, tag: tag) 85 | } 86 | 87 | public required init?(coder aDecoder: NSCoder) { 88 | fatalError("init(coder:) has not been implemented") 89 | } 90 | 91 | // MARK: Public methods 92 | 93 | open func setTitle( 94 | _ title: String? = nil, 95 | image: UIImage? = nil, 96 | selectedImage: UIImage? = nil, 97 | tag: Int = 0 98 | ) { 99 | self.title = title 100 | self.image = image 101 | self.selectedImage = selectedImage 102 | self.tag = tag 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /FluidTabBarController/FluidTabBarItemContainer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FluidTabBarItemContainer.swift 3 | // FluidTabBarController 4 | // 5 | // Created by Vincent Li on 2017/2/8. 6 | // Copyright (c) 2013-2018 ESTabBarController (https://github.com/eggswift/ESTabBarController) 7 | // 8 | // Modified by Hubert Kuczyński on 09/07/2018. 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining a copy 11 | // of this software and associated documentation files (the "Software"), to deal 12 | // in the Software without restriction, including without limitation the rights 13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | // copies of the Software, and to permit persons to whom the Software is 15 | // furnished to do so, subject to the following conditions: 16 | // 17 | // The above copyright notice and this permission notice shall be included in 18 | // all copies or substantial portions of the Software. 19 | // 20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | // THE SOFTWARE. 27 | // 28 | 29 | import UIKit 30 | 31 | final class FluidTabBarItemContainer: UIControl { 32 | 33 | // MARK: Initializers 34 | 35 | init(_ target: AnyObject?, tag: Int) { 36 | super.init(frame: .zero) 37 | self.tag = tag 38 | self.addTarget(target, action: #selector(FluidTabBar.selectAction(_:)), for: .touchUpInside) 39 | self.addTarget(target, action: #selector(FluidTabBar.highlightAction(_:)), for: .touchDown) 40 | self.addTarget(target, action: #selector(FluidTabBar.highlightAction(_:)), for: .touchDragEnter) 41 | self.addTarget(target, action: #selector(FluidTabBar.dehighlightAction(_:)), for: .touchDragExit) 42 | self.backgroundColor = .clear 43 | self.isAccessibilityElement = true 44 | } 45 | 46 | required init?(coder aDecoder: NSCoder) { 47 | fatalError("init(coder:) has not been implemented") 48 | } 49 | 50 | // MARK: Public methods 51 | 52 | override func layoutSubviews() { 53 | super.layoutSubviews() 54 | for subview in self.subviews { 55 | if let subview = subview as? FluidTabBarItemContentView { 56 | subview.frame = bounds 57 | subview.updateLayout() 58 | } 59 | } 60 | } 61 | 62 | override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { 63 | var pointInside = super.point(inside: point, with: event) 64 | if !pointInside { 65 | for subview in self.subviews { 66 | pointInside = subview.point( 67 | inside: CGPoint(x: point.x - subview.frame.origin.x, y: point.y - subview.frame.origin.y), 68 | with: event 69 | ) 70 | } 71 | } 72 | return pointInside 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /FluidTabBarController/FluidTabBarItemContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FluidTabBarItemContentView.swift 3 | // FluidTabBarController 4 | // 5 | // Created by Vincent Li on 2017/2/8. 6 | // Copyright (c) 2013-2018 ESTabBarController (https://github.com/eggswift/ESTabBarController) 7 | // 8 | // Modified by Hubert Kuczyński on 09/07/2018. 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining a copy 11 | // of this software and associated documentation files (the "Software"), to deal 12 | // in the Software without restriction, including without limitation the rights 13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | // copies of the Software, and to permit persons to whom the Software is 15 | // furnished to do so, subject to the following conditions: 16 | // 17 | // The above copyright notice and this permission notice shall be included in 18 | // all copies or substantial portions of the Software. 19 | // 20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | // THE SOFTWARE. 27 | // 28 | 29 | import UIKit 30 | 31 | open class FluidTabBarItemContentView: UIView { 32 | 33 | // MARK: Public properties 34 | 35 | /// Performs state change animations 36 | open lazy var animator: FluidTabBarItemAnimator = { 37 | let animation = FluidTabBarItemAnimatorDefault() 38 | animation.contentView = self 39 | return animation 40 | }() 41 | 42 | open var selected = false 43 | 44 | open var highlighted = false 45 | 46 | open var highlightEnabled = true 47 | 48 | /// Icon imageView renderingMode, default is .alwaysTemplate like UITabBarItem 49 | open var renderingMode: UIImageRenderingMode = .alwaysTemplate { 50 | didSet { 51 | self.updateDisplay() 52 | } 53 | } 54 | 55 | /// Sets the color of selected item's image and text 56 | open override var tintColor: UIColor! { 57 | didSet { 58 | highlightTextColor = tintColor 59 | highlightImageColor = tintColor 60 | } 61 | } 62 | 63 | open var image: UIImage? { 64 | didSet { 65 | if !selected { self.updateDisplay() } 66 | } 67 | } 68 | 69 | open var selectedImage: UIImage? { 70 | didSet { 71 | if selected { self.updateDisplay() } 72 | } 73 | } 74 | 75 | open var title: String? { 76 | didSet { 77 | self.titleLabel.text = title 78 | self.updateLayout() 79 | } 80 | } 81 | 82 | /// Text color of not selected item 83 | open var textColor = UIColor(white: 0.57254902, alpha: 1.0) { 84 | didSet { 85 | if !selected { 86 | titleLabel.textColor = textColor 87 | } 88 | } 89 | } 90 | 91 | /// Text color of selected item 92 | open var highlightTextColor = UIColor(red: 0.0, green: 0.47843137, blue: 1.0, alpha: 1.0) { 93 | didSet { 94 | if selected { 95 | titleLabel.textColor = highlightImageColor 96 | } 97 | } 98 | } 99 | 100 | /// Image color of not selected item 101 | open var imageColor = UIColor(white: 0.57254902, alpha: 1.0) { 102 | didSet { 103 | if !selected { 104 | imageView.tintColor = imageColor 105 | } 106 | } 107 | } 108 | 109 | /// Image color of selected item 110 | open var highlightImageColor: UIColor = UIColor(red: 0.0, green: 0.47843137, blue: 1.0, alpha: 1.0) { 111 | didSet { 112 | if selected { 113 | imageView.tintColor = highlightImageColor 114 | } 115 | } 116 | } 117 | 118 | open var imageView: UIImageView = { 119 | let imageView = UIImageView(frame: .zero) 120 | imageView.backgroundColor = .clear 121 | return imageView 122 | }() 123 | 124 | open var titleLabel: UILabel = { 125 | let titleLabel = UILabel(frame: .zero) 126 | titleLabel.backgroundColor = .clear 127 | titleLabel.textColor = .clear 128 | titleLabel.textAlignment = .center 129 | return titleLabel 130 | }() 131 | 132 | internal let imageViewContainer = UIView() 133 | 134 | // MARK: Initializers 135 | 136 | public override init(frame: CGRect) { 137 | super.init(frame: frame) 138 | self.isUserInteractionEnabled = false 139 | 140 | addSubview(imageViewContainer) 141 | imageViewContainer.addSubview(imageView) 142 | addSubview(titleLabel) 143 | } 144 | 145 | public required init?(coder aDecoder: NSCoder) { 146 | fatalError("init(coder:) has not been implemented") 147 | } 148 | 149 | // MARK: Public methods 150 | 151 | /// Updates the contents of titleLabel and imageView depending on the selection 152 | open func updateDisplay() { 153 | imageView.image = (selected ? (selectedImage ?? image) : image)?.withRenderingMode(renderingMode) 154 | imageView.tintColor = selected ? highlightImageColor : imageColor 155 | titleLabel.textColor = selected ? highlightTextColor : textColor 156 | } 157 | 158 | /// Updates the content view layout 159 | open func updateLayout() { 160 | let width = bounds.size.width 161 | let height = bounds.size.height 162 | 163 | imageView.isHidden = imageView.image == nil 164 | titleLabel.isHidden = titleLabel.text == nil 165 | 166 | var imageSize: CGFloat = 0.0 167 | var fontSize: CGFloat = 0.0 168 | var isLandscape = false 169 | if let keyWindow = UIApplication.shared.keyWindow { 170 | isLandscape = keyWindow.bounds.width > keyWindow.bounds.height 171 | } 172 | // is landscape or regular 173 | let isWide = animator.allowsLandscapeIconsArrangement && (isLandscape || traitCollection.horizontalSizeClass == .regular) 174 | if #available(iOS 11.0, *), isWide { 175 | imageSize = UIScreen.main.scale == 3.0 ? 23.0 : 20.0 176 | fontSize = UIScreen.main.scale == 3.0 ? 13.0 : 12.0 177 | } else { 178 | imageSize = 23.0 179 | fontSize = 10.0 180 | } 181 | 182 | if !imageView.isHidden && !titleLabel.isHidden { 183 | titleLabel.font = UIFont.systemFont(ofSize: fontSize) 184 | titleLabel.sizeToFit() 185 | if #available(iOS 11.0, *), isWide { 186 | titleLabel.frame = CGRect( 187 | x: (width - titleLabel.bounds.size.width) / 2.0 + (UIScreen.main.scale == 3.0 ? 14.25 : 12.25), 188 | y: (height - titleLabel.bounds.size.height) / 2.0, 189 | width: titleLabel.bounds.size.width, 190 | height: titleLabel.bounds.size.height 191 | ) 192 | imageViewContainer.frame = CGRect( 193 | x: titleLabel.frame.origin.x - imageSize - (UIScreen.main.scale == 3.0 ? 6.0 : 5.0), 194 | y: (height - imageSize) / 2.0, 195 | width: imageSize, 196 | height: imageSize 197 | ) 198 | } else { 199 | titleLabel.frame = CGRect( 200 | x: (width - titleLabel.bounds.size.width) / 2.0, 201 | y: height - titleLabel.bounds.size.height - 1.0, 202 | width: titleLabel.bounds.size.width, 203 | height: titleLabel.bounds.size.height 204 | ) 205 | imageViewContainer.frame = CGRect( 206 | x: (width - imageSize) / 2.0, 207 | y: (height - imageSize) / 2.0 - 6.0, 208 | width: imageSize, 209 | height: imageSize 210 | ) 211 | } 212 | } else if !imageView.isHidden { 213 | imageViewContainer.frame = CGRect( 214 | x: (width - imageSize) / 2.0, 215 | y: (height - imageSize) / 2.0, 216 | width: imageSize, 217 | height: imageSize 218 | ) 219 | } else if !titleLabel.isHidden { 220 | titleLabel.font = UIFont.systemFont(ofSize: fontSize) 221 | titleLabel.sizeToFit() 222 | titleLabel.frame = CGRect( 223 | x: (width - titleLabel.bounds.size.width) / 2.0, 224 | y: (height - titleLabel.bounds.size.height) / 2.0, 225 | width: titleLabel.bounds.size.width, 226 | height: titleLabel.bounds.size.height 227 | ) 228 | } 229 | 230 | imageView.frame = imageViewContainer.bounds 231 | 232 | animator.initialize() 233 | if selected { 234 | select(animated: false, completion: nil) 235 | } 236 | } 237 | } 238 | 239 | extension FluidTabBarItemContentView { 240 | internal func select(animated: Bool, completion: (() -> ())?) { 241 | selected = true 242 | if highlightEnabled && highlighted { 243 | highlighted = false 244 | animator.dehighlightAnimation(animated: animated, completion: { [weak self] in 245 | self?.updateDisplay() 246 | self?.animator.selectAnimation(animated: animated, completion: completion) 247 | }) 248 | } else { 249 | updateDisplay() 250 | animator.selectAnimation(animated: animated, completion: completion) 251 | } 252 | } 253 | 254 | internal func deselect(animated: Bool, completion: (() -> ())?) { 255 | selected = false 256 | updateDisplay() 257 | animator.deselectAnimation(animated: animated, completion: completion) 258 | } 259 | 260 | internal func reselect(animated: Bool, completion: (() -> ())?) { 261 | if selected == false { 262 | select(animated: animated, completion: completion) 263 | } else { 264 | if highlightEnabled && highlighted { 265 | highlighted = false 266 | animator.dehighlightAnimation(animated: animated, completion: { [weak self] in 267 | self?.animator.reselectAnimation(animated: animated, completion: completion) 268 | }) 269 | } else { 270 | animator.reselectAnimation(animated: animated, completion: completion) 271 | } 272 | } 273 | } 274 | 275 | internal func highlight(animated: Bool, completion: (() -> ())?) { 276 | if !highlightEnabled || highlighted { 277 | return 278 | } 279 | highlighted = true 280 | self.animator.highlightAnimation(animated: animated, completion: completion) 281 | } 282 | 283 | internal func dehighlight(animated: Bool, completion: (() -> ())?) { 284 | if !highlightEnabled || !highlighted { 285 | return 286 | } 287 | highlighted = false 288 | animator.dehighlightAnimation(animated: animated, completion: completion) 289 | } 290 | } 291 | -------------------------------------------------------------------------------- /FluidTabBarController/FluidTabBarMoreItemContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // FluidTabBarModeItemContentView.swift 3 | // FluidTabBarController 4 | // 5 | // Created by Vincent Li on 2017/2/8. 6 | // Copyright (c) 2013-2018 ESTabBarController (https://github.com/eggswift/ESTabBarController) 7 | // 8 | // Modified by Hubert Kuczyński on 25/07/2018. 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining a copy 11 | // of this software and associated documentation files (the "Software"), to deal 12 | // in the Software without restriction, including without limitation the rights 13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | // copies of the Software, and to permit persons to whom the Software is 15 | // furnished to do so, subject to the following conditions: 16 | // 17 | // The above copyright notice and this permission notice shall be included in 18 | // all copies or substantial portions of the Software. 19 | // 20 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | // THE SOFTWARE. 27 | // 28 | 29 | import UIKit 30 | 31 | open class FluidTabBarItemMoreContentView: FluidTabBarItemContentView { 32 | 33 | // MARK: Initializers 34 | 35 | public override init(frame: CGRect) { 36 | super.init(frame: frame) 37 | title = NSLocalizedString("More", bundle: Bundle.main, comment: "") 38 | image = systemMore(highlighted: false) 39 | selectedImage = systemMore(highlighted: true) 40 | } 41 | 42 | public required init?(coder aDecoder: NSCoder) { 43 | fatalError("init(coder:) has not been implemented") 44 | } 45 | 46 | // MARK: Private methods 47 | 48 | public func systemMore(highlighted isHighlighted: Bool) -> UIImage? { 49 | let image = UIImage() 50 | let circleDiameter = isHighlighted ? 5.0 : 4.0 51 | let scale = UIScreen.main.scale 52 | 53 | UIGraphicsBeginImageContextWithOptions(CGSize(width: 32, height: 32), false, scale) 54 | 55 | guard let context = UIGraphicsGetCurrentContext() else { return nil } 56 | 57 | context.setLineWidth(1.0) 58 | for index in 0...2 { 59 | let tmpRect = CGRect(x: 5.0 + 9.0 * Double(index), y: 14.0, width: circleDiameter, height: circleDiameter) 60 | context.addEllipse(in: tmpRect) 61 | image.draw(in: tmpRect) 62 | } 63 | 64 | if isHighlighted { 65 | context.setFillColor(UIColor.blue.cgColor) 66 | context.fillPath() 67 | } else { 68 | context.strokePath() 69 | } 70 | 71 | let newImage = UIGraphicsGetImageFromCurrentImageContext() 72 | UIGraphicsEndImageContext() 73 | return newImage 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 Hubert Kuczyński 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FluidTabBarController 2 | 3 | [![Version](https://img.shields.io/cocoapods/v/FluidTabBarController.svg?style=flat)](https://cocoapods.org/pods/FluidTabBarController) 4 | [![License](https://img.shields.io/cocoapods/l/FluidTabBarController.svg?style=flat)](https://cocoapods.org/pods/FluidTabBarController) 5 | [![Platform](https://img.shields.io/cocoapods/p/FluidTabBarController.svg?style=flat)](https://cocoapods.org/pods/FluidTabBarController) 6 | 7 | 8 | ![Example](https://raw.githubusercontent.com/10clouds/FluidBottomNavigation-ios/master/Static/example.gif) 9 | 10 | ## Example 11 | 12 | To run the example project, clone the repo, and run `pod install` from the Example directory first. 13 | 14 | ## Requirements 15 | 16 | ## Installation 17 | FluidTabBarController doesn't contain any external dependencies. 18 | 19 | It is available through [CocoaPods](https://cocoapods.org). To install 20 | it, simply add the following line to your Podfile: 21 | 22 | ```ruby 23 | pod 'FluidTabBarController' 24 | ``` 25 | 26 | ## Usage 27 | 28 | To use FluidTabBarController in your application first create the `FluidTabBarController` instance: 29 | ``` 30 | let tabBarController = FluidTabBarController() 31 | ``` 32 | Then create items for all of view controllers you want to add to the tab bar controller. You must use `FluidTabBarItem` to make animations work. 33 | 34 | ``` 35 | let mainViewController = MainViewController() 36 | let mainViewControllerItem = FluidTabBarItem(title: "Main", image: UIImage(named: "main"), tag: 0) 37 | mainViewController.tabBarItem = mainViewControllerItem 38 | ``` 39 | Create an array of your view controllers and assign it to the tab bar's `viewControllers` property. 40 | ``` 41 | tabBarController.viewControllers = [mainViewController] 42 | ``` 43 | 44 | 45 | ## Customization 46 | You can change the color of selected item's text by setting the tint color of the tab bar. 47 | `tabBarController.tabBar.tintColor = UIColor.red` 48 | 49 | ![Tint color example](https://raw.githubusercontent.com/10clouds/FluidBottomNavigation-ios/master/Static/tint_color_example.png) 50 | 51 | You can also change the color of icons by specifying `imageColor` and `highlightImageColor` or text color by modifying `textColor` and `highlightTextColor`. 52 | 53 | ## Author 54 | 55 | Hubert Kuczyński, hubert.kuczynski@10clouds.com 56 | 57 | ## License 58 | 59 | FluidTabBarController is available under the MIT license. See the LICENSE file for more info. 60 | -------------------------------------------------------------------------------- /Static/example.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/10clouds/FluidBottomNavigation-ios/13e62068e8f7b361866c60d45bfd05fd89850d43/Static/example.gif -------------------------------------------------------------------------------- /Static/tint_color_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/10clouds/FluidBottomNavigation-ios/13e62068e8f7b361866c60d45bfd05fd89850d43/Static/tint_color_example.png -------------------------------------------------------------------------------- /_Pods.xcodeproj: -------------------------------------------------------------------------------- 1 | Example/Pods/Pods.xcodeproj --------------------------------------------------------------------------------