├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── SCCollectionViewController.podspec ├── SCCollectionViewController.xcodeproj ├── project.pbxproj └── xcshareddata │ └── xcschemes │ └── SCCollectionViewController.xcscheme ├── SCCollectionViewController.xcworkspace └── contents.xcworkspacedata ├── Sample ├── Podfile ├── Sample.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── xcshareddata │ │ └── xcschemes │ │ └── Sample.xcscheme └── Source │ ├── AppDelegate.swift │ ├── Base.lproj │ ├── LaunchScreen.xib │ └── Main.storyboard │ ├── CustomNavigationController.swift │ ├── Images.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── button_back.imageset │ │ ├── Contents.json │ │ ├── button_back.png │ │ ├── button_back@2x.png │ │ └── button_back@3x.png │ └── town.imageset │ │ ├── 16075461243_f9dbe86321_z.png │ │ └── Contents.json │ ├── Info.plist │ └── SubclassExampleController.swift └── Source ├── Info.plist ├── SCCollectionViewController.h ├── SCCollectionViewController.swift └── SCNavigationBar.swift /.gitignore: -------------------------------------------------------------------------------- 1 | # Exclude the build directory 2 | build/* 3 | examples/FilterShowcase/build* 4 | 5 | # Exclude temp nibs and swap files 6 | *~.nib 7 | *.swp 8 | 9 | # Exclude OS X folder attributes 10 | .DS_Store 11 | 12 | # Exclude user-specific XCode 3 and 4 files 13 | *.mode1 14 | *.mode1v3 15 | *.mode2v3 16 | *.perspective 17 | *.perspectivev3 18 | *.pbxuser 19 | xcuserdata 20 | 21 | # Documentation 22 | documentation/* 23 | 24 | # CocoaPods 25 | Pods/* 26 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | xcode_workspace: SCCollectionViewController.xcworkspace 3 | xcode_scheme: Sample 4 | xcode_sdk: iphonesimulator8.1 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 Benoît LAYER 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![SCCollectionViewController](https://raw.githubusercontent.com/notbenoit/notbenoit.github.io/master/images/sccollectionviewcontroller/sccollectionviewcontroller.gif) 2 | 3 | # SCCollectionViewController 4 | This framework provides a controller to subclass, which presents a UICollectionView with builtin animations for a growing header (scale effect), a parallax effect, and a navigation bar background which fades in and out as you scroll through the UICollectionView. 5 | 6 | ## Requirements 7 | 8 | - iOS 7.0+ (do not use cocoapods for iOS before 8, since cocoapods forces Swift frameworks to have a iOS8 deployment target) 9 | - Xcode 6.3 (Usage of Swift 1.2) 10 | 11 | ## Installation 12 | 13 | ### CocoaPods 14 | [CocoaPods](http://cocoapods.org) is a dependency manager for Cocoa projects. 15 | 16 | CocoaPods 0.36 adds supports for Swift and embedded frameworks. You can install it with the following command: 17 | 18 | ```bash 19 | $ gem install cocoapods 20 | ``` 21 | 22 | To add `SCCollectionViewController` to your project, add this lines to your `Podfile`: 23 | 24 | ```ruby 25 | use_frameworks! 26 | pod 'SCCollectionViewController', '~> 1.0' 27 | ``` 28 | The flag `use_frameworks!` is used because this framework is entirely written in Swift, and generates a .framework file. 29 | 30 | ### Manual 31 | - Simply add the `SCCollectionViewController.xcodeproj` to your workspace and add its framework output as a dependency of your project (see the Sample project). 32 | - You can also build the framework and directly link it to your target. 33 | 34 | ## Usage 35 | ### CollectionView layout setup 36 | You can customize some properties to change the appearance of the controller. 37 | 38 | * `cellMargin: CGFloat = 5` It's the spacing between two lines, and the edge insets for left and right (left and right margins). 39 | * `cellHeight: CGFloat = 120` Corresponds to the height of every cell. 40 | * `headerBaseHeight: CGFloat = 170` The height of the header when not scaled. 41 | 42 | 43 | ### Growing header and parallax 44 | First, you **MUST** subclass SCCollectionViewController, and provide your own implementation for the following methods : 45 | 46 | ```swift 47 | func configureCell(cell: UICollectionViewCell, indexPath: NSIndexPath) 48 | func configureHeader(header: UICollectionReusableView) 49 | func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 50 | ``` 51 | 52 | You can also overrides any delegate method which is not declared `final` in the SCCollectionViewController. 53 | 54 | Combine this subclass with your views and models, and you'll be able to customize the cells and headers as you like. 55 | 56 | You'll have automatically the growing header, and parallax effects. 57 | 58 | ### Fading navigation bar 59 | For the fading effect, you'll have to push your SCCollectionViewController in a navigation controller. 60 | Your navigation controller should have a navigation bar of type `SCNavigationBar` because it overrides the alpha property of the UINavigationBar (to only have the background fading, and not the navigation items). If you do not use the SCNavigationBar, the whole bar will fade out and so will the navigation items. 61 | 62 | You can set the class of the navigation bar directly in your nib or storyboard file, or when you instantiate your UINavigationController with `init(navigationBarClass: AnyClass?, toolbarClass: AnyClass?)` 63 | 64 | ## Limitations 65 | Right now, the SCCollectionViewController is made for a single section in the UICollectionView. 66 | 67 | ## Changelog 68 | ### 1.0.1 69 | Used the mask property on CALayer instead of the mnew maskView property of UIView in order to be run on iOS7.0+. 70 | 71 | ### 1.0.0 72 | Initial version 73 | 74 | ## Creator 75 | 76 | - [Benoît Layer](http://github.com/notbenoit) ([@notbenoit](https://twitter.com/notbenoit)) 77 | 78 | ## License 79 | 80 | SCCollectionViewController is released under the MIT license. See LICENSE for details. 81 | -------------------------------------------------------------------------------- /SCCollectionViewController.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'SCCollectionViewController' 3 | s.version = '1.0.1' 4 | s.license = 'MIT' 5 | s.summary = 'A controller presenting a collection view with out of the box effects, like parallax, growing header, and a fading navigation bar.' 6 | s.homepage = 'https://github.com/notbenoit/SCCollectionViewController' 7 | s.social_media_url = 'http://twitter.com/notbenoit' 8 | s.authors = { 'Benoit Layer' => 'benoit.layer@gmail.com' } 9 | s.source = { :git => 'https://github.com/notbenoit/SCCollectionViewController.git', :tag => s.version } 10 | 11 | s.ios.deployment_target = '8.0' 12 | 13 | s.source_files = 'Source/*.swift' 14 | 15 | s.requires_arc = true 16 | end 17 | -------------------------------------------------------------------------------- /SCCollectionViewController.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | FCD358151AEC5618005F3188 /* SCCollectionViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = FCD358131AEC5618005F3188 /* SCCollectionViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; 11 | FCD358181AEC56A5005F3188 /* SCCollectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCD358161AEC56A5005F3188 /* SCCollectionViewController.swift */; }; 12 | FCD358191AEC56A5005F3188 /* SCNavigationBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCD358171AEC56A5005F3188 /* SCNavigationBar.swift */; }; 13 | /* End PBXBuildFile section */ 14 | 15 | /* Begin PBXFileReference section */ 16 | FCD357F51AEC5585005F3188 /* SCCollectionViewController.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SCCollectionViewController.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 17 | FCD358121AEC5618005F3188 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 18 | FCD358131AEC5618005F3188 /* SCCollectionViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SCCollectionViewController.h; sourceTree = ""; }; 19 | FCD358161AEC56A5005F3188 /* SCCollectionViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SCCollectionViewController.swift; sourceTree = ""; }; 20 | FCD358171AEC56A5005F3188 /* SCNavigationBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SCNavigationBar.swift; sourceTree = ""; }; 21 | /* End PBXFileReference section */ 22 | 23 | /* Begin PBXFrameworksBuildPhase section */ 24 | FCD357F11AEC5585005F3188 /* Frameworks */ = { 25 | isa = PBXFrameworksBuildPhase; 26 | buildActionMask = 2147483647; 27 | files = ( 28 | ); 29 | runOnlyForDeploymentPostprocessing = 0; 30 | }; 31 | /* End PBXFrameworksBuildPhase section */ 32 | 33 | /* Begin PBXGroup section */ 34 | FCD357EB1AEC5585005F3188 = { 35 | isa = PBXGroup; 36 | children = ( 37 | FCD358111AEC5618005F3188 /* Source */, 38 | FCD357F61AEC5585005F3188 /* Products */, 39 | ); 40 | sourceTree = ""; 41 | }; 42 | FCD357F61AEC5585005F3188 /* Products */ = { 43 | isa = PBXGroup; 44 | children = ( 45 | FCD357F51AEC5585005F3188 /* SCCollectionViewController.framework */, 46 | ); 47 | name = Products; 48 | sourceTree = ""; 49 | }; 50 | FCD358111AEC5618005F3188 /* Source */ = { 51 | isa = PBXGroup; 52 | children = ( 53 | FCD358121AEC5618005F3188 /* Info.plist */, 54 | FCD358131AEC5618005F3188 /* SCCollectionViewController.h */, 55 | FCD358161AEC56A5005F3188 /* SCCollectionViewController.swift */, 56 | FCD358171AEC56A5005F3188 /* SCNavigationBar.swift */, 57 | ); 58 | path = Source; 59 | sourceTree = ""; 60 | }; 61 | /* End PBXGroup section */ 62 | 63 | /* Begin PBXHeadersBuildPhase section */ 64 | FCD357F21AEC5585005F3188 /* Headers */ = { 65 | isa = PBXHeadersBuildPhase; 66 | buildActionMask = 2147483647; 67 | files = ( 68 | FCD358151AEC5618005F3188 /* SCCollectionViewController.h in Headers */, 69 | ); 70 | runOnlyForDeploymentPostprocessing = 0; 71 | }; 72 | /* End PBXHeadersBuildPhase section */ 73 | 74 | /* Begin PBXNativeTarget section */ 75 | FCD357F41AEC5585005F3188 /* SCCollectionViewController */ = { 76 | isa = PBXNativeTarget; 77 | buildConfigurationList = FCD3580B1AEC5586005F3188 /* Build configuration list for PBXNativeTarget "SCCollectionViewController" */; 78 | buildPhases = ( 79 | FCD357F01AEC5585005F3188 /* Sources */, 80 | FCD357F11AEC5585005F3188 /* Frameworks */, 81 | FCD357F21AEC5585005F3188 /* Headers */, 82 | FCD357F31AEC5585005F3188 /* Resources */, 83 | ); 84 | buildRules = ( 85 | ); 86 | dependencies = ( 87 | ); 88 | name = SCCollectionViewController; 89 | productName = SCCollectionViewController; 90 | productReference = FCD357F51AEC5585005F3188 /* SCCollectionViewController.framework */; 91 | productType = "com.apple.product-type.framework"; 92 | }; 93 | /* End PBXNativeTarget section */ 94 | 95 | /* Begin PBXProject section */ 96 | FCD357EC1AEC5585005F3188 /* Project object */ = { 97 | isa = PBXProject; 98 | attributes = { 99 | LastUpgradeCheck = 0630; 100 | ORGANIZATIONNAME = "Benoit Layer"; 101 | TargetAttributes = { 102 | FCD357F41AEC5585005F3188 = { 103 | CreatedOnToolsVersion = 6.3; 104 | }; 105 | }; 106 | }; 107 | buildConfigurationList = FCD357EF1AEC5585005F3188 /* Build configuration list for PBXProject "SCCollectionViewController" */; 108 | compatibilityVersion = "Xcode 3.2"; 109 | developmentRegion = English; 110 | hasScannedForEncodings = 0; 111 | knownRegions = ( 112 | en, 113 | ); 114 | mainGroup = FCD357EB1AEC5585005F3188; 115 | productRefGroup = FCD357F61AEC5585005F3188 /* Products */; 116 | projectDirPath = ""; 117 | projectRoot = ""; 118 | targets = ( 119 | FCD357F41AEC5585005F3188 /* SCCollectionViewController */, 120 | ); 121 | }; 122 | /* End PBXProject section */ 123 | 124 | /* Begin PBXResourcesBuildPhase section */ 125 | FCD357F31AEC5585005F3188 /* Resources */ = { 126 | isa = PBXResourcesBuildPhase; 127 | buildActionMask = 2147483647; 128 | files = ( 129 | ); 130 | runOnlyForDeploymentPostprocessing = 0; 131 | }; 132 | /* End PBXResourcesBuildPhase section */ 133 | 134 | /* Begin PBXSourcesBuildPhase section */ 135 | FCD357F01AEC5585005F3188 /* Sources */ = { 136 | isa = PBXSourcesBuildPhase; 137 | buildActionMask = 2147483647; 138 | files = ( 139 | FCD358181AEC56A5005F3188 /* SCCollectionViewController.swift in Sources */, 140 | FCD358191AEC56A5005F3188 /* SCNavigationBar.swift in Sources */, 141 | ); 142 | runOnlyForDeploymentPostprocessing = 0; 143 | }; 144 | /* End PBXSourcesBuildPhase section */ 145 | 146 | /* Begin XCBuildConfiguration section */ 147 | FCD358091AEC5585005F3188 /* Debug */ = { 148 | isa = XCBuildConfiguration; 149 | buildSettings = { 150 | ALWAYS_SEARCH_USER_PATHS = NO; 151 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 152 | CLANG_CXX_LIBRARY = "libc++"; 153 | CLANG_ENABLE_MODULES = YES; 154 | CLANG_ENABLE_OBJC_ARC = YES; 155 | CLANG_WARN_BOOL_CONVERSION = YES; 156 | CLANG_WARN_CONSTANT_CONVERSION = YES; 157 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 158 | CLANG_WARN_EMPTY_BODY = YES; 159 | CLANG_WARN_ENUM_CONVERSION = YES; 160 | CLANG_WARN_INT_CONVERSION = YES; 161 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 162 | CLANG_WARN_UNREACHABLE_CODE = YES; 163 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 164 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 165 | COPY_PHASE_STRIP = NO; 166 | CURRENT_PROJECT_VERSION = 1; 167 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 168 | ENABLE_STRICT_OBJC_MSGSEND = YES; 169 | GCC_C_LANGUAGE_STANDARD = gnu99; 170 | GCC_DYNAMIC_NO_PIC = NO; 171 | GCC_NO_COMMON_BLOCKS = YES; 172 | GCC_OPTIMIZATION_LEVEL = 0; 173 | GCC_PREPROCESSOR_DEFINITIONS = ( 174 | "DEBUG=1", 175 | "$(inherited)", 176 | ); 177 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 178 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 179 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 180 | GCC_WARN_UNDECLARED_SELECTOR = YES; 181 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 182 | GCC_WARN_UNUSED_FUNCTION = YES; 183 | GCC_WARN_UNUSED_VARIABLE = YES; 184 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 185 | MTL_ENABLE_DEBUG_INFO = YES; 186 | ONLY_ACTIVE_ARCH = YES; 187 | SDKROOT = iphoneos; 188 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 189 | TARGETED_DEVICE_FAMILY = "1,2"; 190 | VERSIONING_SYSTEM = "apple-generic"; 191 | VERSION_INFO_PREFIX = ""; 192 | }; 193 | name = Debug; 194 | }; 195 | FCD3580A1AEC5585005F3188 /* Release */ = { 196 | isa = XCBuildConfiguration; 197 | buildSettings = { 198 | ALWAYS_SEARCH_USER_PATHS = NO; 199 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 200 | CLANG_CXX_LIBRARY = "libc++"; 201 | CLANG_ENABLE_MODULES = YES; 202 | CLANG_ENABLE_OBJC_ARC = YES; 203 | CLANG_WARN_BOOL_CONVERSION = YES; 204 | CLANG_WARN_CONSTANT_CONVERSION = YES; 205 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 206 | CLANG_WARN_EMPTY_BODY = YES; 207 | CLANG_WARN_ENUM_CONVERSION = YES; 208 | CLANG_WARN_INT_CONVERSION = YES; 209 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 210 | CLANG_WARN_UNREACHABLE_CODE = YES; 211 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 212 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 213 | COPY_PHASE_STRIP = NO; 214 | CURRENT_PROJECT_VERSION = 1; 215 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 216 | ENABLE_NS_ASSERTIONS = NO; 217 | ENABLE_STRICT_OBJC_MSGSEND = YES; 218 | GCC_C_LANGUAGE_STANDARD = gnu99; 219 | GCC_NO_COMMON_BLOCKS = YES; 220 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 221 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 222 | GCC_WARN_UNDECLARED_SELECTOR = YES; 223 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 224 | GCC_WARN_UNUSED_FUNCTION = YES; 225 | GCC_WARN_UNUSED_VARIABLE = YES; 226 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 227 | MTL_ENABLE_DEBUG_INFO = NO; 228 | SDKROOT = iphoneos; 229 | TARGETED_DEVICE_FAMILY = "1,2"; 230 | VALIDATE_PRODUCT = YES; 231 | VERSIONING_SYSTEM = "apple-generic"; 232 | VERSION_INFO_PREFIX = ""; 233 | }; 234 | name = Release; 235 | }; 236 | FCD3580C1AEC5586005F3188 /* Debug */ = { 237 | isa = XCBuildConfiguration; 238 | buildSettings = { 239 | CLANG_ENABLE_MODULES = YES; 240 | DEFINES_MODULE = YES; 241 | DYLIB_COMPATIBILITY_VERSION = 1; 242 | DYLIB_CURRENT_VERSION = 1; 243 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 244 | INFOPLIST_FILE = Source/Info.plist; 245 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 246 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 247 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 248 | PRODUCT_NAME = "$(TARGET_NAME)"; 249 | SDKROOT = iphoneos8.1; 250 | SKIP_INSTALL = YES; 251 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 252 | }; 253 | name = Debug; 254 | }; 255 | FCD3580D1AEC5586005F3188 /* Release */ = { 256 | isa = XCBuildConfiguration; 257 | buildSettings = { 258 | CLANG_ENABLE_MODULES = YES; 259 | DEFINES_MODULE = YES; 260 | DYLIB_COMPATIBILITY_VERSION = 1; 261 | DYLIB_CURRENT_VERSION = 1; 262 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 263 | INFOPLIST_FILE = Source/Info.plist; 264 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 265 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 266 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 267 | PRODUCT_NAME = "$(TARGET_NAME)"; 268 | SDKROOT = iphoneos8.1; 269 | SKIP_INSTALL = YES; 270 | }; 271 | name = Release; 272 | }; 273 | /* End XCBuildConfiguration section */ 274 | 275 | /* Begin XCConfigurationList section */ 276 | FCD357EF1AEC5585005F3188 /* Build configuration list for PBXProject "SCCollectionViewController" */ = { 277 | isa = XCConfigurationList; 278 | buildConfigurations = ( 279 | FCD358091AEC5585005F3188 /* Debug */, 280 | FCD3580A1AEC5585005F3188 /* Release */, 281 | ); 282 | defaultConfigurationIsVisible = 0; 283 | defaultConfigurationName = Release; 284 | }; 285 | FCD3580B1AEC5586005F3188 /* Build configuration list for PBXNativeTarget "SCCollectionViewController" */ = { 286 | isa = XCConfigurationList; 287 | buildConfigurations = ( 288 | FCD3580C1AEC5586005F3188 /* Debug */, 289 | FCD3580D1AEC5586005F3188 /* Release */, 290 | ); 291 | defaultConfigurationIsVisible = 0; 292 | defaultConfigurationName = Release; 293 | }; 294 | /* End XCConfigurationList section */ 295 | }; 296 | rootObject = FCD357EC1AEC5585005F3188 /* Project object */; 297 | } 298 | -------------------------------------------------------------------------------- /SCCollectionViewController.xcodeproj/xcshareddata/xcschemes/SCCollectionViewController.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 75 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 94 | 100 | 101 | 102 | 103 | 105 | 106 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /SCCollectionViewController.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Sample/Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, 8.0 2 | pod 'SCCollectionViewController', :path => '../' 3 | -------------------------------------------------------------------------------- /Sample/Sample.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | FC160D041AFE5CD000B8FE6C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = FCD358521AEC5BA3005F3188 /* Main.storyboard */; }; 11 | FC160D051AFE5CD300B8FE6C /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = FCD358501AEC5BA3005F3188 /* LaunchScreen.xib */; }; 12 | FC9C25611AFE59DE00FC6A97 /* SCCollectionViewController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FCD358671AEC5D33005F3188 /* SCCollectionViewController.framework */; }; 13 | FC9C25621AFE59DE00FC6A97 /* SCCollectionViewController.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = FCD358671AEC5D33005F3188 /* SCCollectionViewController.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 14 | FCD358571AEC5BA3005F3188 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCD3584F1AEC5BA3005F3188 /* AppDelegate.swift */; }; 15 | FCD3585A1AEC5BA3005F3188 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = FCD358541AEC5BA3005F3188 /* Images.xcassets */; }; 16 | FCD3585E1AEC5BFA005F3188 /* SubclassExampleController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCD3585D1AEC5BFA005F3188 /* SubclassExampleController.swift */; }; 17 | FCD3586C1AEC5E26005F3188 /* CustomNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCD3586B1AEC5E26005F3188 /* CustomNavigationController.swift */; }; 18 | /* End PBXBuildFile section */ 19 | 20 | /* Begin PBXContainerItemProxy section */ 21 | FC9C25631AFE59DE00FC6A97 /* PBXContainerItemProxy */ = { 22 | isa = PBXContainerItemProxy; 23 | containerPortal = FCD358621AEC5D33005F3188 /* SCCollectionViewController.xcodeproj */; 24 | proxyType = 1; 25 | remoteGlobalIDString = FCD357F41AEC5585005F3188; 26 | remoteInfo = SCCollectionViewController; 27 | }; 28 | FCD358661AEC5D33005F3188 /* PBXContainerItemProxy */ = { 29 | isa = PBXContainerItemProxy; 30 | containerPortal = FCD358621AEC5D33005F3188 /* SCCollectionViewController.xcodeproj */; 31 | proxyType = 2; 32 | remoteGlobalIDString = FCD357F51AEC5585005F3188; 33 | remoteInfo = SCCollectionViewController; 34 | }; 35 | FCD358681AEC5D38005F3188 /* PBXContainerItemProxy */ = { 36 | isa = PBXContainerItemProxy; 37 | containerPortal = FCD358621AEC5D33005F3188 /* SCCollectionViewController.xcodeproj */; 38 | proxyType = 1; 39 | remoteGlobalIDString = FCD357F41AEC5585005F3188; 40 | remoteInfo = SCCollectionViewController; 41 | }; 42 | /* End PBXContainerItemProxy section */ 43 | 44 | /* Begin PBXCopyFilesBuildPhase section */ 45 | FC9C25651AFE59DE00FC6A97 /* Embed Frameworks */ = { 46 | isa = PBXCopyFilesBuildPhase; 47 | buildActionMask = 2147483647; 48 | dstPath = ""; 49 | dstSubfolderSpec = 10; 50 | files = ( 51 | FC9C25621AFE59DE00FC6A97 /* SCCollectionViewController.framework in Embed Frameworks */, 52 | ); 53 | name = "Embed Frameworks"; 54 | runOnlyForDeploymentPostprocessing = 0; 55 | }; 56 | /* End PBXCopyFilesBuildPhase section */ 57 | 58 | /* Begin PBXFileReference section */ 59 | FCD358231AEC5A31005F3188 /* Sample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Sample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 60 | FCD3584F1AEC5BA3005F3188 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 61 | FCD358511AEC5BA3005F3188 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 62 | FCD358531AEC5BA3005F3188 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 63 | FCD358541AEC5BA3005F3188 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 64 | FCD358551AEC5BA3005F3188 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 65 | FCD3585D1AEC5BFA005F3188 /* SubclassExampleController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SubclassExampleController.swift; sourceTree = ""; }; 66 | FCD358621AEC5D33005F3188 /* SCCollectionViewController.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = SCCollectionViewController.xcodeproj; path = ../SCCollectionViewController.xcodeproj; sourceTree = ""; }; 67 | FCD3586B1AEC5E26005F3188 /* CustomNavigationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomNavigationController.swift; sourceTree = ""; }; 68 | /* End PBXFileReference section */ 69 | 70 | /* Begin PBXFrameworksBuildPhase section */ 71 | FCD358201AEC5A31005F3188 /* Frameworks */ = { 72 | isa = PBXFrameworksBuildPhase; 73 | buildActionMask = 2147483647; 74 | files = ( 75 | FC9C25611AFE59DE00FC6A97 /* SCCollectionViewController.framework in Frameworks */, 76 | ); 77 | runOnlyForDeploymentPostprocessing = 0; 78 | }; 79 | /* End PBXFrameworksBuildPhase section */ 80 | 81 | /* Begin PBXGroup section */ 82 | FCD3581A1AEC5A31005F3188 = { 83 | isa = PBXGroup; 84 | children = ( 85 | FCD358621AEC5D33005F3188 /* SCCollectionViewController.xcodeproj */, 86 | FCD3584E1AEC5BA3005F3188 /* Source */, 87 | FCD358241AEC5A31005F3188 /* Products */, 88 | ); 89 | sourceTree = ""; 90 | }; 91 | FCD358241AEC5A31005F3188 /* Products */ = { 92 | isa = PBXGroup; 93 | children = ( 94 | FCD358231AEC5A31005F3188 /* Sample.app */, 95 | ); 96 | name = Products; 97 | sourceTree = ""; 98 | }; 99 | FCD3584E1AEC5BA3005F3188 /* Source */ = { 100 | isa = PBXGroup; 101 | children = ( 102 | FCD3584F1AEC5BA3005F3188 /* AppDelegate.swift */, 103 | FCD3586B1AEC5E26005F3188 /* CustomNavigationController.swift */, 104 | FCD3585D1AEC5BFA005F3188 /* SubclassExampleController.swift */, 105 | FCD358541AEC5BA3005F3188 /* Images.xcassets */, 106 | FCD358501AEC5BA3005F3188 /* LaunchScreen.xib */, 107 | FCD358521AEC5BA3005F3188 /* Main.storyboard */, 108 | FCD358551AEC5BA3005F3188 /* Info.plist */, 109 | ); 110 | path = Source; 111 | sourceTree = ""; 112 | }; 113 | FCD358631AEC5D33005F3188 /* Products */ = { 114 | isa = PBXGroup; 115 | children = ( 116 | FCD358671AEC5D33005F3188 /* SCCollectionViewController.framework */, 117 | ); 118 | name = Products; 119 | sourceTree = ""; 120 | }; 121 | /* End PBXGroup section */ 122 | 123 | /* Begin PBXNativeTarget section */ 124 | FCD358221AEC5A31005F3188 /* Sample */ = { 125 | isa = PBXNativeTarget; 126 | buildConfigurationList = FCD358421AEC5A31005F3188 /* Build configuration list for PBXNativeTarget "Sample" */; 127 | buildPhases = ( 128 | FCD3581F1AEC5A31005F3188 /* Sources */, 129 | FCD358201AEC5A31005F3188 /* Frameworks */, 130 | FCD358211AEC5A31005F3188 /* Resources */, 131 | FC9C25651AFE59DE00FC6A97 /* Embed Frameworks */, 132 | ); 133 | buildRules = ( 134 | ); 135 | dependencies = ( 136 | FCD358691AEC5D38005F3188 /* PBXTargetDependency */, 137 | FC9C25641AFE59DE00FC6A97 /* PBXTargetDependency */, 138 | ); 139 | name = Sample; 140 | productName = Sample; 141 | productReference = FCD358231AEC5A31005F3188 /* Sample.app */; 142 | productType = "com.apple.product-type.application"; 143 | }; 144 | /* End PBXNativeTarget section */ 145 | 146 | /* Begin PBXProject section */ 147 | FCD3581B1AEC5A31005F3188 /* Project object */ = { 148 | isa = PBXProject; 149 | attributes = { 150 | LastUpgradeCheck = 0630; 151 | ORGANIZATIONNAME = "Benoit Layer"; 152 | TargetAttributes = { 153 | FCD358221AEC5A31005F3188 = { 154 | CreatedOnToolsVersion = 6.3; 155 | }; 156 | }; 157 | }; 158 | buildConfigurationList = FCD3581E1AEC5A31005F3188 /* Build configuration list for PBXProject "Sample" */; 159 | compatibilityVersion = "Xcode 3.2"; 160 | developmentRegion = English; 161 | hasScannedForEncodings = 0; 162 | knownRegions = ( 163 | en, 164 | Base, 165 | ); 166 | mainGroup = FCD3581A1AEC5A31005F3188; 167 | productRefGroup = FCD358241AEC5A31005F3188 /* Products */; 168 | projectDirPath = ""; 169 | projectReferences = ( 170 | { 171 | ProductGroup = FCD358631AEC5D33005F3188 /* Products */; 172 | ProjectRef = FCD358621AEC5D33005F3188 /* SCCollectionViewController.xcodeproj */; 173 | }, 174 | ); 175 | projectRoot = ""; 176 | targets = ( 177 | FCD358221AEC5A31005F3188 /* Sample */, 178 | ); 179 | }; 180 | /* End PBXProject section */ 181 | 182 | /* Begin PBXReferenceProxy section */ 183 | FCD358671AEC5D33005F3188 /* SCCollectionViewController.framework */ = { 184 | isa = PBXReferenceProxy; 185 | fileType = wrapper.framework; 186 | path = SCCollectionViewController.framework; 187 | remoteRef = FCD358661AEC5D33005F3188 /* PBXContainerItemProxy */; 188 | sourceTree = BUILT_PRODUCTS_DIR; 189 | }; 190 | /* End PBXReferenceProxy section */ 191 | 192 | /* Begin PBXResourcesBuildPhase section */ 193 | FCD358211AEC5A31005F3188 /* Resources */ = { 194 | isa = PBXResourcesBuildPhase; 195 | buildActionMask = 2147483647; 196 | files = ( 197 | FC160D051AFE5CD300B8FE6C /* LaunchScreen.xib in Resources */, 198 | FC160D041AFE5CD000B8FE6C /* Main.storyboard in Resources */, 199 | FCD3585A1AEC5BA3005F3188 /* Images.xcassets in Resources */, 200 | ); 201 | runOnlyForDeploymentPostprocessing = 0; 202 | }; 203 | /* End PBXResourcesBuildPhase section */ 204 | 205 | /* Begin PBXSourcesBuildPhase section */ 206 | FCD3581F1AEC5A31005F3188 /* Sources */ = { 207 | isa = PBXSourcesBuildPhase; 208 | buildActionMask = 2147483647; 209 | files = ( 210 | FCD3586C1AEC5E26005F3188 /* CustomNavigationController.swift in Sources */, 211 | FCD3585E1AEC5BFA005F3188 /* SubclassExampleController.swift in Sources */, 212 | FCD358571AEC5BA3005F3188 /* AppDelegate.swift in Sources */, 213 | ); 214 | runOnlyForDeploymentPostprocessing = 0; 215 | }; 216 | /* End PBXSourcesBuildPhase section */ 217 | 218 | /* Begin PBXTargetDependency section */ 219 | FC9C25641AFE59DE00FC6A97 /* PBXTargetDependency */ = { 220 | isa = PBXTargetDependency; 221 | name = SCCollectionViewController; 222 | targetProxy = FC9C25631AFE59DE00FC6A97 /* PBXContainerItemProxy */; 223 | }; 224 | FCD358691AEC5D38005F3188 /* PBXTargetDependency */ = { 225 | isa = PBXTargetDependency; 226 | name = SCCollectionViewController; 227 | targetProxy = FCD358681AEC5D38005F3188 /* PBXContainerItemProxy */; 228 | }; 229 | /* End PBXTargetDependency section */ 230 | 231 | /* Begin PBXVariantGroup section */ 232 | FCD358501AEC5BA3005F3188 /* LaunchScreen.xib */ = { 233 | isa = PBXVariantGroup; 234 | children = ( 235 | FCD358511AEC5BA3005F3188 /* Base */, 236 | ); 237 | name = LaunchScreen.xib; 238 | sourceTree = ""; 239 | }; 240 | FCD358521AEC5BA3005F3188 /* Main.storyboard */ = { 241 | isa = PBXVariantGroup; 242 | children = ( 243 | FCD358531AEC5BA3005F3188 /* Base */, 244 | ); 245 | name = Main.storyboard; 246 | sourceTree = ""; 247 | }; 248 | /* End PBXVariantGroup section */ 249 | 250 | /* Begin XCBuildConfiguration section */ 251 | FCD358401AEC5A31005F3188 /* Debug */ = { 252 | isa = XCBuildConfiguration; 253 | buildSettings = { 254 | ALWAYS_SEARCH_USER_PATHS = NO; 255 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 256 | CLANG_CXX_LIBRARY = "libc++"; 257 | CLANG_ENABLE_MODULES = YES; 258 | CLANG_ENABLE_OBJC_ARC = YES; 259 | CLANG_WARN_BOOL_CONVERSION = YES; 260 | CLANG_WARN_CONSTANT_CONVERSION = YES; 261 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 262 | CLANG_WARN_EMPTY_BODY = YES; 263 | CLANG_WARN_ENUM_CONVERSION = YES; 264 | CLANG_WARN_INT_CONVERSION = YES; 265 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 266 | CLANG_WARN_UNREACHABLE_CODE = YES; 267 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 268 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 269 | COPY_PHASE_STRIP = NO; 270 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 271 | ENABLE_STRICT_OBJC_MSGSEND = YES; 272 | GCC_C_LANGUAGE_STANDARD = gnu99; 273 | GCC_DYNAMIC_NO_PIC = NO; 274 | GCC_NO_COMMON_BLOCKS = YES; 275 | GCC_OPTIMIZATION_LEVEL = 0; 276 | GCC_PREPROCESSOR_DEFINITIONS = ( 277 | "DEBUG=1", 278 | "$(inherited)", 279 | ); 280 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 281 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 282 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 283 | GCC_WARN_UNDECLARED_SELECTOR = YES; 284 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 285 | GCC_WARN_UNUSED_FUNCTION = YES; 286 | GCC_WARN_UNUSED_VARIABLE = YES; 287 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 288 | MTL_ENABLE_DEBUG_INFO = YES; 289 | ONLY_ACTIVE_ARCH = YES; 290 | SDKROOT = iphoneos; 291 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 292 | }; 293 | name = Debug; 294 | }; 295 | FCD358411AEC5A31005F3188 /* Release */ = { 296 | isa = XCBuildConfiguration; 297 | buildSettings = { 298 | ALWAYS_SEARCH_USER_PATHS = NO; 299 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 300 | CLANG_CXX_LIBRARY = "libc++"; 301 | CLANG_ENABLE_MODULES = YES; 302 | CLANG_ENABLE_OBJC_ARC = YES; 303 | CLANG_WARN_BOOL_CONVERSION = YES; 304 | CLANG_WARN_CONSTANT_CONVERSION = YES; 305 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 306 | CLANG_WARN_EMPTY_BODY = YES; 307 | CLANG_WARN_ENUM_CONVERSION = YES; 308 | CLANG_WARN_INT_CONVERSION = YES; 309 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 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 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 315 | ENABLE_NS_ASSERTIONS = NO; 316 | ENABLE_STRICT_OBJC_MSGSEND = YES; 317 | GCC_C_LANGUAGE_STANDARD = gnu99; 318 | GCC_NO_COMMON_BLOCKS = YES; 319 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 320 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 321 | GCC_WARN_UNDECLARED_SELECTOR = YES; 322 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 323 | GCC_WARN_UNUSED_FUNCTION = YES; 324 | GCC_WARN_UNUSED_VARIABLE = YES; 325 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 326 | MTL_ENABLE_DEBUG_INFO = NO; 327 | SDKROOT = iphoneos; 328 | VALIDATE_PRODUCT = YES; 329 | }; 330 | name = Release; 331 | }; 332 | FCD358431AEC5A31005F3188 /* Debug */ = { 333 | isa = XCBuildConfiguration; 334 | buildSettings = { 335 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 336 | FRAMEWORK_SEARCH_PATHS = "$(inherited)"; 337 | INFOPLIST_FILE = Source/Info.plist; 338 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 339 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 340 | PRODUCT_NAME = "$(TARGET_NAME)"; 341 | SDKROOT = iphoneos8.1; 342 | }; 343 | name = Debug; 344 | }; 345 | FCD358441AEC5A31005F3188 /* Release */ = { 346 | isa = XCBuildConfiguration; 347 | buildSettings = { 348 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 349 | FRAMEWORK_SEARCH_PATHS = "$(inherited)"; 350 | INFOPLIST_FILE = Source/Info.plist; 351 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 352 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 353 | PRODUCT_NAME = "$(TARGET_NAME)"; 354 | SDKROOT = iphoneos8.1; 355 | }; 356 | name = Release; 357 | }; 358 | /* End XCBuildConfiguration section */ 359 | 360 | /* Begin XCConfigurationList section */ 361 | FCD3581E1AEC5A31005F3188 /* Build configuration list for PBXProject "Sample" */ = { 362 | isa = XCConfigurationList; 363 | buildConfigurations = ( 364 | FCD358401AEC5A31005F3188 /* Debug */, 365 | FCD358411AEC5A31005F3188 /* Release */, 366 | ); 367 | defaultConfigurationIsVisible = 0; 368 | defaultConfigurationName = Release; 369 | }; 370 | FCD358421AEC5A31005F3188 /* Build configuration list for PBXNativeTarget "Sample" */ = { 371 | isa = XCConfigurationList; 372 | buildConfigurations = ( 373 | FCD358431AEC5A31005F3188 /* Debug */, 374 | FCD358441AEC5A31005F3188 /* Release */, 375 | ); 376 | defaultConfigurationIsVisible = 0; 377 | defaultConfigurationName = Release; 378 | }; 379 | /* End XCConfigurationList section */ 380 | }; 381 | rootObject = FCD3581B1AEC5A31005F3188 /* Project object */; 382 | } 383 | -------------------------------------------------------------------------------- /Sample/Sample.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Sample/Sample.xcodeproj/xcshareddata/xcschemes/Sample.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 75 | 77 | 83 | 84 | 85 | 86 | 87 | 88 | 94 | 96 | 102 | 103 | 104 | 105 | 107 | 108 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /Sample/Source/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Benoit Layer 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | import UIKit 22 | 23 | @UIApplicationMain 24 | class AppDelegate: UIResponder, UIApplicationDelegate { 25 | 26 | var window: UIWindow? 27 | 28 | 29 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 30 | // Override point for customization after application launch. 31 | return true 32 | } 33 | 34 | func applicationWillResignActive(application: UIApplication) { 35 | // 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. 36 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 37 | } 38 | 39 | func applicationDidEnterBackground(application: UIApplication) { 40 | // 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. 41 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 42 | } 43 | 44 | func applicationWillEnterForeground(application: UIApplication) { 45 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 46 | } 47 | 48 | func applicationDidBecomeActive(application: UIApplication) { 49 | // 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. 50 | } 51 | 52 | func applicationWillTerminate(application: UIApplication) { 53 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 54 | } 55 | 56 | 57 | } 58 | 59 | -------------------------------------------------------------------------------- /Sample/Source/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Sample/Source/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 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 | -------------------------------------------------------------------------------- /Sample/Source/CustomNavigationController.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Benoit Layer 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | import UIKit 22 | 23 | class CustomNavigationController: UINavigationController { 24 | 25 | override func preferredStatusBarStyle() -> UIStatusBarStyle { 26 | return .LightContent 27 | } 28 | 29 | override func viewDidLoad() { 30 | super.viewDidLoad() 31 | self.navigationBar.tintColor = UIColor.whiteColor() 32 | self.navigationBar.barTintColor = UIColor(red: 99.0/255, green: 95.0/255, blue: 95.0/255, alpha: 1.0) 33 | self.navigationBar.backIndicatorImage = UIImage(named: "button_back") 34 | self.navigationBar.backIndicatorTransitionMaskImage = UIImage(named: "button_back") 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Sample/Source/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /Sample/Source/Images.xcassets/button_back.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "button_back.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "button_back@2x.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x", 16 | "filename" : "button_back@3x.png" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Sample/Source/Images.xcassets/button_back.imageset/button_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notbenoit/SCCollectionViewController/bd8f107ba1410dc6a7b5af9f525cc2ddd2aef473/Sample/Source/Images.xcassets/button_back.imageset/button_back.png -------------------------------------------------------------------------------- /Sample/Source/Images.xcassets/button_back.imageset/button_back@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notbenoit/SCCollectionViewController/bd8f107ba1410dc6a7b5af9f525cc2ddd2aef473/Sample/Source/Images.xcassets/button_back.imageset/button_back@2x.png -------------------------------------------------------------------------------- /Sample/Source/Images.xcassets/button_back.imageset/button_back@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notbenoit/SCCollectionViewController/bd8f107ba1410dc6a7b5af9f525cc2ddd2aef473/Sample/Source/Images.xcassets/button_back.imageset/button_back@3x.png -------------------------------------------------------------------------------- /Sample/Source/Images.xcassets/town.imageset/16075461243_f9dbe86321_z.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/notbenoit/SCCollectionViewController/bd8f107ba1410dc6a7b5af9f525cc2ddd2aef473/Sample/Source/Images.xcassets/town.imageset/16075461243_f9dbe86321_z.png -------------------------------------------------------------------------------- /Sample/Source/Images.xcassets/town.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "16075461243_f9dbe86321_z.png" 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 | } -------------------------------------------------------------------------------- /Sample/Source/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.notbenoit.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0.1 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /Sample/Source/SubclassExampleController.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Benoit Layer 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | import UIKit 22 | import SCCollectionViewController 23 | 24 | class SubclassExampleController: SCCollectionViewController { 25 | 26 | override func viewDidLoad() { 27 | super.viewDidLoad() 28 | 29 | // We want something fashion as our back button :) 30 | self.navigationItem.leftBarButtonItem = UIBarButtonItem(image: UIImage(named: "button_back"), style: .Plain, target: self, action: "back:") 31 | } 32 | 33 | func back(sender: UIButton) { 34 | self.navigationController?.popViewControllerAnimated(true) 35 | } 36 | 37 | override func configureHeader(header: UICollectionReusableView) { 38 | // Since the header is recycled, I check for the existence of the imageview. 39 | var imageView: UIImageView? = header.viewWithTag(0) as? UIImageView 40 | if let unwrappedImageView = imageView { 41 | 42 | } else { 43 | imageView = UIImageView(frame: header.bounds) 44 | imageView!.image = UIImage(named: "town") 45 | header.addSubview(imageView!) 46 | } 47 | } 48 | 49 | override func configureCell(cell: UICollectionViewCell, indexPath: NSIndexPath) { 50 | // Simple cell with just a background color. 51 | cell.backgroundColor = UIColor.lightGrayColor() 52 | } 53 | 54 | override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 55 | // Let's say we want 10 cells for the demo. 56 | return 10 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Source/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.notbenoit.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.1 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Source/SCCollectionViewController.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Benoit Layer 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | #import 22 | 23 | //! Project version number for SCCollectionViewController. 24 | FOUNDATION_EXPORT double SCCollectionViewControllerVersionNumber; 25 | 26 | //! Project version string for SCCollectionViewController. 27 | FOUNDATION_EXPORT const unsigned char SCCollectionViewControllerVersionString[]; 28 | 29 | // In this header, you should import all the public headers of your framework using statements like #import 30 | 31 | 32 | -------------------------------------------------------------------------------- /Source/SCCollectionViewController.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Benoit Layer 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | import UIKit 22 | 23 | public 24 | class SCCollectionViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout { 25 | 26 | // Set the cell margin (spacing between lines, columns, and left/right borders of the collectionview). Default to 5 27 | public var cellMargin: CGFloat = 5 28 | // Set the cell height. default to 120. 29 | public var cellHeight: CGFloat = 120 30 | // Set the base height for the header (height when not scaled up). 31 | public var headerBaseHeight: CGFloat = 170 32 | 33 | /** 34 | You must override this method to provide the number of cells to show below the header. 35 | */ 36 | public func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 37 | fatalError("You must override this dataSource method") 38 | } 39 | 40 | /** 41 | You must override this method to configure the header view as you like. 42 | 43 | :param: header The recycled UICollectionReusableView. 44 | */ 45 | public func configureHeader(header: UICollectionReusableView) { 46 | fatalError("You must override this method to configure the header view as you like.") 47 | } 48 | 49 | /** 50 | You must override this method to configure the cells to your convenience. 51 | 52 | :param: cell The recycled UICollectionViewCell. 53 | :param: indexPath The corresponding indexPath. 54 | */ 55 | public func configureCell(cell: UICollectionViewCell, indexPath: NSIndexPath) { 56 | fatalError("You must override this method to configure the cells as you like.") 57 | } 58 | 59 | private let reuseIdentifier = "Cell" 60 | private let headerReuseIdentifier = "Header" 61 | private var growingHeader: UIView? 62 | private let collectionView = UICollectionView(frame: CGRectZero, collectionViewLayout: UICollectionViewFlowLayout()) 63 | private let headerMask = CALayer() 64 | 65 | public override func preferredStatusBarStyle() -> UIStatusBarStyle { 66 | return .LightContent 67 | } 68 | 69 | override public func viewDidLoad() { 70 | super.viewDidLoad() 71 | 72 | // Register cell classes 73 | self.collectionView.registerClass(UICollectionReusableView.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: headerReuseIdentifier) 74 | self.collectionView.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier) 75 | 76 | // Configure UICollectionView 77 | collectionView.delegate = self 78 | collectionView.dataSource = self 79 | collectionView.frame = self.view.bounds 80 | collectionView.backgroundColor = UIColor.clearColor() 81 | collectionView.clipsToBounds = false 82 | 83 | // Let the scrollview go under navigationBar. 84 | self.automaticallyAdjustsScrollViewInsets = false 85 | 86 | // Hide the navigation bar at first 87 | if let unwrappedNavigationController = self.navigationController { 88 | unwrappedNavigationController.navigationBar.alpha = 0 89 | } 90 | 91 | headerMask.backgroundColor = UIColor(white: 1, alpha: 1).CGColor 92 | self.view.addSubview(collectionView) 93 | } 94 | 95 | public override func viewWillAppear(animated: Bool) { 96 | super.viewWillAppear(animated) 97 | if let unwrappedNavigationController = self.navigationController { 98 | self.transitionCoordinator()?.animateAlongsideTransition({ (context) -> Void in 99 | unwrappedNavigationController.navigationBar.alpha = 0 100 | }, completion: nil) 101 | } 102 | } 103 | 104 | public override func viewWillDisappear(animated: Bool) { 105 | super.viewWillDisappear(animated) 106 | if let unwrappedNavigationController = self.navigationController { 107 | self.transitionCoordinator()?.animateAlongsideTransition({ (context) -> Void in 108 | unwrappedNavigationController.navigationBar.alpha = 1 109 | }, completion: nil) 110 | } 111 | } 112 | 113 | override public func didReceiveMemoryWarning() { 114 | super.didReceiveMemoryWarning() 115 | // Dispose of any resources that can be recreated. 116 | } 117 | 118 | public override func viewDidLayoutSubviews() { 119 | super.viewDidLayoutSubviews() 120 | collectionView.frame = self.view.bounds 121 | } 122 | 123 | // MARK: UICollectionViewDelegateFlowLayout 124 | 125 | final public func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize { 126 | let numColumns: CGFloat = 1 127 | let edgeInset = self.collectionView(collectionView, layout: collectionViewLayout, insetForSectionAtIndex: indexPath.section) 128 | let spacingLeft = edgeInset.left 129 | let spacingRight = edgeInset.right 130 | let width = (collectionView.bounds.size.width - spacingLeft - spacingRight - cellMargin*(numColumns-1)) / numColumns 131 | return CGSize(width: width, height: cellHeight) 132 | } 133 | 134 | final public func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets { 135 | return UIEdgeInsets(top: cellMargin, left: cellMargin, bottom: cellMargin, right: cellMargin) 136 | } 137 | 138 | final public func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAtIndex section: Int) -> CGFloat { 139 | return cellMargin 140 | } 141 | 142 | final public func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAtIndex section: Int) -> CGFloat { 143 | return cellMargin 144 | } 145 | 146 | final public func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { 147 | return CGSize(width: collectionView.bounds.size.width, height: headerBaseHeight) 148 | } 149 | 150 | // MARK: UICollectionViewDataSource 151 | 152 | final public func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int { 153 | return 1 154 | } 155 | 156 | final public func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell { 157 | let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! UICollectionViewCell 158 | 159 | // Configure the cell 160 | cell.backgroundColor = UIColor.clearColor() 161 | configureCell(cell, indexPath: indexPath) 162 | return cell 163 | } 164 | 165 | final public func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView { 166 | if (kind == UICollectionElementKindSectionHeader) { 167 | let supplementaryView: UICollectionReusableView = collectionView.dequeueReusableSupplementaryViewOfKind(UICollectionElementKindSectionHeader, withReuseIdentifier: headerReuseIdentifier, forIndexPath: indexPath) as! UICollectionReusableView 168 | 169 | growingHeader = supplementaryView as UIView 170 | growingHeader!.clipsToBounds = false 171 | growingHeader!.backgroundColor = UIColor.clearColor() 172 | 173 | configureHeader(supplementaryView) 174 | 175 | growingHeader!.layer.mask = headerMask 176 | adjustHeaderMaskWithScrollOffset(collectionView.contentOffset.y) 177 | 178 | return supplementaryView 179 | } 180 | return UICollectionReusableView() 181 | } 182 | 183 | final public func scrollViewDidScroll(scrollView: UIScrollView) { 184 | if let unwrapperGrowingHeader = growingHeader { 185 | let scrollOffset = scrollView.contentOffset.y 186 | let scale = 1 + (min(0, scrollOffset * 0.011)) * (-1.0) 187 | var transform = CGAffineTransformMakeScale(scale, scale) 188 | if (scrollOffset <= 0) { 189 | transform = CGAffineTransformTranslate(transform, 0, min(0, scrollOffset*0.1)) 190 | } else { 191 | transform = CGAffineTransformTranslate(transform, 0, min(scrollOffset*0.5, 60)) 192 | } 193 | unwrapperGrowingHeader.transform = transform 194 | adjustHeaderMaskWithScrollOffset(scrollOffset) 195 | 196 | if let unwrappedNavigationController = self.navigationController { 197 | let barAlpha = max(0, min(1, (scrollOffset/80))) 198 | unwrappedNavigationController.navigationBar.alpha = barAlpha 199 | } 200 | } 201 | } 202 | 203 | private func adjustHeaderMaskWithScrollOffset(offset: CGFloat) { 204 | // Find bottom of header without growing effect 205 | let maskBottom = self.view.convertPoint(CGPoint(x: 0, y: headerBaseHeight-offset), toView: growingHeader) 206 | // We set appropriate frame to clip the header 207 | CATransaction.begin() 208 | CATransaction.setDisableActions(true) 209 | headerMask.frame = CGRectMake(0, 0, collectionView.bounds.size.width, maskBottom.y) 210 | CATransaction.commit() 211 | } 212 | } 213 | -------------------------------------------------------------------------------- /Source/SCNavigationBar.swift: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015 Benoit Layer 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a copy 4 | // of this software and associated documentation files (the "Software"), to deal 5 | // in the Software without restriction, including without limitation the rights 6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | // copies of the Software, and to permit persons to whom the Software is 8 | // furnished to do so, subject to the following conditions: 9 | // 10 | // The above copyright notice and this permission notice shall be included in 11 | // all copies or substantial portions of the Software. 12 | // 13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | // THE SOFTWARE. 20 | 21 | import UIKit 22 | 23 | /** 24 | * I did not override drawRect: to draw the background with a custom alpha, because 25 | * the rect passed as a paramterer to drawRect: does not 26 | * cover the status bar space 27 | * 28 | * Use this navigation bar as a standard navigation bar. The only thing 29 | * is that setting its alpha will only set the alpha of the bar background. 30 | * It takes the current barTintColor and creates a background with 31 | * corresponding alpha. 32 | **/ 33 | 34 | class SCNavigationBar: UINavigationBar { 35 | 36 | // Setting the alpha of the status bar only changes the background. 37 | override var alpha: CGFloat { 38 | get { 39 | return 1.0 40 | } 41 | set { 42 | self.setBackgroundImage(createImageBackgroundWithAlpha(newValue), forBarMetrics: UIBarMetrics.Default) 43 | self.shadowImage = UIImage() 44 | } 45 | } 46 | 47 | private func createImageBackgroundWithAlpha(alpha: CGFloat) -> UIImage { 48 | let rect = CGRectMake(0, 0, 1, 1); 49 | UIGraphicsBeginImageContext(rect.size); 50 | let context = UIGraphicsGetCurrentContext(); 51 | let color = CGColorCreateCopyWithAlpha(self.barTintColor?.CGColor, alpha) 52 | CGContextSetFillColorWithColor(context, color) 53 | CGContextFillRect(context, rect); 54 | let img = UIGraphicsGetImageFromCurrentImageContext(); 55 | UIGraphicsEndImageContext() 56 | return img 57 | } 58 | } 59 | --------------------------------------------------------------------------------