├── .gitignore ├── README.md ├── ScrollviewParallax.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── vfedronic.xcuserdatad │ │ └── WorkspaceSettings.xcsettings └── xcuserdata │ └── vfedronic.xcuserdatad │ └── xcschemes │ ├── ScrollviewParallax.xcscheme │ └── xcschememanagement.plist ├── ScrollviewParallax ├── AppDelegate.h ├── AppDelegate.m ├── Base.lproj │ ├── LaunchScreen.xib │ └── Main.storyboard ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Info.plist ├── ViewController.h ├── ViewController.m ├── main.m └── wind.jpg ├── ScrollviewParallaxTests ├── Info.plist └── ScrollviewParallaxTests.m ├── capture.gif └── docs ├── contentView.gif ├── step1.png ├── step3.1.gif ├── step3.2.gif ├── step3.3.gif ├── step3.gif ├── step4.1.gif └── step4.gif /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.swp 3 | *~.nib 4 | 5 | build/ 6 | 7 | *.pbxuser 8 | *.perspective 9 | *.perspectivev3 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Scrollview Parallax/Zoom/Stretch 2 | ================ 3 | 4 | Creating parallax effect on UIScrollView only using Auto Layout. 5 | This sample project is just an illustration of the article written by Pete Hare, that you can find here: 6 | 7 | [PETE SHARE's post on domesticcat.com](http://blog.domesticcat.com.au/ios/2014/03/19/creating-parallax-effect-on-uiscrollview-using-simple-constraints/) 8 | 9 | I saw in the comments that some people were asking for the code, so i think i could share this. 10 | 11 | ![preview](capture.gif "Preview") 12 | 13 | I tried to do it first by only using IB (Interface Builder), i rarely use IB, i usually do these things programmatically. 14 | And i must say that i am really not confortable with it, i had to restart from scratch several times. That's why i decided to also do the same thing with code, you might have a look, i think it makes it more clear. 15 | In the rest of the document i might also use visual format when i find it more easy to understand than screenshots of the IB. 16 | 17 | ## Step by Step notes 18 | 19 | There are some key points that you need to understand if you want to try to do this. 20 | I'd recommand you to first start by setting up the scrollview with the image view in top of the scrollcontent. 21 | Once you have this working you can start to setup the cool effect. 22 | 23 | ### Step 1 : Add the UIScrollview 24 | 25 | Add 4 constraints between the scrollview and the parent view in order to make it full screen. 26 | In my sample i am using the top layout guide to pin the view, but if you want something full screen (or transparency effect under navbar) you can attach to the top of the parent view. 27 | 28 | ![step1](docs/step1.png "Step 1") 29 | 30 | 31 | ### Step 2 : Add the Content View 32 | 33 | In this sample i am using a single child view to put all the scrollable content (notice that you can do differently). 34 | 35 | Here we are doing something very not intuitive for the content constraint. 36 | In order to make the scroll work you must put also four '0' space constraints (top, bottom, left, right) between the scroll content and the scrollview. 37 | 38 | ![step2](docs/contentView.gif "Step 2") 39 | 40 | ### Step 3 : Setup the content 41 | 42 | Now let's add the imageView as a child of the content view. 43 | 44 | Let's set the constraints on the image view, we add again 4 constraints to the image, 0 top, 0 left, 0 right, and let's put the height to some arbritary size (150). 45 | 46 | ![step3](docs/step3.gif "Step 3") 47 | 48 | At this point you should have a lot of warning in IB, we will fix it later. 49 | If you run you should see nothing, simply because a zero size view will respect all your constraint. 50 | 51 | So let's now set the content size. 52 | In the article Pete is giving a nice tip to set the width. We can just say that the width of the image should be equal to the with of the main controller view width (that is full screen :) 53 | In order to do that, you have to Control-drag from the main view to the imageview in the Interface Builder outline view. 54 | 55 | 56 | ![step3.1](docs/step3.1.gif "Step 3.1") 57 | 58 | Let's set the content height. 59 | You have now to add any additional views to the content. 60 | And As stated in apple doc: 61 | > You must make sure you create constraints for all the subviews inside a scroll view. For example, when defining the constraints for a view that doesn’t have an intrinsic content size, you’ll need more than just a leading edge 62 | > constraint—you must also create trailing edge, width, and height constraints. 63 | 64 | > *There cannot be any missing constraints, starting from one edge of the scroll view to the other.* 65 | 66 | In visual format, it could be expressed like that: 67 | 68 | V:|-0-[imageView(150)]-0-[subContentView(700)]-0-| 69 | 70 | |-0-[topImageView(==super)]-0-| 71 | 72 | |-0-[subContentView]-0-| 73 | 74 | ![step3.2](docs/step3.2.gif "Fully define the content size") 75 | 76 | If your subviews have intrinsic height, you can remove the height constraint. 77 | 78 | If you run now, you should have classic scrolling 79 | 80 | ![step3.3](docs/step3.3.gif "Classic scroll") 81 | 82 | 83 | 84 | ### Step 4 : Do the magic 85 | 86 | Ok here is the interesting part. 87 | What we want to do is to remove the top constraint of the image view to the parent view (scrollcontent view), and instead attach to the topGuide, and also to remove the height constraint: 88 | 89 | V:|-0-[imageView(150)].. --- replaced By --> V:[topGuide]-0-[imageView].. 90 | 91 | But by doing this we are violating the scroll content rule: 92 | 93 | > *There cannot be any missing constraints, starting from one edge of the scroll view to the other.* 94 | 95 | Because there is no more constraint starting from the top of the content view going to one of the subview (we broke the one going to the imageView). 96 | 97 | So as explained by Pete Hare in the article, we have to replace this missing constraint with a new one: 98 | 99 | V:|-0-[imageView(150)]-0-[subContentView(700)]-0-| --- replaced By --> @"V:|-150-[subContentView(700)]-0-|" 100 | 101 | You can find here an animated gif capture of this step, i don't know if it's really helpfull :), please let me know if you find it usefull. 102 | 103 | 104 | ![step4](docs/step4.gif "Final setup") 105 | 106 | 107 | If you try to run now, you will already have the cool effect. 108 | But if you try to scroll down, at some point you will have an exception in the console: 109 | 110 | Unable to simultaneously satisfy constraints. 111 | 112 | This is simply because at some point, when the bottom of the imageView reach the top of the screen, the top constraint to the topGuide cannot be satisfied, it would mean that the imageHeight is negative. 113 | 114 | The solution is to add an additional constraint to the top layout guide: 115 | 116 | V:[topGuide]-<=0-[imageView] 117 | 118 | in addition to 119 | 120 | V:[topGuide]-0-[imageView] 121 | 122 | And as we want the image top to stick as long as possible to the top of the screen, but to break when necessary, we just need to lower the priority: 123 | 124 | V:[topGuide]-=0@750-[imageView] 125 | 126 | (The default priority is 1000) 127 | 128 | 129 | ![step4.1](docs/step4.1.gif "Fix the statisfy error") 130 | 131 | 132 | But what happened to the image height? 133 | 134 | We removed the height constraint, so it's not managed by a constraint. Instead of that the first time the view is rendered the image will take the space available between the top guide and the other view in the content. And starting from that the layout engine will use the Content Compression Resistance Priority to decide how to resize the image?. As by default the priority is 750, it seems to be OK but it's probably better to lower the priority to 749 (it depends on the exact effect you want to achieve). 135 | 136 | ## Misc 137 | 138 | If you have some issues with the scroll bar not going to the top (leaving a small gap), you may have to disable the 'Adjust Scroll View Insets' in the property view of the ViewController. 139 | 140 | -------------------------------------------------------------------------------- /ScrollviewParallax.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 282E98891A1BF880007EF23E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 282E98881A1BF880007EF23E /* main.m */; }; 11 | 282E988C1A1BF880007EF23E /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 282E988B1A1BF880007EF23E /* AppDelegate.m */; }; 12 | 282E988F1A1BF880007EF23E /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 282E988E1A1BF880007EF23E /* ViewController.m */; }; 13 | 282E98921A1BF880007EF23E /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 282E98901A1BF880007EF23E /* Main.storyboard */; }; 14 | 282E98941A1BF880007EF23E /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 282E98931A1BF880007EF23E /* Images.xcassets */; }; 15 | 282E98971A1BF880007EF23E /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 282E98951A1BF880007EF23E /* LaunchScreen.xib */; }; 16 | 282E98A31A1BF880007EF23E /* ScrollviewParallaxTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 282E98A21A1BF880007EF23E /* ScrollviewParallaxTests.m */; }; 17 | 282E98AD1A1BFC9C007EF23E /* wind.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 282E98AC1A1BFC9C007EF23E /* wind.jpg */; }; 18 | /* End PBXBuildFile section */ 19 | 20 | /* Begin PBXContainerItemProxy section */ 21 | 282E989D1A1BF880007EF23E /* PBXContainerItemProxy */ = { 22 | isa = PBXContainerItemProxy; 23 | containerPortal = 282E987B1A1BF880007EF23E /* Project object */; 24 | proxyType = 1; 25 | remoteGlobalIDString = 282E98821A1BF880007EF23E; 26 | remoteInfo = ScrollviewParallax; 27 | }; 28 | /* End PBXContainerItemProxy section */ 29 | 30 | /* Begin PBXFileReference section */ 31 | 282E98831A1BF880007EF23E /* ScrollviewParallax.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ScrollviewParallax.app; sourceTree = BUILT_PRODUCTS_DIR; }; 32 | 282E98871A1BF880007EF23E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 33 | 282E98881A1BF880007EF23E /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 34 | 282E988A1A1BF880007EF23E /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 35 | 282E988B1A1BF880007EF23E /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 36 | 282E988D1A1BF880007EF23E /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 37 | 282E988E1A1BF880007EF23E /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 38 | 282E98911A1BF880007EF23E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 39 | 282E98931A1BF880007EF23E /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 40 | 282E98961A1BF880007EF23E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 41 | 282E989C1A1BF880007EF23E /* ScrollviewParallaxTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ScrollviewParallaxTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 42 | 282E98A11A1BF880007EF23E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 43 | 282E98A21A1BF880007EF23E /* ScrollviewParallaxTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ScrollviewParallaxTests.m; sourceTree = ""; }; 44 | 282E98AC1A1BFC9C007EF23E /* wind.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = wind.jpg; sourceTree = ""; }; 45 | /* End PBXFileReference section */ 46 | 47 | /* Begin PBXFrameworksBuildPhase section */ 48 | 282E98801A1BF880007EF23E /* Frameworks */ = { 49 | isa = PBXFrameworksBuildPhase; 50 | buildActionMask = 2147483647; 51 | files = ( 52 | ); 53 | runOnlyForDeploymentPostprocessing = 0; 54 | }; 55 | 282E98991A1BF880007EF23E /* Frameworks */ = { 56 | isa = PBXFrameworksBuildPhase; 57 | buildActionMask = 2147483647; 58 | files = ( 59 | ); 60 | runOnlyForDeploymentPostprocessing = 0; 61 | }; 62 | /* End PBXFrameworksBuildPhase section */ 63 | 64 | /* Begin PBXGroup section */ 65 | 282E987A1A1BF880007EF23E = { 66 | isa = PBXGroup; 67 | children = ( 68 | 282E98851A1BF880007EF23E /* ScrollviewParallax */, 69 | 282E989F1A1BF880007EF23E /* ScrollviewParallaxTests */, 70 | 282E98841A1BF880007EF23E /* Products */, 71 | ); 72 | sourceTree = ""; 73 | }; 74 | 282E98841A1BF880007EF23E /* Products */ = { 75 | isa = PBXGroup; 76 | children = ( 77 | 282E98831A1BF880007EF23E /* ScrollviewParallax.app */, 78 | 282E989C1A1BF880007EF23E /* ScrollviewParallaxTests.xctest */, 79 | ); 80 | name = Products; 81 | sourceTree = ""; 82 | }; 83 | 282E98851A1BF880007EF23E /* ScrollviewParallax */ = { 84 | isa = PBXGroup; 85 | children = ( 86 | 282E98AC1A1BFC9C007EF23E /* wind.jpg */, 87 | 282E988A1A1BF880007EF23E /* AppDelegate.h */, 88 | 282E988B1A1BF880007EF23E /* AppDelegate.m */, 89 | 282E988D1A1BF880007EF23E /* ViewController.h */, 90 | 282E988E1A1BF880007EF23E /* ViewController.m */, 91 | 282E98901A1BF880007EF23E /* Main.storyboard */, 92 | 282E98931A1BF880007EF23E /* Images.xcassets */, 93 | 282E98951A1BF880007EF23E /* LaunchScreen.xib */, 94 | 282E98861A1BF880007EF23E /* Supporting Files */, 95 | ); 96 | path = ScrollviewParallax; 97 | sourceTree = ""; 98 | }; 99 | 282E98861A1BF880007EF23E /* Supporting Files */ = { 100 | isa = PBXGroup; 101 | children = ( 102 | 282E98871A1BF880007EF23E /* Info.plist */, 103 | 282E98881A1BF880007EF23E /* main.m */, 104 | ); 105 | name = "Supporting Files"; 106 | sourceTree = ""; 107 | }; 108 | 282E989F1A1BF880007EF23E /* ScrollviewParallaxTests */ = { 109 | isa = PBXGroup; 110 | children = ( 111 | 282E98A21A1BF880007EF23E /* ScrollviewParallaxTests.m */, 112 | 282E98A01A1BF880007EF23E /* Supporting Files */, 113 | ); 114 | path = ScrollviewParallaxTests; 115 | sourceTree = ""; 116 | }; 117 | 282E98A01A1BF880007EF23E /* Supporting Files */ = { 118 | isa = PBXGroup; 119 | children = ( 120 | 282E98A11A1BF880007EF23E /* Info.plist */, 121 | ); 122 | name = "Supporting Files"; 123 | sourceTree = ""; 124 | }; 125 | /* End PBXGroup section */ 126 | 127 | /* Begin PBXNativeTarget section */ 128 | 282E98821A1BF880007EF23E /* ScrollviewParallax */ = { 129 | isa = PBXNativeTarget; 130 | buildConfigurationList = 282E98A61A1BF880007EF23E /* Build configuration list for PBXNativeTarget "ScrollviewParallax" */; 131 | buildPhases = ( 132 | 282E987F1A1BF880007EF23E /* Sources */, 133 | 282E98801A1BF880007EF23E /* Frameworks */, 134 | 282E98811A1BF880007EF23E /* Resources */, 135 | ); 136 | buildRules = ( 137 | ); 138 | dependencies = ( 139 | ); 140 | name = ScrollviewParallax; 141 | productName = ScrollviewParallax; 142 | productReference = 282E98831A1BF880007EF23E /* ScrollviewParallax.app */; 143 | productType = "com.apple.product-type.application"; 144 | }; 145 | 282E989B1A1BF880007EF23E /* ScrollviewParallaxTests */ = { 146 | isa = PBXNativeTarget; 147 | buildConfigurationList = 282E98A91A1BF880007EF23E /* Build configuration list for PBXNativeTarget "ScrollviewParallaxTests" */; 148 | buildPhases = ( 149 | 282E98981A1BF880007EF23E /* Sources */, 150 | 282E98991A1BF880007EF23E /* Frameworks */, 151 | 282E989A1A1BF880007EF23E /* Resources */, 152 | ); 153 | buildRules = ( 154 | ); 155 | dependencies = ( 156 | 282E989E1A1BF880007EF23E /* PBXTargetDependency */, 157 | ); 158 | name = ScrollviewParallaxTests; 159 | productName = ScrollviewParallaxTests; 160 | productReference = 282E989C1A1BF880007EF23E /* ScrollviewParallaxTests.xctest */; 161 | productType = "com.apple.product-type.bundle.unit-test"; 162 | }; 163 | /* End PBXNativeTarget section */ 164 | 165 | /* Begin PBXProject section */ 166 | 282E987B1A1BF880007EF23E /* Project object */ = { 167 | isa = PBXProject; 168 | attributes = { 169 | LastUpgradeCheck = 0600; 170 | ORGANIZATIONNAME = share; 171 | TargetAttributes = { 172 | 282E98821A1BF880007EF23E = { 173 | CreatedOnToolsVersion = 6.0.1; 174 | }; 175 | 282E989B1A1BF880007EF23E = { 176 | CreatedOnToolsVersion = 6.0.1; 177 | TestTargetID = 282E98821A1BF880007EF23E; 178 | }; 179 | }; 180 | }; 181 | buildConfigurationList = 282E987E1A1BF880007EF23E /* Build configuration list for PBXProject "ScrollviewParallax" */; 182 | compatibilityVersion = "Xcode 3.2"; 183 | developmentRegion = English; 184 | hasScannedForEncodings = 0; 185 | knownRegions = ( 186 | en, 187 | Base, 188 | ); 189 | mainGroup = 282E987A1A1BF880007EF23E; 190 | productRefGroup = 282E98841A1BF880007EF23E /* Products */; 191 | projectDirPath = ""; 192 | projectRoot = ""; 193 | targets = ( 194 | 282E98821A1BF880007EF23E /* ScrollviewParallax */, 195 | 282E989B1A1BF880007EF23E /* ScrollviewParallaxTests */, 196 | ); 197 | }; 198 | /* End PBXProject section */ 199 | 200 | /* Begin PBXResourcesBuildPhase section */ 201 | 282E98811A1BF880007EF23E /* Resources */ = { 202 | isa = PBXResourcesBuildPhase; 203 | buildActionMask = 2147483647; 204 | files = ( 205 | 282E98921A1BF880007EF23E /* Main.storyboard in Resources */, 206 | 282E98AD1A1BFC9C007EF23E /* wind.jpg in Resources */, 207 | 282E98971A1BF880007EF23E /* LaunchScreen.xib in Resources */, 208 | 282E98941A1BF880007EF23E /* Images.xcassets in Resources */, 209 | ); 210 | runOnlyForDeploymentPostprocessing = 0; 211 | }; 212 | 282E989A1A1BF880007EF23E /* Resources */ = { 213 | isa = PBXResourcesBuildPhase; 214 | buildActionMask = 2147483647; 215 | files = ( 216 | ); 217 | runOnlyForDeploymentPostprocessing = 0; 218 | }; 219 | /* End PBXResourcesBuildPhase section */ 220 | 221 | /* Begin PBXSourcesBuildPhase section */ 222 | 282E987F1A1BF880007EF23E /* Sources */ = { 223 | isa = PBXSourcesBuildPhase; 224 | buildActionMask = 2147483647; 225 | files = ( 226 | 282E988F1A1BF880007EF23E /* ViewController.m in Sources */, 227 | 282E988C1A1BF880007EF23E /* AppDelegate.m in Sources */, 228 | 282E98891A1BF880007EF23E /* main.m in Sources */, 229 | ); 230 | runOnlyForDeploymentPostprocessing = 0; 231 | }; 232 | 282E98981A1BF880007EF23E /* Sources */ = { 233 | isa = PBXSourcesBuildPhase; 234 | buildActionMask = 2147483647; 235 | files = ( 236 | 282E98A31A1BF880007EF23E /* ScrollviewParallaxTests.m in Sources */, 237 | ); 238 | runOnlyForDeploymentPostprocessing = 0; 239 | }; 240 | /* End PBXSourcesBuildPhase section */ 241 | 242 | /* Begin PBXTargetDependency section */ 243 | 282E989E1A1BF880007EF23E /* PBXTargetDependency */ = { 244 | isa = PBXTargetDependency; 245 | target = 282E98821A1BF880007EF23E /* ScrollviewParallax */; 246 | targetProxy = 282E989D1A1BF880007EF23E /* PBXContainerItemProxy */; 247 | }; 248 | /* End PBXTargetDependency section */ 249 | 250 | /* Begin PBXVariantGroup section */ 251 | 282E98901A1BF880007EF23E /* Main.storyboard */ = { 252 | isa = PBXVariantGroup; 253 | children = ( 254 | 282E98911A1BF880007EF23E /* Base */, 255 | ); 256 | name = Main.storyboard; 257 | sourceTree = ""; 258 | }; 259 | 282E98951A1BF880007EF23E /* LaunchScreen.xib */ = { 260 | isa = PBXVariantGroup; 261 | children = ( 262 | 282E98961A1BF880007EF23E /* Base */, 263 | ); 264 | name = LaunchScreen.xib; 265 | sourceTree = ""; 266 | }; 267 | /* End PBXVariantGroup section */ 268 | 269 | /* Begin XCBuildConfiguration section */ 270 | 282E98A41A1BF880007EF23E /* Debug */ = { 271 | isa = XCBuildConfiguration; 272 | buildSettings = { 273 | ALWAYS_SEARCH_USER_PATHS = NO; 274 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 275 | CLANG_CXX_LIBRARY = "libc++"; 276 | CLANG_ENABLE_MODULES = YES; 277 | CLANG_ENABLE_OBJC_ARC = YES; 278 | CLANG_WARN_BOOL_CONVERSION = YES; 279 | CLANG_WARN_CONSTANT_CONVERSION = YES; 280 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 281 | CLANG_WARN_EMPTY_BODY = YES; 282 | CLANG_WARN_ENUM_CONVERSION = YES; 283 | CLANG_WARN_INT_CONVERSION = YES; 284 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 285 | CLANG_WARN_UNREACHABLE_CODE = YES; 286 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 287 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 288 | COPY_PHASE_STRIP = NO; 289 | ENABLE_STRICT_OBJC_MSGSEND = YES; 290 | GCC_C_LANGUAGE_STANDARD = gnu99; 291 | GCC_DYNAMIC_NO_PIC = NO; 292 | GCC_OPTIMIZATION_LEVEL = 0; 293 | GCC_PREPROCESSOR_DEFINITIONS = ( 294 | "DEBUG=1", 295 | "$(inherited)", 296 | ); 297 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 298 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 299 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 300 | GCC_WARN_UNDECLARED_SELECTOR = YES; 301 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 302 | GCC_WARN_UNUSED_FUNCTION = YES; 303 | GCC_WARN_UNUSED_VARIABLE = YES; 304 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 305 | MTL_ENABLE_DEBUG_INFO = YES; 306 | ONLY_ACTIVE_ARCH = YES; 307 | SDKROOT = iphoneos; 308 | TARGETED_DEVICE_FAMILY = "1,2"; 309 | }; 310 | name = Debug; 311 | }; 312 | 282E98A51A1BF880007EF23E /* Release */ = { 313 | isa = XCBuildConfiguration; 314 | buildSettings = { 315 | ALWAYS_SEARCH_USER_PATHS = NO; 316 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 317 | CLANG_CXX_LIBRARY = "libc++"; 318 | CLANG_ENABLE_MODULES = YES; 319 | CLANG_ENABLE_OBJC_ARC = YES; 320 | CLANG_WARN_BOOL_CONVERSION = YES; 321 | CLANG_WARN_CONSTANT_CONVERSION = YES; 322 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 323 | CLANG_WARN_EMPTY_BODY = YES; 324 | CLANG_WARN_ENUM_CONVERSION = YES; 325 | CLANG_WARN_INT_CONVERSION = YES; 326 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 327 | CLANG_WARN_UNREACHABLE_CODE = YES; 328 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 329 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 330 | COPY_PHASE_STRIP = YES; 331 | ENABLE_NS_ASSERTIONS = NO; 332 | ENABLE_STRICT_OBJC_MSGSEND = YES; 333 | GCC_C_LANGUAGE_STANDARD = gnu99; 334 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 335 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 336 | GCC_WARN_UNDECLARED_SELECTOR = YES; 337 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 338 | GCC_WARN_UNUSED_FUNCTION = YES; 339 | GCC_WARN_UNUSED_VARIABLE = YES; 340 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 341 | MTL_ENABLE_DEBUG_INFO = NO; 342 | SDKROOT = iphoneos; 343 | TARGETED_DEVICE_FAMILY = "1,2"; 344 | VALIDATE_PRODUCT = YES; 345 | }; 346 | name = Release; 347 | }; 348 | 282E98A71A1BF880007EF23E /* Debug */ = { 349 | isa = XCBuildConfiguration; 350 | buildSettings = { 351 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 352 | INFOPLIST_FILE = ScrollviewParallax/Info.plist; 353 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 354 | PRODUCT_NAME = "$(TARGET_NAME)"; 355 | }; 356 | name = Debug; 357 | }; 358 | 282E98A81A1BF880007EF23E /* Release */ = { 359 | isa = XCBuildConfiguration; 360 | buildSettings = { 361 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 362 | INFOPLIST_FILE = ScrollviewParallax/Info.plist; 363 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 364 | PRODUCT_NAME = "$(TARGET_NAME)"; 365 | }; 366 | name = Release; 367 | }; 368 | 282E98AA1A1BF880007EF23E /* Debug */ = { 369 | isa = XCBuildConfiguration; 370 | buildSettings = { 371 | BUNDLE_LOADER = "$(TEST_HOST)"; 372 | FRAMEWORK_SEARCH_PATHS = ( 373 | "$(SDKROOT)/Developer/Library/Frameworks", 374 | "$(inherited)", 375 | ); 376 | GCC_PREPROCESSOR_DEFINITIONS = ( 377 | "DEBUG=1", 378 | "$(inherited)", 379 | ); 380 | INFOPLIST_FILE = ScrollviewParallaxTests/Info.plist; 381 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 382 | PRODUCT_NAME = "$(TARGET_NAME)"; 383 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ScrollviewParallax.app/ScrollviewParallax"; 384 | }; 385 | name = Debug; 386 | }; 387 | 282E98AB1A1BF880007EF23E /* Release */ = { 388 | isa = XCBuildConfiguration; 389 | buildSettings = { 390 | BUNDLE_LOADER = "$(TEST_HOST)"; 391 | FRAMEWORK_SEARCH_PATHS = ( 392 | "$(SDKROOT)/Developer/Library/Frameworks", 393 | "$(inherited)", 394 | ); 395 | INFOPLIST_FILE = ScrollviewParallaxTests/Info.plist; 396 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 397 | PRODUCT_NAME = "$(TARGET_NAME)"; 398 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ScrollviewParallax.app/ScrollviewParallax"; 399 | }; 400 | name = Release; 401 | }; 402 | /* End XCBuildConfiguration section */ 403 | 404 | /* Begin XCConfigurationList section */ 405 | 282E987E1A1BF880007EF23E /* Build configuration list for PBXProject "ScrollviewParallax" */ = { 406 | isa = XCConfigurationList; 407 | buildConfigurations = ( 408 | 282E98A41A1BF880007EF23E /* Debug */, 409 | 282E98A51A1BF880007EF23E /* Release */, 410 | ); 411 | defaultConfigurationIsVisible = 0; 412 | defaultConfigurationName = Release; 413 | }; 414 | 282E98A61A1BF880007EF23E /* Build configuration list for PBXNativeTarget "ScrollviewParallax" */ = { 415 | isa = XCConfigurationList; 416 | buildConfigurations = ( 417 | 282E98A71A1BF880007EF23E /* Debug */, 418 | 282E98A81A1BF880007EF23E /* Release */, 419 | ); 420 | defaultConfigurationIsVisible = 0; 421 | }; 422 | 282E98A91A1BF880007EF23E /* Build configuration list for PBXNativeTarget "ScrollviewParallaxTests" */ = { 423 | isa = XCConfigurationList; 424 | buildConfigurations = ( 425 | 282E98AA1A1BF880007EF23E /* Debug */, 426 | 282E98AB1A1BF880007EF23E /* Release */, 427 | ); 428 | defaultConfigurationIsVisible = 0; 429 | }; 430 | /* End XCConfigurationList section */ 431 | }; 432 | rootObject = 282E987B1A1BF880007EF23E /* Project object */; 433 | } 434 | -------------------------------------------------------------------------------- /ScrollviewParallax.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ScrollviewParallax.xcodeproj/project.xcworkspace/xcuserdata/vfedronic.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges 6 | 7 | SnapshotAutomaticallyBeforeSignificantChanges 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ScrollviewParallax.xcodeproj/xcuserdata/vfedronic.xcuserdatad/xcschemes/ScrollviewParallax.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 | -------------------------------------------------------------------------------- /ScrollviewParallax.xcodeproj/xcuserdata/vfedronic.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | ScrollviewParallax.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 282E98821A1BF880007EF23E 16 | 17 | primary 18 | 19 | 20 | 282E989B1A1BF880007EF23E 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /ScrollviewParallax/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // ScrollviewParallax 4 | // 5 | // Created by Valere on 18/11/14. 6 | // Copyright (c) 2014 share. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /ScrollviewParallax/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // ScrollviewParallax 4 | // 5 | // Created by Valere on 18/11/14. 6 | // Copyright (c) 2014 share. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // 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. 25 | // 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. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // 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. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // 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. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // 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. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /ScrollviewParallax/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 | -------------------------------------------------------------------------------- /ScrollviewParallax/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 | 45 | 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 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | -------------------------------------------------------------------------------- /ScrollviewParallax/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 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /ScrollviewParallax/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | org.share.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /ScrollviewParallax/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // ScrollviewParallax 4 | // 5 | // Created by Valere on 18/11/14. 6 | // Copyright (c) 2014 share. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /ScrollviewParallax/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // ScrollviewParallax 4 | // 5 | // Created by Valere on 18/11/14. 6 | // Copyright (c) 2014 share. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | 11 | @interface ViewController () 12 | 13 | @end 14 | 15 | @implementation ViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | // Do any additional setup after loading the view, typically from a nib. 20 | 21 | self.navigationItem.title = @"Programmatically"; 22 | 23 | NSMutableDictionary* views = [NSMutableDictionary new]; 24 | views[@"super"] = self.view; 25 | views[@"topGuide"] = self.topLayoutGuide; // The bottom of the navigation bar, if a navigation bar is visible. The bottom of the status bar, if only a status bar is visible .. etc... 26 | 27 | 28 | //Create the ScrollView 29 | UIScrollView* scrollView = [UIScrollView new]; 30 | scrollView.translatesAutoresizingMaskIntoConstraints = NO; //we are using auto layout 31 | self.automaticallyAdjustsScrollViewInsets = NO; 32 | [self.view addSubview:scrollView]; 33 | views[@"scrollView"] = scrollView; 34 | 35 | //Create the scrollview contentview 36 | UIView* contentView = [UIView new]; 37 | contentView.translatesAutoresizingMaskIntoConstraints = NO; //we are using auto layout 38 | [scrollView addSubview:contentView]; 39 | views[@"contentView"] = contentView; 40 | 41 | //Add the image view and other addtional views to the content view 42 | UIImageView* topImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"wind.jpg"]]; 43 | topImageView.translatesAutoresizingMaskIntoConstraints = NO; //we are using auto layout 44 | topImageView.contentMode = UIViewContentModeScaleAspectFill; 45 | topImageView.clipsToBounds = YES; 46 | [contentView addSubview:topImageView]; 47 | views[@"topImageView"] = topImageView; 48 | 49 | //Add other content to the scrollable view 50 | UIView* subContentView = [UIView new]; 51 | subContentView.translatesAutoresizingMaskIntoConstraints = NO; //we are using auto layout 52 | [contentView addSubview:subContentView]; 53 | views[@"subContentView"] = subContentView; 54 | 55 | 56 | //Now Let's do the layout 57 | NSArray* constraints; 58 | NSString* format; 59 | NSDictionary* metrics = @{@"imageHeight" : @150.0}; 60 | 61 | //======== ScrollView should take all available space ======== 62 | 63 | format = @"|-0-[scrollView]-0-|"; 64 | constraints = [NSLayoutConstraint constraintsWithVisualFormat:format options:0 metrics:nil views:views]; 65 | [self.view addConstraints:constraints]; 66 | 67 | format = @"V:[topGuide]-0-[scrollView]-0-|"; 68 | constraints = [NSLayoutConstraint constraintsWithVisualFormat:format options:0 metrics:nil views:views]; 69 | [self.view addConstraints:constraints]; 70 | 71 | 72 | 73 | //======== ScrollView Content should tie to all four edges of the scrollview ======== 74 | 75 | format = @"|-0-[contentView]-0-|"; 76 | constraints = [NSLayoutConstraint constraintsWithVisualFormat:format options:0 metrics:nil views:views]; 77 | [scrollView addConstraints:constraints]; 78 | 79 | format = @"V:|-0-[contentView]-0-|"; 80 | constraints = [NSLayoutConstraint constraintsWithVisualFormat:format options:0 metrics:nil views:views]; 81 | [scrollView addConstraints:constraints]; 82 | 83 | 84 | 85 | // ========== Layout the image horizontally 86 | 87 | format = @"|-0-[topImageView(==super)]-0-|"; // with trick to force content width 88 | constraints = [NSLayoutConstraint constraintsWithVisualFormat:format options:0 metrics:nil views:views]; 89 | [self.view addConstraints:constraints]; 90 | 91 | 92 | 93 | // ========== Put the sub view height, and leave room for image 94 | 95 | format = @"|-0-[subContentView]-0-|"; 96 | constraints = [NSLayoutConstraint constraintsWithVisualFormat:format options:0 metrics:nil views:views]; 97 | [scrollView addConstraints:constraints]; 98 | 99 | 100 | // we leave some space between the top for the image view 101 | format = @"V:|-imageHeight-[subContentView(700)]-0-|"; /*the view height is set to 700 for the example in order to have enough content */ 102 | constraints = [NSLayoutConstraint constraintsWithVisualFormat:format options:0 metrics:metrics views:views]; 103 | [scrollView addConstraints:constraints]; 104 | 105 | 106 | 107 | // Start of the magic 108 | 109 | format = @"V:[topImageView]-0-[subContentView]"; // image view bottom is subcontent top 110 | constraints = [NSLayoutConstraint constraintsWithVisualFormat:format options:0 metrics:nil views:views]; 111 | [contentView addConstraints:constraints]; 112 | 113 | // image view top is the top layout 114 | // But we lower the priority to let it break if you scroll enough to have the imageViewBottom higher than the top layout guide 115 | format = @"V:[topGuide]-0@750-[topImageView]"; 116 | constraints = [NSLayoutConstraint constraintsWithVisualFormat:format options:0 metrics:nil views:views]; 117 | [self.view addConstraints:constraints]; 118 | 119 | // so add a lower than rule with higher priority (1000) to let the previous rule break; 120 | format = @"V:[topGuide]-<=0-[topImageView]"; 121 | constraints = [NSLayoutConstraint constraintsWithVisualFormat:format options:0 metrics:nil views:views]; 122 | [self.view addConstraints:constraints]; 123 | 124 | 125 | 126 | //Optional stuff, Add The A view 127 | UILabel* aView = [UILabel new]; 128 | aView.text = @"A"; 129 | aView.translatesAutoresizingMaskIntoConstraints = NO; //we are using auto layout 130 | aView.backgroundColor = [UIColor colorWithRed:0.79 green:0.9 blue:0.69 alpha:1]; 131 | [aView setFont: [UIFont systemFontOfSize:44]]; 132 | aView.textColor = [UIColor whiteColor]; 133 | aView.textAlignment = NSTextAlignmentCenter; 134 | [subContentView addSubview:aView]; 135 | views[@"aView"] = aView; 136 | 137 | format = @"|-0-[aView(143)]"; 138 | constraints = [NSLayoutConstraint constraintsWithVisualFormat:format options:0 metrics:nil views:views]; 139 | [subContentView addConstraints:constraints]; 140 | 141 | format = @"V:|-0-[aView(127)]"; 142 | constraints = [NSLayoutConstraint constraintsWithVisualFormat:format options:0 metrics:nil views:views]; 143 | [subContentView addConstraints:constraints]; 144 | } 145 | 146 | - (void)didReceiveMemoryWarning { 147 | [super didReceiveMemoryWarning]; 148 | // Dispose of any resources that can be recreated. 149 | } 150 | 151 | @end 152 | -------------------------------------------------------------------------------- /ScrollviewParallax/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // ScrollviewParallax 4 | // 5 | // Created by Valere Fedronic on 18/11/14. 6 | // Copyright (c) 2014 share. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ScrollviewParallax/wind.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillCarsonFr/ScrollviewParallax/195df0f4b6711233745a0e5cdc15e0a098ff6502/ScrollviewParallax/wind.jpg -------------------------------------------------------------------------------- /ScrollviewParallaxTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | org.share.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /ScrollviewParallaxTests/ScrollviewParallaxTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // ScrollviewParallaxTests.m 3 | // ScrollviewParallaxTests 4 | // 5 | // Created by Valere Fedronic on 18/11/14. 6 | // Copyright (c) 2014 share. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface ScrollviewParallaxTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation ScrollviewParallaxTests 17 | 18 | - (void)setUp { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown { 24 | // Put teardown code here. This method is called after the invocation of each test method in the class. 25 | [super tearDown]; 26 | } 27 | 28 | - (void)testExample { 29 | // This is an example of a functional test case. 30 | XCTAssert(YES, @"Pass"); 31 | } 32 | 33 | - (void)testPerformanceExample { 34 | // This is an example of a performance test case. 35 | [self measureBlock:^{ 36 | // Put the code you want to measure the time of here. 37 | }]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /capture.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillCarsonFr/ScrollviewParallax/195df0f4b6711233745a0e5cdc15e0a098ff6502/capture.gif -------------------------------------------------------------------------------- /docs/contentView.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillCarsonFr/ScrollviewParallax/195df0f4b6711233745a0e5cdc15e0a098ff6502/docs/contentView.gif -------------------------------------------------------------------------------- /docs/step1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillCarsonFr/ScrollviewParallax/195df0f4b6711233745a0e5cdc15e0a098ff6502/docs/step1.png -------------------------------------------------------------------------------- /docs/step3.1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillCarsonFr/ScrollviewParallax/195df0f4b6711233745a0e5cdc15e0a098ff6502/docs/step3.1.gif -------------------------------------------------------------------------------- /docs/step3.2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillCarsonFr/ScrollviewParallax/195df0f4b6711233745a0e5cdc15e0a098ff6502/docs/step3.2.gif -------------------------------------------------------------------------------- /docs/step3.3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillCarsonFr/ScrollviewParallax/195df0f4b6711233745a0e5cdc15e0a098ff6502/docs/step3.3.gif -------------------------------------------------------------------------------- /docs/step3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillCarsonFr/ScrollviewParallax/195df0f4b6711233745a0e5cdc15e0a098ff6502/docs/step3.gif -------------------------------------------------------------------------------- /docs/step4.1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillCarsonFr/ScrollviewParallax/195df0f4b6711233745a0e5cdc15e0a098ff6502/docs/step4.1.gif -------------------------------------------------------------------------------- /docs/step4.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BillCarsonFr/ScrollviewParallax/195df0f4b6711233745a0e5cdc15e0a098ff6502/docs/step4.gif --------------------------------------------------------------------------------