├── .DS_Store ├── .swift-version ├── CardsStack.podspec ├── CardsStack.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata ├── xcshareddata │ └── xcschemes │ │ └── CardsStack.xcscheme └── xcuserdata │ ├── housing.xcuserdatad │ └── xcschemes │ │ └── xcschememanagement.plist │ └── priteshnandgaonkar.xcuserdatad │ └── xcschemes │ └── xcschememanagement.plist ├── CardsStack ├── CardLayout.swift ├── CardStack.swift ├── CardsManager.swift ├── CardsStack.h └── Info.plist ├── CardsStackTests ├── CardsStackTests.swift └── Info.plist ├── Documentation ├── .DS_Store ├── BasicCardStackInteraction.gif ├── LazyInteraction.gif └── Swift-3-orange.png ├── Example ├── CardsStackExample.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── CardsStackExample.xcscmblueprint │ │ └── xcuserdata │ │ │ └── priteshnandgaonkar.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ ├── housing.xcuserdatad │ │ ├── xcdebugger │ │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ │ ├── CardsStackExample.xcscheme │ │ │ └── xcschememanagement.plist │ │ └── priteshnandgaonkar.xcuserdatad │ │ └── xcschemes │ │ ├── CardsStackExample.xcscheme │ │ └── xcschememanagement.plist ├── CardsStackExample │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── Contents.json │ │ ├── alakazam.imageset │ │ │ ├── Contents.json │ │ │ └── alakazam.png │ │ ├── blastoise.imageset │ │ │ ├── Contents.json │ │ │ └── blastoise.jpeg │ │ ├── bulbasaur.imageset │ │ │ ├── Contents.json │ │ │ └── bulbasaur.jpeg │ │ ├── charizard.imageset │ │ │ ├── Contents.json │ │ │ └── charizard.jpg │ │ ├── charmender.imageset │ │ │ ├── Contents.json │ │ │ └── charmender.jpeg │ │ ├── error.imageset │ │ │ ├── Contents.json │ │ │ └── error.jpeg │ │ ├── evy.imageset │ │ │ ├── Contents.json │ │ │ └── evy.jpeg │ │ ├── gengar.imageset │ │ │ ├── Contents.json │ │ │ └── gengar.jpg │ │ ├── pika.imageset │ │ │ ├── Contents.json │ │ │ └── pika.jpg │ │ ├── pokemon_logo.imageset │ │ │ ├── Contents.json │ │ │ └── pokemon_logo.png │ │ ├── raichu.imageset │ │ │ ├── Contents.json │ │ │ └── raichu.jpeg │ │ └── squirtle.imageset │ │ │ ├── Contents.json │ │ │ └── squirtle.jpeg │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── CardView.swift │ ├── Info.plist │ ├── Pokemon.swift │ └── ViewController.swift ├── CardsStackExampleTests │ ├── CardsStackExampleTests.swift │ └── Info.plist └── CardsStackExampleUITests │ ├── CardsStackExampleUITests.swift │ └── Info.plist ├── LICENSE.md └── README.md /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/priteshrnandgaonkar/CardsStack/71a4d7a39236de96349d1204ac5e5f9f5893ae44/.DS_Store -------------------------------------------------------------------------------- /.swift-version: -------------------------------------------------------------------------------- 1 | 3.0 2 | -------------------------------------------------------------------------------- /CardsStack.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |spec| 2 | spec.name = "CardsStack" 3 | spec.version = "0.2.1" 4 | spec.summary = "UICollectionView turned to awesome set of cards" 5 | spec.homepage = "https://github.com/priteshrnandgaonkar/CardsStack" 6 | spec.license = { type: 'MIT', file: 'LICENSE.md' } 7 | spec.authors = { "Pritesh Nandgaonkar" => 'prit.nandgaonkar@gmail.com' } 8 | spec.social_media_url = "https://twitter.com/prit91" 9 | 10 | spec.platform = :ios, "8.0" 11 | spec.requires_arc = true 12 | spec.source = { git: "https://github.com/priteshrnandgaonkar/CardsStack.git", tag: "0.2.1" } 13 | spec.source_files = "CardsStack/**/*.{h,swift}" 14 | end 15 | -------------------------------------------------------------------------------- /CardsStack.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 8432DC161D96D11400A3A0E2 /* CardsStack.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8432DC0C1D96D11400A3A0E2 /* CardsStack.framework */; }; 11 | 8432DC1B1D96D11400A3A0E2 /* CardsStackTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8432DC1A1D96D11400A3A0E2 /* CardsStackTests.swift */; }; 12 | 8432DC1D1D96D11400A3A0E2 /* CardsStack.h in Headers */ = {isa = PBXBuildFile; fileRef = 8432DC0F1D96D11400A3A0E2 /* CardsStack.h */; settings = {ATTRIBUTES = (Public, ); }; }; 13 | 8432DC291D96D18900A3A0E2 /* CardLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8432DC261D96D18900A3A0E2 /* CardLayout.swift */; }; 14 | 8432DC2A1D96D18900A3A0E2 /* CardsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8432DC271D96D18900A3A0E2 /* CardsManager.swift */; }; 15 | 8432DC2B1D96D18900A3A0E2 /* CardStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8432DC281D96D18900A3A0E2 /* CardStack.swift */; }; 16 | /* End PBXBuildFile section */ 17 | 18 | /* Begin PBXContainerItemProxy section */ 19 | 8432DC171D96D11400A3A0E2 /* PBXContainerItemProxy */ = { 20 | isa = PBXContainerItemProxy; 21 | containerPortal = 8432DC031D96D11400A3A0E2 /* Project object */; 22 | proxyType = 1; 23 | remoteGlobalIDString = 8432DC0B1D96D11400A3A0E2; 24 | remoteInfo = CardsStack; 25 | }; 26 | /* End PBXContainerItemProxy section */ 27 | 28 | /* Begin PBXFileReference section */ 29 | 8432DC0C1D96D11400A3A0E2 /* CardsStack.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = CardsStack.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 30 | 8432DC0F1D96D11400A3A0E2 /* CardsStack.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CardsStack.h; sourceTree = ""; }; 31 | 8432DC101D96D11400A3A0E2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 32 | 8432DC151D96D11400A3A0E2 /* CardsStackTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CardsStackTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 33 | 8432DC1A1D96D11400A3A0E2 /* CardsStackTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardsStackTests.swift; sourceTree = ""; }; 34 | 8432DC1C1D96D11400A3A0E2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 35 | 8432DC261D96D18900A3A0E2 /* CardLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardLayout.swift; sourceTree = ""; }; 36 | 8432DC271D96D18900A3A0E2 /* CardsManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardsManager.swift; sourceTree = ""; }; 37 | 8432DC281D96D18900A3A0E2 /* CardStack.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardStack.swift; sourceTree = ""; }; 38 | /* End PBXFileReference section */ 39 | 40 | /* Begin PBXFrameworksBuildPhase section */ 41 | 8432DC081D96D11400A3A0E2 /* Frameworks */ = { 42 | isa = PBXFrameworksBuildPhase; 43 | buildActionMask = 2147483647; 44 | files = ( 45 | ); 46 | runOnlyForDeploymentPostprocessing = 0; 47 | }; 48 | 8432DC121D96D11400A3A0E2 /* Frameworks */ = { 49 | isa = PBXFrameworksBuildPhase; 50 | buildActionMask = 2147483647; 51 | files = ( 52 | 8432DC161D96D11400A3A0E2 /* CardsStack.framework in Frameworks */, 53 | ); 54 | runOnlyForDeploymentPostprocessing = 0; 55 | }; 56 | /* End PBXFrameworksBuildPhase section */ 57 | 58 | /* Begin PBXGroup section */ 59 | 8432DC021D96D11400A3A0E2 = { 60 | isa = PBXGroup; 61 | children = ( 62 | 8432DC0E1D96D11400A3A0E2 /* CardStack */, 63 | 8432DC191D96D11400A3A0E2 /* CardsStackTests */, 64 | 8432DC0D1D96D11400A3A0E2 /* Products */, 65 | ); 66 | sourceTree = ""; 67 | }; 68 | 8432DC0D1D96D11400A3A0E2 /* Products */ = { 69 | isa = PBXGroup; 70 | children = ( 71 | 8432DC0C1D96D11400A3A0E2 /* CardsStack.framework */, 72 | 8432DC151D96D11400A3A0E2 /* CardsStackTests.xctest */, 73 | ); 74 | name = Products; 75 | sourceTree = ""; 76 | }; 77 | 8432DC0E1D96D11400A3A0E2 /* CardStack */ = { 78 | isa = PBXGroup; 79 | children = ( 80 | 8432DC0F1D96D11400A3A0E2 /* CardsStack.h */, 81 | 8432DC261D96D18900A3A0E2 /* CardLayout.swift */, 82 | 8432DC271D96D18900A3A0E2 /* CardsManager.swift */, 83 | 8432DC281D96D18900A3A0E2 /* CardStack.swift */, 84 | 8432DC101D96D11400A3A0E2 /* Info.plist */, 85 | ); 86 | name = CardStack; 87 | path = CardsStack; 88 | sourceTree = ""; 89 | }; 90 | 8432DC191D96D11400A3A0E2 /* CardsStackTests */ = { 91 | isa = PBXGroup; 92 | children = ( 93 | 8432DC1A1D96D11400A3A0E2 /* CardsStackTests.swift */, 94 | 8432DC1C1D96D11400A3A0E2 /* Info.plist */, 95 | ); 96 | path = CardsStackTests; 97 | sourceTree = ""; 98 | }; 99 | /* End PBXGroup section */ 100 | 101 | /* Begin PBXHeadersBuildPhase section */ 102 | 8432DC091D96D11400A3A0E2 /* Headers */ = { 103 | isa = PBXHeadersBuildPhase; 104 | buildActionMask = 2147483647; 105 | files = ( 106 | 8432DC1D1D96D11400A3A0E2 /* CardsStack.h in Headers */, 107 | ); 108 | runOnlyForDeploymentPostprocessing = 0; 109 | }; 110 | /* End PBXHeadersBuildPhase section */ 111 | 112 | /* Begin PBXNativeTarget section */ 113 | 8432DC0B1D96D11400A3A0E2 /* CardsStack */ = { 114 | isa = PBXNativeTarget; 115 | buildConfigurationList = 8432DC201D96D11400A3A0E2 /* Build configuration list for PBXNativeTarget "CardsStack" */; 116 | buildPhases = ( 117 | 8432DC071D96D11400A3A0E2 /* Sources */, 118 | 8432DC081D96D11400A3A0E2 /* Frameworks */, 119 | 8432DC091D96D11400A3A0E2 /* Headers */, 120 | 8432DC0A1D96D11400A3A0E2 /* Resources */, 121 | ); 122 | buildRules = ( 123 | ); 124 | dependencies = ( 125 | ); 126 | name = CardsStack; 127 | productName = CardsStack; 128 | productReference = 8432DC0C1D96D11400A3A0E2 /* CardsStack.framework */; 129 | productType = "com.apple.product-type.framework"; 130 | }; 131 | 8432DC141D96D11400A3A0E2 /* CardsStackTests */ = { 132 | isa = PBXNativeTarget; 133 | buildConfigurationList = 8432DC231D96D11400A3A0E2 /* Build configuration list for PBXNativeTarget "CardsStackTests" */; 134 | buildPhases = ( 135 | 8432DC111D96D11400A3A0E2 /* Sources */, 136 | 8432DC121D96D11400A3A0E2 /* Frameworks */, 137 | 8432DC131D96D11400A3A0E2 /* Resources */, 138 | ); 139 | buildRules = ( 140 | ); 141 | dependencies = ( 142 | 8432DC181D96D11400A3A0E2 /* PBXTargetDependency */, 143 | ); 144 | name = CardsStackTests; 145 | productName = CardsStackTests; 146 | productReference = 8432DC151D96D11400A3A0E2 /* CardsStackTests.xctest */; 147 | productType = "com.apple.product-type.bundle.unit-test"; 148 | }; 149 | /* End PBXNativeTarget section */ 150 | 151 | /* Begin PBXProject section */ 152 | 8432DC031D96D11400A3A0E2 /* Project object */ = { 153 | isa = PBXProject; 154 | attributes = { 155 | LastSwiftUpdateCheck = 0800; 156 | LastUpgradeCheck = 0800; 157 | ORGANIZATIONNAME = Pritesh; 158 | TargetAttributes = { 159 | 8432DC0B1D96D11400A3A0E2 = { 160 | CreatedOnToolsVersion = 8.0; 161 | DevelopmentTeam = TB2282VDLT; 162 | LastSwiftMigration = 0800; 163 | ProvisioningStyle = Automatic; 164 | }; 165 | 8432DC141D96D11400A3A0E2 = { 166 | CreatedOnToolsVersion = 8.0; 167 | DevelopmentTeam = TB2282VDLT; 168 | ProvisioningStyle = Automatic; 169 | }; 170 | }; 171 | }; 172 | buildConfigurationList = 8432DC061D96D11400A3A0E2 /* Build configuration list for PBXProject "CardsStack" */; 173 | compatibilityVersion = "Xcode 3.2"; 174 | developmentRegion = English; 175 | hasScannedForEncodings = 0; 176 | knownRegions = ( 177 | en, 178 | ); 179 | mainGroup = 8432DC021D96D11400A3A0E2; 180 | productRefGroup = 8432DC0D1D96D11400A3A0E2 /* Products */; 181 | projectDirPath = ""; 182 | projectRoot = ""; 183 | targets = ( 184 | 8432DC0B1D96D11400A3A0E2 /* CardsStack */, 185 | 8432DC141D96D11400A3A0E2 /* CardsStackTests */, 186 | ); 187 | }; 188 | /* End PBXProject section */ 189 | 190 | /* Begin PBXResourcesBuildPhase section */ 191 | 8432DC0A1D96D11400A3A0E2 /* Resources */ = { 192 | isa = PBXResourcesBuildPhase; 193 | buildActionMask = 2147483647; 194 | files = ( 195 | ); 196 | runOnlyForDeploymentPostprocessing = 0; 197 | }; 198 | 8432DC131D96D11400A3A0E2 /* Resources */ = { 199 | isa = PBXResourcesBuildPhase; 200 | buildActionMask = 2147483647; 201 | files = ( 202 | ); 203 | runOnlyForDeploymentPostprocessing = 0; 204 | }; 205 | /* End PBXResourcesBuildPhase section */ 206 | 207 | /* Begin PBXSourcesBuildPhase section */ 208 | 8432DC071D96D11400A3A0E2 /* Sources */ = { 209 | isa = PBXSourcesBuildPhase; 210 | buildActionMask = 2147483647; 211 | files = ( 212 | 8432DC2B1D96D18900A3A0E2 /* CardStack.swift in Sources */, 213 | 8432DC291D96D18900A3A0E2 /* CardLayout.swift in Sources */, 214 | 8432DC2A1D96D18900A3A0E2 /* CardsManager.swift in Sources */, 215 | ); 216 | runOnlyForDeploymentPostprocessing = 0; 217 | }; 218 | 8432DC111D96D11400A3A0E2 /* Sources */ = { 219 | isa = PBXSourcesBuildPhase; 220 | buildActionMask = 2147483647; 221 | files = ( 222 | 8432DC1B1D96D11400A3A0E2 /* CardsStackTests.swift in Sources */, 223 | ); 224 | runOnlyForDeploymentPostprocessing = 0; 225 | }; 226 | /* End PBXSourcesBuildPhase section */ 227 | 228 | /* Begin PBXTargetDependency section */ 229 | 8432DC181D96D11400A3A0E2 /* PBXTargetDependency */ = { 230 | isa = PBXTargetDependency; 231 | target = 8432DC0B1D96D11400A3A0E2 /* CardsStack */; 232 | targetProxy = 8432DC171D96D11400A3A0E2 /* PBXContainerItemProxy */; 233 | }; 234 | /* End PBXTargetDependency section */ 235 | 236 | /* Begin XCBuildConfiguration section */ 237 | 8432DC1E1D96D11400A3A0E2 /* Debug */ = { 238 | isa = XCBuildConfiguration; 239 | buildSettings = { 240 | ALWAYS_SEARCH_USER_PATHS = NO; 241 | CLANG_ANALYZER_NONNULL = YES; 242 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 243 | CLANG_CXX_LIBRARY = "libc++"; 244 | CLANG_ENABLE_MODULES = YES; 245 | CLANG_ENABLE_OBJC_ARC = YES; 246 | CLANG_WARN_BOOL_CONVERSION = YES; 247 | CLANG_WARN_CONSTANT_CONVERSION = YES; 248 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 249 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 250 | CLANG_WARN_EMPTY_BODY = YES; 251 | CLANG_WARN_ENUM_CONVERSION = YES; 252 | CLANG_WARN_INFINITE_RECURSION = YES; 253 | CLANG_WARN_INT_CONVERSION = YES; 254 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 255 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 256 | CLANG_WARN_UNREACHABLE_CODE = YES; 257 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 258 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 259 | COPY_PHASE_STRIP = NO; 260 | CURRENT_PROJECT_VERSION = 1; 261 | DEBUG_INFORMATION_FORMAT = dwarf; 262 | ENABLE_STRICT_OBJC_MSGSEND = YES; 263 | ENABLE_TESTABILITY = YES; 264 | GCC_C_LANGUAGE_STANDARD = gnu99; 265 | GCC_DYNAMIC_NO_PIC = NO; 266 | GCC_NO_COMMON_BLOCKS = YES; 267 | GCC_OPTIMIZATION_LEVEL = 0; 268 | GCC_PREPROCESSOR_DEFINITIONS = ( 269 | "DEBUG=1", 270 | "$(inherited)", 271 | ); 272 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 273 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 274 | GCC_WARN_UNDECLARED_SELECTOR = YES; 275 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 276 | GCC_WARN_UNUSED_FUNCTION = YES; 277 | GCC_WARN_UNUSED_VARIABLE = YES; 278 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 279 | MTL_ENABLE_DEBUG_INFO = YES; 280 | ONLY_ACTIVE_ARCH = YES; 281 | SDKROOT = iphoneos; 282 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 283 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 284 | SWIFT_VERSION = 3.0; 285 | TARGETED_DEVICE_FAMILY = "1,2"; 286 | VERSIONING_SYSTEM = "apple-generic"; 287 | VERSION_INFO_PREFIX = ""; 288 | }; 289 | name = Debug; 290 | }; 291 | 8432DC1F1D96D11400A3A0E2 /* Release */ = { 292 | isa = XCBuildConfiguration; 293 | buildSettings = { 294 | ALWAYS_SEARCH_USER_PATHS = NO; 295 | CLANG_ANALYZER_NONNULL = YES; 296 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 297 | CLANG_CXX_LIBRARY = "libc++"; 298 | CLANG_ENABLE_MODULES = YES; 299 | CLANG_ENABLE_OBJC_ARC = YES; 300 | CLANG_WARN_BOOL_CONVERSION = YES; 301 | CLANG_WARN_CONSTANT_CONVERSION = YES; 302 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 303 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 304 | CLANG_WARN_EMPTY_BODY = YES; 305 | CLANG_WARN_ENUM_CONVERSION = YES; 306 | CLANG_WARN_INFINITE_RECURSION = YES; 307 | CLANG_WARN_INT_CONVERSION = YES; 308 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 309 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 310 | CLANG_WARN_UNREACHABLE_CODE = YES; 311 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 312 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 313 | COPY_PHASE_STRIP = NO; 314 | CURRENT_PROJECT_VERSION = 1; 315 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 316 | ENABLE_NS_ASSERTIONS = NO; 317 | ENABLE_STRICT_OBJC_MSGSEND = YES; 318 | GCC_C_LANGUAGE_STANDARD = gnu99; 319 | GCC_NO_COMMON_BLOCKS = YES; 320 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 321 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 322 | GCC_WARN_UNDECLARED_SELECTOR = YES; 323 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 324 | GCC_WARN_UNUSED_FUNCTION = YES; 325 | GCC_WARN_UNUSED_VARIABLE = YES; 326 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 327 | MTL_ENABLE_DEBUG_INFO = NO; 328 | SDKROOT = iphoneos; 329 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 330 | SWIFT_VERSION = 3.0; 331 | TARGETED_DEVICE_FAMILY = "1,2"; 332 | VALIDATE_PRODUCT = YES; 333 | VERSIONING_SYSTEM = "apple-generic"; 334 | VERSION_INFO_PREFIX = ""; 335 | }; 336 | name = Release; 337 | }; 338 | 8432DC211D96D11400A3A0E2 /* Debug */ = { 339 | isa = XCBuildConfiguration; 340 | buildSettings = { 341 | CLANG_ENABLE_MODULES = YES; 342 | CODE_SIGN_IDENTITY = ""; 343 | DEFINES_MODULE = YES; 344 | DEVELOPMENT_TEAM = TB2282VDLT; 345 | DYLIB_COMPATIBILITY_VERSION = 1; 346 | DYLIB_CURRENT_VERSION = 1; 347 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 348 | INFOPLIST_FILE = CardsStack/Info.plist; 349 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 350 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 351 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 352 | PRODUCT_BUNDLE_IDENTIFIER = PN.CardsStack; 353 | PRODUCT_NAME = "$(TARGET_NAME)"; 354 | SKIP_INSTALL = YES; 355 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 356 | SWIFT_VERSION = 3.0; 357 | TARGETED_DEVICE_FAMILY = 1; 358 | }; 359 | name = Debug; 360 | }; 361 | 8432DC221D96D11400A3A0E2 /* Release */ = { 362 | isa = XCBuildConfiguration; 363 | buildSettings = { 364 | CLANG_ENABLE_MODULES = YES; 365 | CODE_SIGN_IDENTITY = ""; 366 | DEFINES_MODULE = YES; 367 | DEVELOPMENT_TEAM = TB2282VDLT; 368 | DYLIB_COMPATIBILITY_VERSION = 1; 369 | DYLIB_CURRENT_VERSION = 1; 370 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 371 | INFOPLIST_FILE = CardsStack/Info.plist; 372 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 373 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 374 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 375 | PRODUCT_BUNDLE_IDENTIFIER = PN.CardsStack; 376 | PRODUCT_NAME = "$(TARGET_NAME)"; 377 | SKIP_INSTALL = YES; 378 | SWIFT_VERSION = 3.0; 379 | TARGETED_DEVICE_FAMILY = 1; 380 | }; 381 | name = Release; 382 | }; 383 | 8432DC241D96D11400A3A0E2 /* Debug */ = { 384 | isa = XCBuildConfiguration; 385 | buildSettings = { 386 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 387 | DEVELOPMENT_TEAM = TB2282VDLT; 388 | INFOPLIST_FILE = CardsStackTests/Info.plist; 389 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 390 | PRODUCT_BUNDLE_IDENTIFIER = PN.CardsStackTests; 391 | PRODUCT_NAME = "$(TARGET_NAME)"; 392 | SWIFT_VERSION = 3.0; 393 | }; 394 | name = Debug; 395 | }; 396 | 8432DC251D96D11400A3A0E2 /* Release */ = { 397 | isa = XCBuildConfiguration; 398 | buildSettings = { 399 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 400 | DEVELOPMENT_TEAM = TB2282VDLT; 401 | INFOPLIST_FILE = CardsStackTests/Info.plist; 402 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 403 | PRODUCT_BUNDLE_IDENTIFIER = PN.CardsStackTests; 404 | PRODUCT_NAME = "$(TARGET_NAME)"; 405 | SWIFT_VERSION = 3.0; 406 | }; 407 | name = Release; 408 | }; 409 | /* End XCBuildConfiguration section */ 410 | 411 | /* Begin XCConfigurationList section */ 412 | 8432DC061D96D11400A3A0E2 /* Build configuration list for PBXProject "CardsStack" */ = { 413 | isa = XCConfigurationList; 414 | buildConfigurations = ( 415 | 8432DC1E1D96D11400A3A0E2 /* Debug */, 416 | 8432DC1F1D96D11400A3A0E2 /* Release */, 417 | ); 418 | defaultConfigurationIsVisible = 0; 419 | defaultConfigurationName = Release; 420 | }; 421 | 8432DC201D96D11400A3A0E2 /* Build configuration list for PBXNativeTarget "CardsStack" */ = { 422 | isa = XCConfigurationList; 423 | buildConfigurations = ( 424 | 8432DC211D96D11400A3A0E2 /* Debug */, 425 | 8432DC221D96D11400A3A0E2 /* Release */, 426 | ); 427 | defaultConfigurationIsVisible = 0; 428 | defaultConfigurationName = Release; 429 | }; 430 | 8432DC231D96D11400A3A0E2 /* Build configuration list for PBXNativeTarget "CardsStackTests" */ = { 431 | isa = XCConfigurationList; 432 | buildConfigurations = ( 433 | 8432DC241D96D11400A3A0E2 /* Debug */, 434 | 8432DC251D96D11400A3A0E2 /* Release */, 435 | ); 436 | defaultConfigurationIsVisible = 0; 437 | defaultConfigurationName = Release; 438 | }; 439 | /* End XCConfigurationList section */ 440 | }; 441 | rootObject = 8432DC031D96D11400A3A0E2 /* Project object */; 442 | } 443 | -------------------------------------------------------------------------------- /CardsStack.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /CardsStack.xcodeproj/xcshareddata/xcschemes/CardsStack.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 65 | 71 | 72 | 73 | 74 | 75 | 76 | 82 | 83 | 89 | 90 | 91 | 92 | 94 | 95 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /CardsStack.xcodeproj/xcuserdata/housing.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | CardsStack.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 8432DC0B1D96D11400A3A0E2 16 | 17 | primary 18 | 19 | 20 | 8432DC141D96D11400A3A0E2 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /CardsStack.xcodeproj/xcuserdata/priteshnandgaonkar.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | CardsStack.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 8432DC0B1D96D11400A3A0E2 16 | 17 | primary 18 | 19 | 20 | 8432DC141D96D11400A3A0E2 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /CardsStack/CardLayout.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CardLayout.swift 3 | // DynamicStackOfCards 4 | // 5 | // Created by Pritesh Nandgaonkar on 9/16/16. 6 | // Copyright © 2016 pritesh. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | internal protocol CardLayoutDelegate { 13 | var fractionToMove: Float { get } 14 | var cardState: CardState { get } 15 | var configuration: Configuration { get } 16 | } 17 | 18 | class CardLayout: UICollectionViewLayout { 19 | 20 | var delegate: CardLayoutDelegate! 21 | var contentHeight: CGFloat = 0.0 22 | 23 | var cachedAttributes = [UICollectionViewLayoutAttributes]() 24 | 25 | override init() { 26 | super.init() 27 | } 28 | 29 | required init?(coder aDecoder: NSCoder) { 30 | fatalError("init(coder:) has not been implemented") 31 | } 32 | 33 | override var collectionViewContentSize: CGSize { 34 | let collection = collectionView! 35 | let width = collection.bounds.size.width 36 | let height = contentHeight 37 | 38 | return CGSize(width: width, height: height) 39 | } 40 | 41 | override func prepare() { 42 | cachedAttributes.removeAll() 43 | contentHeight = delegate.cardState == .Expanded ? 0.0 : CGFloat(delegate.configuration.collapsedHeight + delegate.fractionToMove) 44 | 45 | guard let numberOfItems = collectionView?.numberOfItems(inSection: 0) else { 46 | return 47 | } 48 | 49 | for index in 0.. [UICollectionViewLayoutAttributes]? { 63 | 64 | var layoutAttributes = [UICollectionViewLayoutAttributes]() 65 | 66 | for attributes in cachedAttributes { 67 | if attributes.frame.intersects(rect) { 68 | layoutAttributes.append(cachedAttributes[attributes.indexPath.item]) 69 | } 70 | 71 | } 72 | return layoutAttributes 73 | } 74 | 75 | override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool { 76 | return true 77 | } 78 | 79 | override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? { 80 | return cachedAttributes[indexPath.item] 81 | } 82 | 83 | func frameFor(index: Int, cardState: CardState, translation: Float) -> CGRect { 84 | var frame = CGRect(origin: CGPoint(x: CGFloat(delegate.configuration.leftSpacing), y:0), size: CGSize(width: UIScreen.main.bounds.width - CGFloat(delegate.configuration.leftSpacing + delegate.configuration.rightSpacing), height: CGFloat(delegate.configuration.cardHeight))) 85 | var frameOrigin = frame.origin 86 | switch cardState { 87 | case .Expanded: 88 | let val = (delegate.configuration.cardHeight * Float(index)) 89 | frameOrigin.y = CGFloat(Float(delegate.configuration.verticalSpacing * Float(index)) + val) 90 | 91 | case .InTransit: 92 | if index > 0 { 93 | 94 | let collapsedY = delegate.configuration.verticalSpacing + (delegate.configuration.cardOffset * Float(index)) 95 | let finalDistToMove = Swift.abs(((delegate.configuration.verticalSpacing + delegate.configuration.cardHeight) * Float(index)) - collapsedY) 96 | let fract = (finalDistToMove * translation)/(delegate.configuration.expandedHeight - delegate.configuration.collapsedHeight) 97 | let val = CGFloat(delegate.configuration.verticalSpacing + (delegate.configuration.cardOffset * Float(index)) + fract) 98 | frameOrigin.y = val 99 | } 100 | 101 | case .Collapsed: 102 | if index > 0 { 103 | frameOrigin.y = CGFloat(delegate.configuration.verticalSpacing + (delegate.configuration.cardOffset * Float(index))) 104 | } 105 | } 106 | frame.origin = frameOrigin 107 | return frame 108 | } 109 | 110 | } 111 | -------------------------------------------------------------------------------- /CardsStack/CardStack.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CardStack.swift 3 | // DynamicStackOfCards 4 | // 5 | // Created by Pritesh Nandgaonkar on 9/24/16. 6 | // Copyright © 2016 pritesh. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | /// Struct for the UI information related to cards. 13 | public struct Configuration { 14 | 15 | /// Offset(distance between the top of the consecutive cards) between the cards while the cards are in collapsed state 16 | public let cardOffset: Float 17 | 18 | /// Height of the collection view when the cards are in collapsed state 19 | public let collapsedHeight:Float 20 | 21 | /// Height of the collection view when the cards are in expanded state 22 | public let expandedHeight:Float 23 | 24 | /// Height of the cards 25 | public let cardHeight: Float 26 | 27 | /// The minimum threshold required for the cards to be dragged down when the cards are in expanded state 28 | public let downwardThreshold: Float 29 | 30 | /// The minimum threshold required for the cards to be dragged up when the cards are in collapsed state 31 | public let upwardThreshold: Float 32 | 33 | /// Vertical Spacing between the cards while the cards are in expanded state 34 | public let verticalSpacing: Float 35 | 36 | /// Leading space for the cards 37 | public let leftSpacing: Float 38 | 39 | /// Trailing space for the cards 40 | public let rightSpacing: Float 41 | 42 | 43 | /// init 44 | /// 45 | /// - parameter cardOffset: Offset(distance between the top of the consecutive cards) between the cards while the cards are in collapsed state 46 | /// - parameter collapsedHeight: Height of the collection view when the cards are in collapsed state 47 | /// - parameter expandedHeight: Height of the collection view when the cards are in expanded state 48 | /// - parameter cardHeight: Height of the cards 49 | /// - parameter downwardThreshold: The minimum threshold required for the cards to be dragged down when the cards are in expanded state. Its an optional field. Default value is 20 50 | /// - parameter upwardThreshold: The minimum threshold required for the cards to be dragged up when the cards are in collapsed state. Its an optional field. Default value is 20 51 | /// - parameter leftSpacing: Leading space for the cards. Its not a required field, default value is 8 52 | /// - parameter rightSpacing: Trailing space for the cards. Optional field, default value is 8 53 | /// - parameter verticalSpacing: Leading space for the cards. Optional field, default value is 8 54 | /// 55 | /// - returns: Configuration 56 | public init(cardOffset: Float, collapsedHeight: Float, expandedHeight: Float, cardHeight: Float, downwardThreshold: Float = 20, upwardThreshold: Float = 20, leftSpacing: Float = 8.0, rightSpacing: Float = 8.0, verticalSpacing: Float = 8.0) { 57 | self.cardOffset = cardOffset 58 | self.collapsedHeight = collapsedHeight 59 | self.expandedHeight = expandedHeight 60 | self.downwardThreshold = downwardThreshold 61 | self.upwardThreshold = upwardThreshold 62 | self.cardHeight = cardHeight 63 | self.verticalSpacing = verticalSpacing 64 | self.leftSpacing = leftSpacing 65 | self.rightSpacing = rightSpacing 66 | } 67 | } 68 | 69 | /// Enum for decribing the state of the cards 70 | @objc public enum CardsPosition: Int { 71 | /// Case when the cards are collapsed 72 | case Collapsed 73 | 74 | /// Case when the cards are expanded 75 | case Expanded 76 | } 77 | 78 | /// Delegate to get hooks to interaction over cards 79 | @objc public protocol CardsManagerDelegate { 80 | 81 | @objc optional func cardsPositionChangedTo(position: CardsPosition) 82 | @objc optional func tappedOnCardsStack(cardsCollectionView: UICollectionView) 83 | @objc optional func cardsCollectionView(_ cardsCollectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) 84 | @objc optional func cardsCollectionView(_ cardsCollectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) 85 | } 86 | 87 | /// Class for initialising stack of cards 88 | public class CardStack { 89 | 90 | public weak var delegate: CardsManagerDelegate? = nil { 91 | didSet { 92 | cardsManager.delegate = delegate 93 | } 94 | } 95 | internal var cardsManager = CardsManager() 96 | 97 | internal(set) var position: CardsPosition 98 | 99 | /// init 100 | /// uses config = Configuration(cardOffset: 40, collapsedHeight: 200, expandedHeight: 500, cardHeight: 200, downwardThreshold: 20, upwardThreshold: 20) in 101 | /// init(cardsState: .Collapsed, configuration: config, collectionView: nil, collectionViewHeight: nil) 102 | /// - returns: CardStack 103 | public convenience init() { 104 | let configuration = Configuration(cardOffset: 40, collapsedHeight: 200, expandedHeight: 500, cardHeight: 200, downwardThreshold: 20, upwardThreshold: 20) 105 | 106 | self.init(cardsState: .Collapsed, configuration: configuration, collectionView: nil, collectionViewHeight: nil) 107 | } 108 | 109 | /// init 110 | /// 111 | /// - parameter cardsState: Initial state of the cards 112 | /// - parameter configuration: Instance of the Configuration, which holds the UI related information 113 | /// - parameter collectionView: UICollectionView 114 | /// - parameter collectionViewHeight: NSLayoutConstraint, height constraint of the collectionview 115 | /// 116 | /// - returns: CardStack 117 | public init(cardsState: CardsPosition, configuration: Configuration, collectionView: UICollectionView?, collectionViewHeight: NSLayoutConstraint?) { 118 | 119 | position = cardsState 120 | cardsManager = CardsManager(cardState: cardsState, configuration: configuration, collectionView: collectionView, heightConstraint: collectionViewHeight) 121 | cardsManager.cardsDelegate = self 122 | } 123 | 124 | /// changeCardsPosition(to position: CardsPosition) 125 | /// This function can be called on CardStack to change the state of cardsStack. It can be used to programmatically change the states of the cards stack 126 | /// - parameter position: CardsPosition 127 | public func changeCardsPosition(to position: CardsPosition) { 128 | cardsManager.updateView(with: position) 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /CardsStack/CardsManager.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CardsManager.swift 3 | // DynamicStackOfCards 4 | // 5 | // Created by Pritesh Nandgaonkar on 9/24/16. 6 | // Copyright © 2016 pritesh. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | internal enum CardState { 13 | case Expanded 14 | case InTransit 15 | case Collapsed 16 | } 17 | 18 | class CardsManager: NSObject, CardLayoutDelegate { 19 | 20 | var fractionToMove:Float = 0 21 | var cardState: CardState { 22 | didSet { 23 | switch cardState { 24 | case .InTransit: 25 | tapGesture.isEnabled = false 26 | 27 | case .Collapsed: 28 | cardsDelegate?.position = .Collapsed 29 | tapGesture.isEnabled = true 30 | 31 | case .Expanded: 32 | cardsDelegate?.position = .Expanded 33 | tapGesture.isEnabled = false 34 | } 35 | } 36 | } 37 | var configuration: Configuration 38 | 39 | weak var delegate: CardsManagerDelegate? 40 | weak var collectionView: UICollectionView? 41 | weak var cardsCollectionViewHeight: NSLayoutConstraint? 42 | weak var cardsDelegate: CardStack? = nil 43 | 44 | var panGesture = UIPanGestureRecognizer() 45 | var tapGesture = UITapGestureRecognizer() 46 | 47 | var previousTranslation: CGFloat = 0 48 | 49 | convenience override init() { 50 | 51 | let configuration = Configuration(cardOffset: 40, collapsedHeight: 200, expandedHeight: 500, cardHeight: 200, downwardThreshold: 20, upwardThreshold: 20) 52 | 53 | self.init(cardState: .Collapsed, configuration: configuration, collectionView: nil, heightConstraint: nil) 54 | } 55 | 56 | func cardsStateFromCardsPosition(position: CardsPosition) -> CardState { 57 | switch position { 58 | case .Expanded: 59 | return CardState.Expanded 60 | case .Collapsed: 61 | return CardState.Collapsed 62 | } 63 | } 64 | 65 | func cardsPositionFromCardsState(state: CardState) -> CardsPosition? { 66 | switch state { 67 | case .Collapsed: 68 | return CardsPosition.Expanded 69 | case .Expanded: 70 | return CardsPosition.Collapsed 71 | default: 72 | return nil 73 | } 74 | } 75 | 76 | init(cardState: CardsPosition, configuration: Configuration, collectionView: UICollectionView?, heightConstraint: NSLayoutConstraint?) { 77 | 78 | switch cardState { 79 | case .Expanded: 80 | self.cardState = CardState.Expanded 81 | case .Collapsed: 82 | self.cardState = CardState.Collapsed 83 | } 84 | 85 | self.configuration = configuration 86 | cardsCollectionViewHeight = heightConstraint 87 | self.collectionView = collectionView 88 | super.init() 89 | guard let cardsView = self.collectionView else { 90 | return 91 | } 92 | let cardLayout = CardLayout() 93 | cardLayout.delegate = self 94 | cardsView.collectionViewLayout = cardLayout 95 | cardsView.bounces = true 96 | cardsView.alwaysBounceVertical = true 97 | cardsView.delegate = self 98 | 99 | panGesture = UIPanGestureRecognizer(target: self, action:#selector(self.pannedCard)) 100 | tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.tappedCard)) 101 | cardsView.addGestureRecognizer(panGesture) 102 | cardsView.addGestureRecognizer(tapGesture) 103 | panGesture.isEnabled = cardState == .Collapsed 104 | tapGesture.isEnabled = cardState == .Collapsed 105 | } 106 | 107 | func tappedCard(tapGesture: UITapGestureRecognizer) { 108 | guard let cardsCollectionView = collectionView else { 109 | return 110 | } 111 | delegate?.tappedOnCardsStack?(cardsCollectionView: cardsCollectionView) 112 | } 113 | 114 | func pannedCard(panGesture: UIPanGestureRecognizer) { 115 | 116 | guard let collectionView = self.collectionView else { 117 | return 118 | } 119 | let translation = panGesture.translation(in: collectionView.superview!) 120 | collectionView.collectionViewLayout.invalidateLayout() 121 | 122 | let distanceMoved = translation.y 123 | guard let heightConstraint = self.cardsCollectionViewHeight else { 124 | return 125 | } 126 | 127 | switch panGesture.state { 128 | case .changed: 129 | heightConstraint.constant -= distanceMoved 130 | 131 | heightConstraint.constant = Swift.min(heightConstraint.constant, CGFloat(self.configuration.expandedHeight)) 132 | heightConstraint.constant = Swift.max(heightConstraint.constant, CGFloat(self.configuration.collapsedHeight)) 133 | 134 | self.cardState = .InTransit 135 | self.fractionToMove = Float(heightConstraint.constant - CGFloat(self.configuration.collapsedHeight)) 136 | self.collectionView?.isScrollEnabled = false 137 | 138 | self.collectionView?.collectionViewLayout.invalidateLayout() 139 | self.collectionView?.superview?.layoutIfNeeded() 140 | 141 | case .cancelled: 142 | fallthrough 143 | case .ended: 144 | 145 | if self.previousTranslation < 0 { 146 | if heightConstraint.constant > CGFloat(self.configuration.collapsedHeight + self.configuration.upwardThreshold) { 147 | heightConstraint.constant = CGFloat(self.configuration.expandedHeight) 148 | self.cardState = .Expanded 149 | self.panGesture.isEnabled = false 150 | } 151 | else { 152 | heightConstraint.constant = CGFloat(self.configuration.collapsedHeight) 153 | self.cardState = .Collapsed 154 | self.panGesture.isEnabled = true 155 | } 156 | } 157 | else { 158 | if heightConstraint.constant < CGFloat(self.configuration.expandedHeight - self.configuration.downwardThreshold) { 159 | heightConstraint.constant = CGFloat(self.configuration.collapsedHeight) 160 | self.cardState = .Collapsed 161 | self.panGesture.isEnabled = true 162 | } 163 | else { 164 | 165 | heightConstraint.constant = CGFloat(self.configuration.expandedHeight) 166 | self.cardState = .Expanded 167 | self.panGesture.isEnabled = false 168 | } 169 | 170 | } 171 | self.collectionView?.isScrollEnabled = !panGesture.isEnabled 172 | 173 | UIView.animate(withDuration: 0.3, animations: { 174 | self.collectionView?.collectionViewLayout.invalidateLayout() 175 | self.collectionView?.superview?.layoutIfNeeded() 176 | }, completion: { (finished) in 177 | self.triggerStateCallBack() 178 | }) 179 | default: 180 | break 181 | } 182 | 183 | self.previousTranslation = translation.y 184 | self.panGesture.setTranslation(CGPoint.zero, in: self.collectionView?.superview) 185 | } 186 | 187 | func triggerStateCallBack() { 188 | guard let position = cardsPositionFromCardsState(state: cardState) else { 189 | return 190 | } 191 | delegate?.cardsPositionChangedTo?(position: position) 192 | } 193 | 194 | func updateView(with position: CardsPosition) { 195 | var ht:Float = 0.0 196 | cardState = cardsStateFromCardsPosition(position: position) 197 | switch cardState { 198 | case .Collapsed: 199 | ht = configuration.collapsedHeight 200 | 201 | case .Expanded: 202 | ht = configuration.expandedHeight 203 | default: 204 | return 205 | } 206 | 207 | DispatchQueue.main.async { [weak self] in 208 | 209 | guard let weakSelf = self else { 210 | return 211 | } 212 | weakSelf.cardsCollectionViewHeight?.constant = CGFloat(ht) 213 | 214 | UIView.animate(withDuration: 0.3, animations: { 215 | weakSelf.collectionView?.collectionViewLayout.invalidateLayout() 216 | weakSelf.collectionView?.superview?.layoutIfNeeded() 217 | }, completion: { (finished) in 218 | weakSelf.triggerStateCallBack() 219 | }) 220 | } 221 | } 222 | } 223 | 224 | extension CardsManager: UICollectionViewDelegate { 225 | 226 | public func scrollViewDidScroll(_ scrollView: UIScrollView) { 227 | 228 | if scrollView.contentOffset.y < 0 { 229 | panGesture.isEnabled = true 230 | scrollView.isScrollEnabled = false 231 | } 232 | } 233 | 234 | public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { 235 | 236 | delegate?.cardsCollectionView?(collectionView, didSelectItemAt: indexPath) 237 | } 238 | 239 | public func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) { 240 | delegate?.cardsCollectionView?(collectionView, willDisplay: cell, forItemAt: indexPath) 241 | } 242 | } 243 | -------------------------------------------------------------------------------- /CardsStack/CardsStack.h: -------------------------------------------------------------------------------- 1 | // 2 | // CardsStack.h 3 | // CardsStack 4 | // 5 | // Created by Pritesh Nandgaonkar on 9/24/16. 6 | // Copyright © 2016 Pritesh. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for CardsStack. 12 | FOUNDATION_EXPORT double CardsStackVersionNumber; 13 | 14 | //! Project version string for CardsStack. 15 | FOUNDATION_EXPORT const unsigned char CardsStackVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | -------------------------------------------------------------------------------- /CardsStack/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | CardStack 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | FMWK 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /CardsStackTests/CardsStackTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CardsStackTests.swift 3 | // CardsStackTests 4 | // 5 | // Created by Pritesh Nandgaonkar on 9/24/16. 6 | // Copyright © 2016 Pritesh. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import CardsStack 11 | 12 | class CardsStackTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | // Use XCTAssert and related functions to verify your tests produce the correct results. 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measure { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /CardsStackTests/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 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Documentation/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/priteshrnandgaonkar/CardsStack/71a4d7a39236de96349d1204ac5e5f9f5893ae44/Documentation/.DS_Store -------------------------------------------------------------------------------- /Documentation/BasicCardStackInteraction.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/priteshrnandgaonkar/CardsStack/71a4d7a39236de96349d1204ac5e5f9f5893ae44/Documentation/BasicCardStackInteraction.gif -------------------------------------------------------------------------------- /Documentation/LazyInteraction.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/priteshrnandgaonkar/CardsStack/71a4d7a39236de96349d1204ac5e5f9f5893ae44/Documentation/LazyInteraction.gif -------------------------------------------------------------------------------- /Documentation/Swift-3-orange.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/priteshrnandgaonkar/CardsStack/71a4d7a39236de96349d1204ac5e5f9f5893ae44/Documentation/Swift-3-orange.png -------------------------------------------------------------------------------- /Example/CardsStackExample.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 8432DC391D96D1BD00A3A0E2 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8432DC381D96D1BD00A3A0E2 /* AppDelegate.swift */; }; 11 | 8432DC3B1D96D1BD00A3A0E2 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8432DC3A1D96D1BD00A3A0E2 /* ViewController.swift */; }; 12 | 8432DC3E1D96D1BD00A3A0E2 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8432DC3C1D96D1BD00A3A0E2 /* Main.storyboard */; }; 13 | 8432DC401D96D1BD00A3A0E2 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8432DC3F1D96D1BD00A3A0E2 /* Assets.xcassets */; }; 14 | 8432DC431D96D1BD00A3A0E2 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8432DC411D96D1BD00A3A0E2 /* LaunchScreen.storyboard */; }; 15 | 8432DC4E1D96D1BE00A3A0E2 /* CardsStackExampleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8432DC4D1D96D1BE00A3A0E2 /* CardsStackExampleTests.swift */; }; 16 | 8432DC591D96D1BE00A3A0E2 /* CardsStackExampleUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8432DC581D96D1BE00A3A0E2 /* CardsStackExampleUITests.swift */; }; 17 | 8432DC7A1D96D50100A3A0E2 /* CardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8432DC791D96D50100A3A0E2 /* CardView.swift */; }; 18 | 8432DC801D96E6B900A3A0E2 /* Pokemon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8432DC7F1D96E6B900A3A0E2 /* Pokemon.swift */; }; 19 | CAFBE0741D9D57FE00AF931F /* CardsStack.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CAFBE0711D9D57F300AF931F /* CardsStack.framework */; }; 20 | CAFBE0751D9D57FE00AF931F /* CardsStack.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = CAFBE0711D9D57F300AF931F /* CardsStack.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 21 | /* End PBXBuildFile section */ 22 | 23 | /* Begin PBXContainerItemProxy section */ 24 | 8432DC4A1D96D1BE00A3A0E2 /* PBXContainerItemProxy */ = { 25 | isa = PBXContainerItemProxy; 26 | containerPortal = 8432DC2D1D96D1BD00A3A0E2 /* Project object */; 27 | proxyType = 1; 28 | remoteGlobalIDString = 8432DC341D96D1BD00A3A0E2; 29 | remoteInfo = CardsStackExample; 30 | }; 31 | 8432DC551D96D1BE00A3A0E2 /* PBXContainerItemProxy */ = { 32 | isa = PBXContainerItemProxy; 33 | containerPortal = 8432DC2D1D96D1BD00A3A0E2 /* Project object */; 34 | proxyType = 1; 35 | remoteGlobalIDString = 8432DC341D96D1BD00A3A0E2; 36 | remoteInfo = CardsStackExample; 37 | }; 38 | CAFBE0701D9D57F300AF931F /* PBXContainerItemProxy */ = { 39 | isa = PBXContainerItemProxy; 40 | containerPortal = CAFBE06B1D9D57F300AF931F /* CardsStack.xcodeproj */; 41 | proxyType = 2; 42 | remoteGlobalIDString = 8432DC0C1D96D11400A3A0E2; 43 | remoteInfo = CardsStack; 44 | }; 45 | CAFBE0721D9D57F300AF931F /* PBXContainerItemProxy */ = { 46 | isa = PBXContainerItemProxy; 47 | containerPortal = CAFBE06B1D9D57F300AF931F /* CardsStack.xcodeproj */; 48 | proxyType = 2; 49 | remoteGlobalIDString = 8432DC151D96D11400A3A0E2; 50 | remoteInfo = CardsStackTests; 51 | }; 52 | CAFBE0761D9D57FE00AF931F /* PBXContainerItemProxy */ = { 53 | isa = PBXContainerItemProxy; 54 | containerPortal = CAFBE06B1D9D57F300AF931F /* CardsStack.xcodeproj */; 55 | proxyType = 1; 56 | remoteGlobalIDString = 8432DC0B1D96D11400A3A0E2; 57 | remoteInfo = CardsStack; 58 | }; 59 | /* End PBXContainerItemProxy section */ 60 | 61 | /* Begin PBXCopyFilesBuildPhase section */ 62 | 8432DC781D96D2BF00A3A0E2 /* Embed Frameworks */ = { 63 | isa = PBXCopyFilesBuildPhase; 64 | buildActionMask = 2147483647; 65 | dstPath = ""; 66 | dstSubfolderSpec = 10; 67 | files = ( 68 | CAFBE0751D9D57FE00AF931F /* CardsStack.framework in Embed Frameworks */, 69 | ); 70 | name = "Embed Frameworks"; 71 | runOnlyForDeploymentPostprocessing = 0; 72 | }; 73 | /* End PBXCopyFilesBuildPhase section */ 74 | 75 | /* Begin PBXFileReference section */ 76 | 8432DC351D96D1BD00A3A0E2 /* CardsStackExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CardsStackExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 77 | 8432DC381D96D1BD00A3A0E2 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 78 | 8432DC3A1D96D1BD00A3A0E2 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 79 | 8432DC3D1D96D1BD00A3A0E2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 80 | 8432DC3F1D96D1BD00A3A0E2 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 81 | 8432DC421D96D1BD00A3A0E2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 82 | 8432DC441D96D1BD00A3A0E2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 83 | 8432DC491D96D1BE00A3A0E2 /* CardsStackExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CardsStackExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 84 | 8432DC4D1D96D1BE00A3A0E2 /* CardsStackExampleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardsStackExampleTests.swift; sourceTree = ""; }; 85 | 8432DC4F1D96D1BE00A3A0E2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 86 | 8432DC541D96D1BE00A3A0E2 /* CardsStackExampleUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CardsStackExampleUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 87 | 8432DC581D96D1BE00A3A0E2 /* CardsStackExampleUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardsStackExampleUITests.swift; sourceTree = ""; }; 88 | 8432DC5A1D96D1BE00A3A0E2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 89 | 8432DC791D96D50100A3A0E2 /* CardView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardView.swift; sourceTree = ""; }; 90 | 8432DC7F1D96E6B900A3A0E2 /* Pokemon.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Pokemon.swift; sourceTree = ""; }; 91 | CAFBE06B1D9D57F300AF931F /* CardsStack.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = CardsStack.xcodeproj; path = ../CardsStack.xcodeproj; sourceTree = ""; }; 92 | /* End PBXFileReference section */ 93 | 94 | /* Begin PBXFrameworksBuildPhase section */ 95 | 8432DC321D96D1BD00A3A0E2 /* Frameworks */ = { 96 | isa = PBXFrameworksBuildPhase; 97 | buildActionMask = 2147483647; 98 | files = ( 99 | CAFBE0741D9D57FE00AF931F /* CardsStack.framework in Frameworks */, 100 | ); 101 | runOnlyForDeploymentPostprocessing = 0; 102 | }; 103 | 8432DC461D96D1BE00A3A0E2 /* Frameworks */ = { 104 | isa = PBXFrameworksBuildPhase; 105 | buildActionMask = 2147483647; 106 | files = ( 107 | ); 108 | runOnlyForDeploymentPostprocessing = 0; 109 | }; 110 | 8432DC511D96D1BE00A3A0E2 /* Frameworks */ = { 111 | isa = PBXFrameworksBuildPhase; 112 | buildActionMask = 2147483647; 113 | files = ( 114 | ); 115 | runOnlyForDeploymentPostprocessing = 0; 116 | }; 117 | /* End PBXFrameworksBuildPhase section */ 118 | 119 | /* Begin PBXGroup section */ 120 | 8432DC2C1D96D1BD00A3A0E2 = { 121 | isa = PBXGroup; 122 | children = ( 123 | 8432DC371D96D1BD00A3A0E2 /* CardsStackExample */, 124 | 8432DC661D96D1DD00A3A0E2 /* Frameworks */, 125 | 8432DC4C1D96D1BE00A3A0E2 /* CardsStackExampleTests */, 126 | 8432DC571D96D1BE00A3A0E2 /* CardsStackExampleUITests */, 127 | 8432DC361D96D1BD00A3A0E2 /* Products */, 128 | ); 129 | sourceTree = ""; 130 | }; 131 | 8432DC361D96D1BD00A3A0E2 /* Products */ = { 132 | isa = PBXGroup; 133 | children = ( 134 | 8432DC351D96D1BD00A3A0E2 /* CardsStackExample.app */, 135 | 8432DC491D96D1BE00A3A0E2 /* CardsStackExampleTests.xctest */, 136 | 8432DC541D96D1BE00A3A0E2 /* CardsStackExampleUITests.xctest */, 137 | ); 138 | name = Products; 139 | sourceTree = ""; 140 | }; 141 | 8432DC371D96D1BD00A3A0E2 /* CardsStackExample */ = { 142 | isa = PBXGroup; 143 | children = ( 144 | 8432DC381D96D1BD00A3A0E2 /* AppDelegate.swift */, 145 | 8432DC3A1D96D1BD00A3A0E2 /* ViewController.swift */, 146 | 8432DC791D96D50100A3A0E2 /* CardView.swift */, 147 | 8432DC3C1D96D1BD00A3A0E2 /* Main.storyboard */, 148 | 8432DC3F1D96D1BD00A3A0E2 /* Assets.xcassets */, 149 | 8432DC411D96D1BD00A3A0E2 /* LaunchScreen.storyboard */, 150 | 8432DC441D96D1BD00A3A0E2 /* Info.plist */, 151 | 8432DC7F1D96E6B900A3A0E2 /* Pokemon.swift */, 152 | ); 153 | path = CardsStackExample; 154 | sourceTree = ""; 155 | }; 156 | 8432DC4C1D96D1BE00A3A0E2 /* CardsStackExampleTests */ = { 157 | isa = PBXGroup; 158 | children = ( 159 | 8432DC4D1D96D1BE00A3A0E2 /* CardsStackExampleTests.swift */, 160 | 8432DC4F1D96D1BE00A3A0E2 /* Info.plist */, 161 | ); 162 | path = CardsStackExampleTests; 163 | sourceTree = ""; 164 | }; 165 | 8432DC571D96D1BE00A3A0E2 /* CardsStackExampleUITests */ = { 166 | isa = PBXGroup; 167 | children = ( 168 | 8432DC581D96D1BE00A3A0E2 /* CardsStackExampleUITests.swift */, 169 | 8432DC5A1D96D1BE00A3A0E2 /* Info.plist */, 170 | ); 171 | path = CardsStackExampleUITests; 172 | sourceTree = ""; 173 | }; 174 | 8432DC661D96D1DD00A3A0E2 /* Frameworks */ = { 175 | isa = PBXGroup; 176 | children = ( 177 | CAFBE06B1D9D57F300AF931F /* CardsStack.xcodeproj */, 178 | ); 179 | name = Frameworks; 180 | sourceTree = ""; 181 | }; 182 | CAFBE06C1D9D57F300AF931F /* Products */ = { 183 | isa = PBXGroup; 184 | children = ( 185 | CAFBE0711D9D57F300AF931F /* CardsStack.framework */, 186 | CAFBE0731D9D57F300AF931F /* CardsStackTests.xctest */, 187 | ); 188 | name = Products; 189 | sourceTree = ""; 190 | }; 191 | /* End PBXGroup section */ 192 | 193 | /* Begin PBXNativeTarget section */ 194 | 8432DC341D96D1BD00A3A0E2 /* CardsStackExample */ = { 195 | isa = PBXNativeTarget; 196 | buildConfigurationList = 8432DC5D1D96D1BE00A3A0E2 /* Build configuration list for PBXNativeTarget "CardsStackExample" */; 197 | buildPhases = ( 198 | 8432DC311D96D1BD00A3A0E2 /* Sources */, 199 | 8432DC321D96D1BD00A3A0E2 /* Frameworks */, 200 | 8432DC331D96D1BD00A3A0E2 /* Resources */, 201 | 8432DC781D96D2BF00A3A0E2 /* Embed Frameworks */, 202 | ); 203 | buildRules = ( 204 | ); 205 | dependencies = ( 206 | CAFBE0771D9D57FE00AF931F /* PBXTargetDependency */, 207 | ); 208 | name = CardsStackExample; 209 | productName = CardsStackExample; 210 | productReference = 8432DC351D96D1BD00A3A0E2 /* CardsStackExample.app */; 211 | productType = "com.apple.product-type.application"; 212 | }; 213 | 8432DC481D96D1BE00A3A0E2 /* CardsStackExampleTests */ = { 214 | isa = PBXNativeTarget; 215 | buildConfigurationList = 8432DC601D96D1BE00A3A0E2 /* Build configuration list for PBXNativeTarget "CardsStackExampleTests" */; 216 | buildPhases = ( 217 | 8432DC451D96D1BE00A3A0E2 /* Sources */, 218 | 8432DC461D96D1BE00A3A0E2 /* Frameworks */, 219 | 8432DC471D96D1BE00A3A0E2 /* Resources */, 220 | ); 221 | buildRules = ( 222 | ); 223 | dependencies = ( 224 | 8432DC4B1D96D1BE00A3A0E2 /* PBXTargetDependency */, 225 | ); 226 | name = CardsStackExampleTests; 227 | productName = CardsStackExampleTests; 228 | productReference = 8432DC491D96D1BE00A3A0E2 /* CardsStackExampleTests.xctest */; 229 | productType = "com.apple.product-type.bundle.unit-test"; 230 | }; 231 | 8432DC531D96D1BE00A3A0E2 /* CardsStackExampleUITests */ = { 232 | isa = PBXNativeTarget; 233 | buildConfigurationList = 8432DC631D96D1BE00A3A0E2 /* Build configuration list for PBXNativeTarget "CardsStackExampleUITests" */; 234 | buildPhases = ( 235 | 8432DC501D96D1BE00A3A0E2 /* Sources */, 236 | 8432DC511D96D1BE00A3A0E2 /* Frameworks */, 237 | 8432DC521D96D1BE00A3A0E2 /* Resources */, 238 | ); 239 | buildRules = ( 240 | ); 241 | dependencies = ( 242 | 8432DC561D96D1BE00A3A0E2 /* PBXTargetDependency */, 243 | ); 244 | name = CardsStackExampleUITests; 245 | productName = CardsStackExampleUITests; 246 | productReference = 8432DC541D96D1BE00A3A0E2 /* CardsStackExampleUITests.xctest */; 247 | productType = "com.apple.product-type.bundle.ui-testing"; 248 | }; 249 | /* End PBXNativeTarget section */ 250 | 251 | /* Begin PBXProject section */ 252 | 8432DC2D1D96D1BD00A3A0E2 /* Project object */ = { 253 | isa = PBXProject; 254 | attributes = { 255 | LastSwiftUpdateCheck = 0800; 256 | LastUpgradeCheck = 0800; 257 | ORGANIZATIONNAME = Pritesh; 258 | TargetAttributes = { 259 | 8432DC341D96D1BD00A3A0E2 = { 260 | CreatedOnToolsVersion = 8.0; 261 | DevelopmentTeam = TB2282VDLT; 262 | ProvisioningStyle = Automatic; 263 | }; 264 | 8432DC481D96D1BE00A3A0E2 = { 265 | CreatedOnToolsVersion = 8.0; 266 | DevelopmentTeam = TB2282VDLT; 267 | ProvisioningStyle = Automatic; 268 | TestTargetID = 8432DC341D96D1BD00A3A0E2; 269 | }; 270 | 8432DC531D96D1BE00A3A0E2 = { 271 | CreatedOnToolsVersion = 8.0; 272 | DevelopmentTeam = TB2282VDLT; 273 | ProvisioningStyle = Automatic; 274 | TestTargetID = 8432DC341D96D1BD00A3A0E2; 275 | }; 276 | }; 277 | }; 278 | buildConfigurationList = 8432DC301D96D1BD00A3A0E2 /* Build configuration list for PBXProject "CardsStackExample" */; 279 | compatibilityVersion = "Xcode 3.2"; 280 | developmentRegion = English; 281 | hasScannedForEncodings = 0; 282 | knownRegions = ( 283 | en, 284 | Base, 285 | ); 286 | mainGroup = 8432DC2C1D96D1BD00A3A0E2; 287 | productRefGroup = 8432DC361D96D1BD00A3A0E2 /* Products */; 288 | projectDirPath = ""; 289 | projectReferences = ( 290 | { 291 | ProductGroup = CAFBE06C1D9D57F300AF931F /* Products */; 292 | ProjectRef = CAFBE06B1D9D57F300AF931F /* CardsStack.xcodeproj */; 293 | }, 294 | ); 295 | projectRoot = ""; 296 | targets = ( 297 | 8432DC341D96D1BD00A3A0E2 /* CardsStackExample */, 298 | 8432DC481D96D1BE00A3A0E2 /* CardsStackExampleTests */, 299 | 8432DC531D96D1BE00A3A0E2 /* CardsStackExampleUITests */, 300 | ); 301 | }; 302 | /* End PBXProject section */ 303 | 304 | /* Begin PBXReferenceProxy section */ 305 | CAFBE0711D9D57F300AF931F /* CardsStack.framework */ = { 306 | isa = PBXReferenceProxy; 307 | fileType = wrapper.framework; 308 | path = CardsStack.framework; 309 | remoteRef = CAFBE0701D9D57F300AF931F /* PBXContainerItemProxy */; 310 | sourceTree = BUILT_PRODUCTS_DIR; 311 | }; 312 | CAFBE0731D9D57F300AF931F /* CardsStackTests.xctest */ = { 313 | isa = PBXReferenceProxy; 314 | fileType = wrapper.cfbundle; 315 | path = CardsStackTests.xctest; 316 | remoteRef = CAFBE0721D9D57F300AF931F /* PBXContainerItemProxy */; 317 | sourceTree = BUILT_PRODUCTS_DIR; 318 | }; 319 | /* End PBXReferenceProxy section */ 320 | 321 | /* Begin PBXResourcesBuildPhase section */ 322 | 8432DC331D96D1BD00A3A0E2 /* Resources */ = { 323 | isa = PBXResourcesBuildPhase; 324 | buildActionMask = 2147483647; 325 | files = ( 326 | 8432DC431D96D1BD00A3A0E2 /* LaunchScreen.storyboard in Resources */, 327 | 8432DC401D96D1BD00A3A0E2 /* Assets.xcassets in Resources */, 328 | 8432DC3E1D96D1BD00A3A0E2 /* Main.storyboard in Resources */, 329 | ); 330 | runOnlyForDeploymentPostprocessing = 0; 331 | }; 332 | 8432DC471D96D1BE00A3A0E2 /* Resources */ = { 333 | isa = PBXResourcesBuildPhase; 334 | buildActionMask = 2147483647; 335 | files = ( 336 | ); 337 | runOnlyForDeploymentPostprocessing = 0; 338 | }; 339 | 8432DC521D96D1BE00A3A0E2 /* Resources */ = { 340 | isa = PBXResourcesBuildPhase; 341 | buildActionMask = 2147483647; 342 | files = ( 343 | ); 344 | runOnlyForDeploymentPostprocessing = 0; 345 | }; 346 | /* End PBXResourcesBuildPhase section */ 347 | 348 | /* Begin PBXSourcesBuildPhase section */ 349 | 8432DC311D96D1BD00A3A0E2 /* Sources */ = { 350 | isa = PBXSourcesBuildPhase; 351 | buildActionMask = 2147483647; 352 | files = ( 353 | 8432DC3B1D96D1BD00A3A0E2 /* ViewController.swift in Sources */, 354 | 8432DC801D96E6B900A3A0E2 /* Pokemon.swift in Sources */, 355 | 8432DC7A1D96D50100A3A0E2 /* CardView.swift in Sources */, 356 | 8432DC391D96D1BD00A3A0E2 /* AppDelegate.swift in Sources */, 357 | ); 358 | runOnlyForDeploymentPostprocessing = 0; 359 | }; 360 | 8432DC451D96D1BE00A3A0E2 /* Sources */ = { 361 | isa = PBXSourcesBuildPhase; 362 | buildActionMask = 2147483647; 363 | files = ( 364 | 8432DC4E1D96D1BE00A3A0E2 /* CardsStackExampleTests.swift in Sources */, 365 | ); 366 | runOnlyForDeploymentPostprocessing = 0; 367 | }; 368 | 8432DC501D96D1BE00A3A0E2 /* Sources */ = { 369 | isa = PBXSourcesBuildPhase; 370 | buildActionMask = 2147483647; 371 | files = ( 372 | 8432DC591D96D1BE00A3A0E2 /* CardsStackExampleUITests.swift in Sources */, 373 | ); 374 | runOnlyForDeploymentPostprocessing = 0; 375 | }; 376 | /* End PBXSourcesBuildPhase section */ 377 | 378 | /* Begin PBXTargetDependency section */ 379 | 8432DC4B1D96D1BE00A3A0E2 /* PBXTargetDependency */ = { 380 | isa = PBXTargetDependency; 381 | target = 8432DC341D96D1BD00A3A0E2 /* CardsStackExample */; 382 | targetProxy = 8432DC4A1D96D1BE00A3A0E2 /* PBXContainerItemProxy */; 383 | }; 384 | 8432DC561D96D1BE00A3A0E2 /* PBXTargetDependency */ = { 385 | isa = PBXTargetDependency; 386 | target = 8432DC341D96D1BD00A3A0E2 /* CardsStackExample */; 387 | targetProxy = 8432DC551D96D1BE00A3A0E2 /* PBXContainerItemProxy */; 388 | }; 389 | CAFBE0771D9D57FE00AF931F /* PBXTargetDependency */ = { 390 | isa = PBXTargetDependency; 391 | name = CardsStack; 392 | targetProxy = CAFBE0761D9D57FE00AF931F /* PBXContainerItemProxy */; 393 | }; 394 | /* End PBXTargetDependency section */ 395 | 396 | /* Begin PBXVariantGroup section */ 397 | 8432DC3C1D96D1BD00A3A0E2 /* Main.storyboard */ = { 398 | isa = PBXVariantGroup; 399 | children = ( 400 | 8432DC3D1D96D1BD00A3A0E2 /* Base */, 401 | ); 402 | name = Main.storyboard; 403 | sourceTree = ""; 404 | }; 405 | 8432DC411D96D1BD00A3A0E2 /* LaunchScreen.storyboard */ = { 406 | isa = PBXVariantGroup; 407 | children = ( 408 | 8432DC421D96D1BD00A3A0E2 /* Base */, 409 | ); 410 | name = LaunchScreen.storyboard; 411 | sourceTree = ""; 412 | }; 413 | /* End PBXVariantGroup section */ 414 | 415 | /* Begin XCBuildConfiguration section */ 416 | 8432DC5B1D96D1BE00A3A0E2 /* Debug */ = { 417 | isa = XCBuildConfiguration; 418 | buildSettings = { 419 | ALWAYS_SEARCH_USER_PATHS = NO; 420 | CLANG_ANALYZER_NONNULL = YES; 421 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 422 | CLANG_CXX_LIBRARY = "libc++"; 423 | CLANG_ENABLE_MODULES = YES; 424 | CLANG_ENABLE_OBJC_ARC = YES; 425 | CLANG_WARN_BOOL_CONVERSION = YES; 426 | CLANG_WARN_CONSTANT_CONVERSION = YES; 427 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 428 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 429 | CLANG_WARN_EMPTY_BODY = YES; 430 | CLANG_WARN_ENUM_CONVERSION = YES; 431 | CLANG_WARN_INFINITE_RECURSION = YES; 432 | CLANG_WARN_INT_CONVERSION = YES; 433 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 434 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 435 | CLANG_WARN_UNREACHABLE_CODE = YES; 436 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 437 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 438 | COPY_PHASE_STRIP = NO; 439 | DEBUG_INFORMATION_FORMAT = dwarf; 440 | ENABLE_STRICT_OBJC_MSGSEND = YES; 441 | ENABLE_TESTABILITY = YES; 442 | GCC_C_LANGUAGE_STANDARD = gnu99; 443 | GCC_DYNAMIC_NO_PIC = NO; 444 | GCC_NO_COMMON_BLOCKS = YES; 445 | GCC_OPTIMIZATION_LEVEL = 0; 446 | GCC_PREPROCESSOR_DEFINITIONS = ( 447 | "DEBUG=1", 448 | "$(inherited)", 449 | ); 450 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 451 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 452 | GCC_WARN_UNDECLARED_SELECTOR = YES; 453 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 454 | GCC_WARN_UNUSED_FUNCTION = YES; 455 | GCC_WARN_UNUSED_VARIABLE = YES; 456 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 457 | MTL_ENABLE_DEBUG_INFO = YES; 458 | ONLY_ACTIVE_ARCH = YES; 459 | SDKROOT = iphoneos; 460 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 461 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 462 | SWIFT_VERSION = 3.0; 463 | TARGETED_DEVICE_FAMILY = "1,2"; 464 | }; 465 | name = Debug; 466 | }; 467 | 8432DC5C1D96D1BE00A3A0E2 /* Release */ = { 468 | isa = XCBuildConfiguration; 469 | buildSettings = { 470 | ALWAYS_SEARCH_USER_PATHS = NO; 471 | CLANG_ANALYZER_NONNULL = YES; 472 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 473 | CLANG_CXX_LIBRARY = "libc++"; 474 | CLANG_ENABLE_MODULES = YES; 475 | CLANG_ENABLE_OBJC_ARC = YES; 476 | CLANG_WARN_BOOL_CONVERSION = YES; 477 | CLANG_WARN_CONSTANT_CONVERSION = YES; 478 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 479 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 480 | CLANG_WARN_EMPTY_BODY = YES; 481 | CLANG_WARN_ENUM_CONVERSION = YES; 482 | CLANG_WARN_INFINITE_RECURSION = YES; 483 | CLANG_WARN_INT_CONVERSION = YES; 484 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 485 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 486 | CLANG_WARN_UNREACHABLE_CODE = YES; 487 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 488 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 489 | COPY_PHASE_STRIP = NO; 490 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 491 | ENABLE_NS_ASSERTIONS = NO; 492 | ENABLE_STRICT_OBJC_MSGSEND = YES; 493 | GCC_C_LANGUAGE_STANDARD = gnu99; 494 | GCC_NO_COMMON_BLOCKS = YES; 495 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 496 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 497 | GCC_WARN_UNDECLARED_SELECTOR = YES; 498 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 499 | GCC_WARN_UNUSED_FUNCTION = YES; 500 | GCC_WARN_UNUSED_VARIABLE = YES; 501 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 502 | MTL_ENABLE_DEBUG_INFO = NO; 503 | SDKROOT = iphoneos; 504 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 505 | SWIFT_VERSION = 3.0; 506 | TARGETED_DEVICE_FAMILY = "1,2"; 507 | VALIDATE_PRODUCT = YES; 508 | }; 509 | name = Release; 510 | }; 511 | 8432DC5E1D96D1BE00A3A0E2 /* Debug */ = { 512 | isa = XCBuildConfiguration; 513 | buildSettings = { 514 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 515 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 516 | DEVELOPMENT_TEAM = TB2282VDLT; 517 | INFOPLIST_FILE = CardsStackExample/Info.plist; 518 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 519 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 520 | PRODUCT_BUNDLE_IDENTIFIER = PN.CardsStackExample; 521 | PRODUCT_NAME = "$(TARGET_NAME)"; 522 | SWIFT_VERSION = 3.0; 523 | }; 524 | name = Debug; 525 | }; 526 | 8432DC5F1D96D1BE00A3A0E2 /* Release */ = { 527 | isa = XCBuildConfiguration; 528 | buildSettings = { 529 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 530 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 531 | DEVELOPMENT_TEAM = TB2282VDLT; 532 | INFOPLIST_FILE = CardsStackExample/Info.plist; 533 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 534 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 535 | PRODUCT_BUNDLE_IDENTIFIER = PN.CardsStackExample; 536 | PRODUCT_NAME = "$(TARGET_NAME)"; 537 | SWIFT_VERSION = 3.0; 538 | }; 539 | name = Release; 540 | }; 541 | 8432DC611D96D1BE00A3A0E2 /* Debug */ = { 542 | isa = XCBuildConfiguration; 543 | buildSettings = { 544 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 545 | BUNDLE_LOADER = "$(TEST_HOST)"; 546 | DEVELOPMENT_TEAM = TB2282VDLT; 547 | INFOPLIST_FILE = CardsStackExampleTests/Info.plist; 548 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 549 | PRODUCT_BUNDLE_IDENTIFIER = PN.CardsStackExampleTests; 550 | PRODUCT_NAME = "$(TARGET_NAME)"; 551 | SWIFT_VERSION = 3.0; 552 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/CardsStackExample.app/CardsStackExample"; 553 | }; 554 | name = Debug; 555 | }; 556 | 8432DC621D96D1BE00A3A0E2 /* Release */ = { 557 | isa = XCBuildConfiguration; 558 | buildSettings = { 559 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 560 | BUNDLE_LOADER = "$(TEST_HOST)"; 561 | DEVELOPMENT_TEAM = TB2282VDLT; 562 | INFOPLIST_FILE = CardsStackExampleTests/Info.plist; 563 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 564 | PRODUCT_BUNDLE_IDENTIFIER = PN.CardsStackExampleTests; 565 | PRODUCT_NAME = "$(TARGET_NAME)"; 566 | SWIFT_VERSION = 3.0; 567 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/CardsStackExample.app/CardsStackExample"; 568 | }; 569 | name = Release; 570 | }; 571 | 8432DC641D96D1BE00A3A0E2 /* Debug */ = { 572 | isa = XCBuildConfiguration; 573 | buildSettings = { 574 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 575 | DEVELOPMENT_TEAM = TB2282VDLT; 576 | INFOPLIST_FILE = CardsStackExampleUITests/Info.plist; 577 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 578 | PRODUCT_BUNDLE_IDENTIFIER = PN.CardsStackExampleUITests; 579 | PRODUCT_NAME = "$(TARGET_NAME)"; 580 | SWIFT_VERSION = 3.0; 581 | TEST_TARGET_NAME = CardsStackExample; 582 | }; 583 | name = Debug; 584 | }; 585 | 8432DC651D96D1BE00A3A0E2 /* Release */ = { 586 | isa = XCBuildConfiguration; 587 | buildSettings = { 588 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 589 | DEVELOPMENT_TEAM = TB2282VDLT; 590 | INFOPLIST_FILE = CardsStackExampleUITests/Info.plist; 591 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 592 | PRODUCT_BUNDLE_IDENTIFIER = PN.CardsStackExampleUITests; 593 | PRODUCT_NAME = "$(TARGET_NAME)"; 594 | SWIFT_VERSION = 3.0; 595 | TEST_TARGET_NAME = CardsStackExample; 596 | }; 597 | name = Release; 598 | }; 599 | /* End XCBuildConfiguration section */ 600 | 601 | /* Begin XCConfigurationList section */ 602 | 8432DC301D96D1BD00A3A0E2 /* Build configuration list for PBXProject "CardsStackExample" */ = { 603 | isa = XCConfigurationList; 604 | buildConfigurations = ( 605 | 8432DC5B1D96D1BE00A3A0E2 /* Debug */, 606 | 8432DC5C1D96D1BE00A3A0E2 /* Release */, 607 | ); 608 | defaultConfigurationIsVisible = 0; 609 | defaultConfigurationName = Release; 610 | }; 611 | 8432DC5D1D96D1BE00A3A0E2 /* Build configuration list for PBXNativeTarget "CardsStackExample" */ = { 612 | isa = XCConfigurationList; 613 | buildConfigurations = ( 614 | 8432DC5E1D96D1BE00A3A0E2 /* Debug */, 615 | 8432DC5F1D96D1BE00A3A0E2 /* Release */, 616 | ); 617 | defaultConfigurationIsVisible = 0; 618 | defaultConfigurationName = Release; 619 | }; 620 | 8432DC601D96D1BE00A3A0E2 /* Build configuration list for PBXNativeTarget "CardsStackExampleTests" */ = { 621 | isa = XCConfigurationList; 622 | buildConfigurations = ( 623 | 8432DC611D96D1BE00A3A0E2 /* Debug */, 624 | 8432DC621D96D1BE00A3A0E2 /* Release */, 625 | ); 626 | defaultConfigurationIsVisible = 0; 627 | defaultConfigurationName = Release; 628 | }; 629 | 8432DC631D96D1BE00A3A0E2 /* Build configuration list for PBXNativeTarget "CardsStackExampleUITests" */ = { 630 | isa = XCConfigurationList; 631 | buildConfigurations = ( 632 | 8432DC641D96D1BE00A3A0E2 /* Debug */, 633 | 8432DC651D96D1BE00A3A0E2 /* Release */, 634 | ); 635 | defaultConfigurationIsVisible = 0; 636 | defaultConfigurationName = Release; 637 | }; 638 | /* End XCConfigurationList section */ 639 | }; 640 | rootObject = 8432DC2D1D96D1BD00A3A0E2 /* Project object */; 641 | } 642 | -------------------------------------------------------------------------------- /Example/CardsStackExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/CardsStackExample.xcodeproj/project.xcworkspace/xcshareddata/CardsStackExample.xcscmblueprint: -------------------------------------------------------------------------------- 1 | { 2 | "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "A66143EEE51951E22CF314759A046F3FF619A563", 3 | "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : { 4 | 5 | }, 6 | "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : { 7 | "A66143EEE51951E22CF314759A046F3FF619A563" : 9223372036854775807, 8 | "756A0D8326C6250D4548B9F479EC83CFE515F3D7" : 9223372036854775807 9 | }, 10 | "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "CD8ED545-8221-43A7-A2C9-DF4FE0622F7A", 11 | "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : { 12 | "A66143EEE51951E22CF314759A046F3FF619A563" : "CardsStackExample\/", 13 | "756A0D8326C6250D4548B9F479EC83CFE515F3D7" : "CardsStack\/" 14 | }, 15 | "DVTSourceControlWorkspaceBlueprintNameKey" : "CardsStackExample", 16 | "DVTSourceControlWorkspaceBlueprintVersion" : 204, 17 | "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "CardsStackExample.xcodeproj", 18 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [ 19 | { 20 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/priteshrnandgaonkar\/CardsStack.git", 21 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", 22 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "756A0D8326C6250D4548B9F479EC83CFE515F3D7" 23 | }, 24 | { 25 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/priteshrnandgaonkar\/CardsStackExample.git", 26 | "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", 27 | "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "A66143EEE51951E22CF314759A046F3FF619A563" 28 | } 29 | ] 30 | } -------------------------------------------------------------------------------- /Example/CardsStackExample.xcodeproj/project.xcworkspace/xcuserdata/priteshnandgaonkar.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/priteshrnandgaonkar/CardsStack/71a4d7a39236de96349d1204ac5e5f9f5893ae44/Example/CardsStackExample.xcodeproj/project.xcworkspace/xcuserdata/priteshnandgaonkar.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Example/CardsStackExample.xcodeproj/xcuserdata/housing.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 12 | 13 | 14 | 16 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Example/CardsStackExample.xcodeproj/xcuserdata/housing.xcuserdatad/xcschemes/CardsStackExample.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 43 | 49 | 50 | 51 | 52 | 53 | 59 | 60 | 61 | 62 | 63 | 64 | 74 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 95 | 101 | 102 | 103 | 104 | 106 | 107 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /Example/CardsStackExample.xcodeproj/xcuserdata/housing.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | CardsStackExample.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 8432DC341D96D1BD00A3A0E2 16 | 17 | primary 18 | 19 | 20 | 8432DC481D96D1BE00A3A0E2 21 | 22 | primary 23 | 24 | 25 | 8432DC531D96D1BE00A3A0E2 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /Example/CardsStackExample.xcodeproj/xcuserdata/priteshnandgaonkar.xcuserdatad/xcschemes/CardsStackExample.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 43 | 49 | 50 | 51 | 52 | 53 | 59 | 60 | 61 | 62 | 63 | 64 | 74 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 95 | 101 | 102 | 103 | 104 | 106 | 107 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /Example/CardsStackExample.xcodeproj/xcuserdata/priteshnandgaonkar.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | CardsStackExample.xcscheme 8 | 9 | orderHint 10 | 1 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 8432DC341D96D1BD00A3A0E2 16 | 17 | primary 18 | 19 | 20 | 8432DC481D96D1BE00A3A0E2 21 | 22 | primary 23 | 24 | 25 | 8432DC531D96D1BE00A3A0E2 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /Example/CardsStackExample/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // CardsStackExample 4 | // 5 | // Created by Pritesh Nandgaonkar on 9/24/16. 6 | // Copyright © 2016 Pritesh. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(_ application: UIApplication) { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(_ application: UIApplication) { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(_ application: UIApplication) { 33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(_ application: UIApplication) { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | func applicationWillTerminate(_ application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /Example/CardsStackExample/Assets.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" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | } 88 | ], 89 | "info" : { 90 | "version" : 1, 91 | "author" : "xcode" 92 | } 93 | } -------------------------------------------------------------------------------- /Example/CardsStackExample/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Example/CardsStackExample/Assets.xcassets/alakazam.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "alakazam.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example/CardsStackExample/Assets.xcassets/alakazam.imageset/alakazam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/priteshrnandgaonkar/CardsStack/71a4d7a39236de96349d1204ac5e5f9f5893ae44/Example/CardsStackExample/Assets.xcassets/alakazam.imageset/alakazam.png -------------------------------------------------------------------------------- /Example/CardsStackExample/Assets.xcassets/blastoise.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "blastoise.jpeg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example/CardsStackExample/Assets.xcassets/blastoise.imageset/blastoise.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/priteshrnandgaonkar/CardsStack/71a4d7a39236de96349d1204ac5e5f9f5893ae44/Example/CardsStackExample/Assets.xcassets/blastoise.imageset/blastoise.jpeg -------------------------------------------------------------------------------- /Example/CardsStackExample/Assets.xcassets/bulbasaur.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "bulbasaur.jpeg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example/CardsStackExample/Assets.xcassets/bulbasaur.imageset/bulbasaur.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/priteshrnandgaonkar/CardsStack/71a4d7a39236de96349d1204ac5e5f9f5893ae44/Example/CardsStackExample/Assets.xcassets/bulbasaur.imageset/bulbasaur.jpeg -------------------------------------------------------------------------------- /Example/CardsStackExample/Assets.xcassets/charizard.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "charizard.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example/CardsStackExample/Assets.xcassets/charizard.imageset/charizard.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/priteshrnandgaonkar/CardsStack/71a4d7a39236de96349d1204ac5e5f9f5893ae44/Example/CardsStackExample/Assets.xcassets/charizard.imageset/charizard.jpg -------------------------------------------------------------------------------- /Example/CardsStackExample/Assets.xcassets/charmender.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "charmender.jpeg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example/CardsStackExample/Assets.xcassets/charmender.imageset/charmender.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/priteshrnandgaonkar/CardsStack/71a4d7a39236de96349d1204ac5e5f9f5893ae44/Example/CardsStackExample/Assets.xcassets/charmender.imageset/charmender.jpeg -------------------------------------------------------------------------------- /Example/CardsStackExample/Assets.xcassets/error.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "error.jpeg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example/CardsStackExample/Assets.xcassets/error.imageset/error.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/priteshrnandgaonkar/CardsStack/71a4d7a39236de96349d1204ac5e5f9f5893ae44/Example/CardsStackExample/Assets.xcassets/error.imageset/error.jpeg -------------------------------------------------------------------------------- /Example/CardsStackExample/Assets.xcassets/evy.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "evy.jpeg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example/CardsStackExample/Assets.xcassets/evy.imageset/evy.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/priteshrnandgaonkar/CardsStack/71a4d7a39236de96349d1204ac5e5f9f5893ae44/Example/CardsStackExample/Assets.xcassets/evy.imageset/evy.jpeg -------------------------------------------------------------------------------- /Example/CardsStackExample/Assets.xcassets/gengar.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "gengar.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example/CardsStackExample/Assets.xcassets/gengar.imageset/gengar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/priteshrnandgaonkar/CardsStack/71a4d7a39236de96349d1204ac5e5f9f5893ae44/Example/CardsStackExample/Assets.xcassets/gengar.imageset/gengar.jpg -------------------------------------------------------------------------------- /Example/CardsStackExample/Assets.xcassets/pika.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "pika.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example/CardsStackExample/Assets.xcassets/pika.imageset/pika.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/priteshrnandgaonkar/CardsStack/71a4d7a39236de96349d1204ac5e5f9f5893ae44/Example/CardsStackExample/Assets.xcassets/pika.imageset/pika.jpg -------------------------------------------------------------------------------- /Example/CardsStackExample/Assets.xcassets/pokemon_logo.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "pokemon_logo.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example/CardsStackExample/Assets.xcassets/pokemon_logo.imageset/pokemon_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/priteshrnandgaonkar/CardsStack/71a4d7a39236de96349d1204ac5e5f9f5893ae44/Example/CardsStackExample/Assets.xcassets/pokemon_logo.imageset/pokemon_logo.png -------------------------------------------------------------------------------- /Example/CardsStackExample/Assets.xcassets/raichu.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "raichu.jpeg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example/CardsStackExample/Assets.xcassets/raichu.imageset/raichu.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/priteshrnandgaonkar/CardsStack/71a4d7a39236de96349d1204ac5e5f9f5893ae44/Example/CardsStackExample/Assets.xcassets/raichu.imageset/raichu.jpeg -------------------------------------------------------------------------------- /Example/CardsStackExample/Assets.xcassets/squirtle.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "squirtle.jpeg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example/CardsStackExample/Assets.xcassets/squirtle.imageset/squirtle.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/priteshrnandgaonkar/CardsStack/71a4d7a39236de96349d1204ac5e5f9f5893ae44/Example/CardsStackExample/Assets.xcassets/squirtle.imageset/squirtle.jpeg -------------------------------------------------------------------------------- /Example/CardsStackExample/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Example/CardsStackExample/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /Example/CardsStackExample/CardView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CardView.swift 3 | // DynamicStackOfCards 4 | // 5 | // Created by Pritesh Nandgaonkar on 9/16/16. 6 | // Copyright © 2016 pritesh. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | @IBDesignable 13 | class CardView: UICollectionViewCell { 14 | 15 | @IBOutlet weak var header: UILabel! 16 | 17 | @IBOutlet weak var imageView: UIImageView! 18 | 19 | override func layoutSubviews() 20 | { 21 | super.layoutSubviews() 22 | 23 | let shadowPath = UIBezierPath(rect: bounds) 24 | layer.masksToBounds = false 25 | layer.shadowColor = UIColor.black.cgColor 26 | layer.shadowOffset = CGSize(width: 0, height: 2) 27 | layer.shadowOpacity = 0.5 28 | layer.shadowPath = shadowPath.cgPath 29 | layer.cornerRadius = 4 30 | layer.rasterizationScale = UIScreen.main.scale 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Example/CardsStackExample/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 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /Example/CardsStackExample/Pokemon.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Pokemon.swift 3 | // CardsStackExample 4 | // 5 | // Created by Pritesh Nandgaonkar on 9/24/16. 6 | // Copyright © 2016 Pritesh. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | struct Pokemon { 12 | let name: String 13 | let imageName: String 14 | } 15 | -------------------------------------------------------------------------------- /Example/CardsStackExample/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // CardsStackExample 4 | // 5 | // Created by Pritesh Nandgaonkar on 9/24/16. 6 | // Copyright © 2016 Pritesh. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import CardsStack 11 | 12 | class ViewController: UIViewController { 13 | 14 | @IBOutlet weak var heightConstraint: NSLayoutConstraint! 15 | @IBOutlet weak var collectionView: UICollectionView! 16 | 17 | @IBOutlet weak var pokemon: UIImageView! 18 | var cardState: CardsPosition = .Collapsed 19 | var cardsStack: CardStack = CardStack() 20 | var pokemons = [Pokemon(name: "Pikachu", imageName:"pika"), Pokemon(name: "Squirtle", imageName:"squirtle"), Pokemon(name: "Blastoise", imageName:"blastoise"), Pokemon(name: "Charmender", imageName:"charmender"), Pokemon(name: "Raichu", imageName:"raichu"), Pokemon(name: "Evy", imageName:"evy"),Pokemon(name: "Charizard", imageName:"charizard"),Pokemon(name: "gengar", imageName:"gengar"),Pokemon(name: "Alakazam", imageName:"alakazam")] 21 | 22 | override func viewDidLoad() { 23 | 24 | super.viewDidLoad() 25 | 26 | let expandedHeight = Float(UIScreen.main.bounds.size.height - 124) 27 | 28 | let config = Configuration(cardOffset: 40, collapsedHeight: 200, expandedHeight: expandedHeight, cardHeight: 200, downwardThreshold: 20, upwardThreshold: 20, leftSpacing: 8.0, rightSpacing: 8.0) 29 | 30 | cardsStack = CardStack(cardsState: cardState, configuration: config, collectionView: collectionView, collectionViewHeight: heightConstraint) 31 | cardsStack.delegate = self 32 | 33 | //Uncomment the following line if this viewcontroller is embeded in the navigationcontroller 34 | //automaticallyAdjustsScrollViewInsets = false 35 | } 36 | 37 | override func didReceiveMemoryWarning() { 38 | super.didReceiveMemoryWarning() 39 | // Dispose of any resources that can be recreated. 40 | } 41 | } 42 | 43 | extension ViewController: UICollectionViewDataSource, CardsManagerDelegate { 44 | 45 | func tappedOnCardsStack(cardsCollectionView: UICollectionView) { 46 | cardsStack.changeCardsPosition(to: .Expanded) 47 | } 48 | 49 | func cardsCollectionView(_ cardsCollectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { 50 | print("Selected \(pokemons[indexPath.item].name)") 51 | } 52 | 53 | func cardsPositionChangedTo(position: CardsPosition) { 54 | print("CardsPosition Changed To \(position.rawValue)") 55 | } 56 | func numberOfSections(in collectionView: UICollectionView) -> Int { 57 | return 1 58 | } 59 | 60 | func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 61 | return pokemons.count 62 | } 63 | 64 | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 65 | guard let cardView = collectionView.dequeueReusableCell(withReuseIdentifier: "CardReuseID", for: indexPath) as? CardView else { 66 | fatalError("Failed to downcast to CardView") 67 | } 68 | cardView.header.text = "\(pokemons[indexPath.item].name)" 69 | 70 | cardView.imageView.image = UIImage(imageLiteralResourceName: pokemons[indexPath.item].imageName) 71 | 72 | return cardView 73 | } 74 | 75 | } 76 | 77 | -------------------------------------------------------------------------------- /Example/CardsStackExampleTests/CardsStackExampleTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CardsStackExampleTests.swift 3 | // CardsStackExampleTests 4 | // 5 | // Created by housing on 9/24/16. 6 | // Copyright © 2016 Pritesh. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import CardsStackExample 11 | 12 | class CardsStackExampleTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | // Use XCTAssert and related functions to verify your tests produce the correct results. 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measure { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /Example/CardsStackExampleTests/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 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Example/CardsStackExampleUITests/CardsStackExampleUITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CardsStackExampleUITests.swift 3 | // CardsStackExampleUITests 4 | // 5 | // Created by housing on 9/24/16. 6 | // Copyright © 2016 Pritesh. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class CardsStackExampleUITests: XCTestCase { 12 | 13 | override func setUp() { 14 | super.setUp() 15 | 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | 18 | // In UI tests it is usually best to stop immediately when a failure occurs. 19 | continueAfterFailure = false 20 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 21 | XCUIApplication().launch() 22 | 23 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 24 | } 25 | 26 | override func tearDown() { 27 | // Put teardown code here. This method is called after the invocation of each test method in the class. 28 | super.tearDown() 29 | } 30 | 31 | func testExample() { 32 | // Use recording to get started writing UI tests. 33 | // Use XCTAssert and related functions to verify your tests produce the correct results. 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /Example/CardsStackExampleUITests/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 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Pritesh Nandgaonkar 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CardStack [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) ![Pod Support](https://img.shields.io/cocoapods/v/CardsStack.svg?maxAge=2592000) ![Swift 3 compatible](Documentation/Swift-3-orange.png) 2 | 3 | 4 | CardStack converts your `UICollectionView` to an awesome stack of cards using custom `UICollectionViewLayout`. 5 | 6 | ## What is CardStack? 💫 ✨💥⭐️ 7 | 8 | Talk is cheap, lets look at the gif. 9 | 10 | ![Basic Interaction](Documentation/BasicCardStackInteraction.gif) 11 | 12 | 13 | The Basic interaction with the CardStack is dragging up the cards till they are unraveled. But hold on, for the impatient users, there is one more interaction, you can drag a little and the cards will unwind or wind. 14 | 15 | ![Lazy Interaction](Documentation/LazyInteraction.gif) 16 | 17 | ## Installation 18 | ### CocoaPods 19 | 20 | [CocoaPods](https://cocoapods.org/) is a dependency manager for Cocoa projects. You can install it with the following command: 21 | 22 | ``` 23 | $ gem install cocoapods 24 | 25 | ``` 26 | To integrate CardsStack into your Xcode project using CocoaPods, specify it in your Podfile: 27 | 28 | ``` 29 | source 'https://github.com/CocoaPods/Specs.git' 30 | platform :ios, '8.0' 31 | use_frameworks! 32 | 33 | target '' do 34 | pod 'CardsStack', '0.2.1' 35 | end 36 | 37 | ``` 38 | Then, run the following command: 39 | 40 | ``` 41 | $ pod install 42 | 43 | ``` 44 | ### Carthage 45 | [Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks. 46 | 47 | You can install Carthage with [Homebrew](http://brew.sh/) using the following command: 48 | 49 | ``` 50 | $ brew update 51 | $ brew install carthage 52 | 53 | ``` 54 | To integrate CardsStack into your Xcode project using Carthage, specify it in your Cartfile: 55 | 56 | ``` 57 | github "priteshrnandgaonkar/CardsStack" == 0.2.1 58 | 59 | ``` 60 | Run `carthage update` to build the framework and drag the built CardsStack.framework into your Xcode project. 61 | 62 | ## How to use it? 63 | 64 | There are 4 basic components required by CardsStack to function. To initialise the `CardStack` it needs the `CardsPosition`, `Configuration` along with `UICollectionView` and its height constraint i.e `NSLayoutConstraint`. 65 | 66 | Initialise `CardStack` as follows 67 | 68 | ``` swift 69 | let config = Configuration(cardOffset: 40, collapsedHeight: 200, expandedHeight: 500, cardHeight: 200, downwardThreshold: 20, upwardThreshold: 20, leftSpacing: 8.0, rightSpacing: 8.0, verticalSpacing: 8.0) 70 | let cardStack = CardStack(cardsState: .Collapsed, configuration: config, collectionView: collectionView, collectionViewHeight: heightConstraint) 71 | 72 | ``` 73 | ### Configuration 74 | 75 | `Configuration` object holds the information related to Stacks view, like the collapsed height, expanded height etc. 76 | 77 | ``` swift 78 | public struct Configuration { 79 | public let cardOffset: Float 80 | public let collapsedHeight:Float 81 | public let expandedHeight:Float 82 | public let cardHeight: Float 83 | public let downwardThreshold: Float 84 | public let upwardThreshold: Float 85 | public let verticalSpacing: Float 86 | public let leftSpacing: Float 87 | public let rightSpacing: Float 88 | 89 | public init(cardOffset: Float, collapsedHeight: Float, expandedHeight: Float, cardHeight: Float, downwardThreshold: Float = 20, upwardThreshold: Float = 20, leftSpacing: Float = 8.0, rightSpacing: Float = 8.0, verticalSpacing: Float = 8.0) { 90 | self.cardOffset = cardOffset 91 | self.collapsedHeight = collapsedHeight 92 | self.expandedHeight = expandedHeight 93 | self.downwardThreshold = downwardThreshold 94 | self.upwardThreshold = upwardThreshold 95 | self.cardHeight = cardHeight 96 | self.verticalSpacing = verticalSpacing 97 | self.leftSpacing = leftSpacing 98 | self.rightSpacing = rightSpacing 99 | } 100 | } 101 | 102 | ``` 103 | 104 | Its initialiser requires the necessary fields like `cardOffset`, `collapsedHeight`, `expandedHeight` and `cardHeight`. 105 | 106 | 1. `cardOffset` is the offset between thetwo cards while in collapsed state. 107 | 2. `collapsedHeight`, as name suggests its the height of the collectionview while in collapsed state. 108 | 3. `expandedHeight` is the height of the collectionview while in expanded state. 109 | 4. `cardHeight` is the height of the cell. 110 | 111 | ### CardsPosition 112 | 113 | Its an enum which states the current state of CardsStack. 114 | 115 | ``` swift 116 | @objc public enum CardsPosition: Int { 117 | case Collapsed 118 | case Expanded 119 | } 120 | 121 | ``` 122 | 123 | ## CardsManagerDelegate 124 | 125 | With this delegate you can get the hooks to specific events. 126 | 127 | ``` swift 128 | 129 | @objc public protocol CardsManagerDelegate { 130 | 131 | @objc optional func cardsPositionChangedTo(position: CardsPosition) 132 | @objc optional func tappedOnCardsStack(cardsCollectionView: UICollectionView) 133 | @objc optional func cardsCollectionView(_ cardsCollectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) 134 | @objc optional func cardsCollectionView(_ cardsCollectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) 135 | 136 | } 137 | 138 | ``` 139 | For listening to this call-backs assign a delegate to `CardsStack`. 140 | 141 | ``` swift 142 | cardStack.delegate = self 143 | ``` 144 | 145 | The last two functions are the same as the delegate function for collection view. 146 | 147 | The first function gives the hook to the `CardStacks` position change. 148 | 149 | ``` swift 150 | @objc optional func cardsPositionChangedTo(position: CardsPosition) 151 | ``` 152 | 153 | The CardStack also has the tap gesture which is enabled when the cards are collapsed.The second function gives the hook to the tap gesture on collectionview when the cards are in collapsed state. 154 | 155 | So you can use this hook to open cards, like this 156 | 157 | ``` swift 158 | 159 | func tappedOnCardsStack(cardsCollectionView: UICollectionView) { 160 | cardStack.changeCardsPosition(to: .Expanded) 161 | } 162 | 163 | ``` 164 | 165 | In order to change the state of the cards programatically you can use. 166 | 167 | ``` swift 168 | public func changeCardsPosition(to position: CardsPosition) { 169 | 170 | ``` 171 | 172 | You can checkout the example in the project and play around with it to get hang of the API's. 173 | 174 | You can also find the [example](https://github.com/priteshrnandgaonkar/CardsStackExample) with CardsStack imported through Carthage. 175 | 176 | You can also checkout the my [blog](https://priteshrnandgaonkar.github.io/Details-of-CardsStack/) discussing the details of the library. 177 | 178 | ## TODO 179 | - [x] Carthage Support 180 | - [x] CocoaPods Support 181 | - [ ] SwiftPM Support 182 | - [ ] Watch, TvOS Targets 183 | 184 | ## Contributions 185 | 186 | Found a bug? Want a new feature? Please feel free to report any issue or raise a Pull Request. 187 | --------------------------------------------------------------------------------