├── .gitignore ├── LICENSE ├── MAGPagedScrollView.podspec ├── MAGPagedScrollView ├── PagedParallaxScrollView.swift ├── PagedReusableScrollView.swift ├── PagedScrollView.swift ├── PagedScrollViewContainerViewController.swift └── ParallaxViewProxy.swift ├── MAGPagedScrollViewDemo ├── MAGPagedScrollViewDemo.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata ├── MAGPagedScrollViewDemo │ ├── AppDelegate.swift │ ├── Base.lproj │ │ ├── LaunchScreen.xib │ │ └── Main.storyboard │ ├── Images.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── photo0.imageset │ │ │ ├── Contents.json │ │ │ └── photo0.jpg │ │ ├── photo1.imageset │ │ │ ├── Contents.json │ │ │ └── photo1.jpg │ │ ├── photo2.imageset │ │ │ ├── Contents.json │ │ │ └── photo2.jpg │ │ ├── photo3.imageset │ │ │ ├── Contents.json │ │ │ └── photo3.jpg │ │ └── photo4.imageset │ │ │ ├── Contents.json │ │ │ └── photo4.jpg │ ├── Info.plist │ ├── ParralaxCardViewController.swift │ ├── ParralaxCardViewController.xib │ ├── SimpleCardViewController.swift │ ├── SimpleCardViewController.xib │ ├── ViewController.swift │ ├── ViewController2.swift │ ├── ViewController3.swift │ └── ViewController4.swift └── MAGPagedScrollViewDemoTests │ ├── Info.plist │ └── MAGPagedScrollViewDemoTests.swift ├── README.md └── resources ├── Basic Cards.gif ├── CardsDemo.gif ├── DiveDemo.gif ├── MAGPagedScrollViewDemo.gif ├── MAGPagedScrollViewDemo.mov ├── ParallaxDemo.gif ├── ReusableDemo.gif ├── RollDemo.gif └── SlideDemo.gif /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | *.xccheckout 14 | *.moved-aside 15 | DerivedData 16 | *.hmap 17 | *.ipa 18 | *.xcuserstate 19 | 20 | # CocoaPods 21 | # 22 | # We recommend against adding the Pods directory to your .gitignore. However 23 | # you should judge for yourself, the pros and cons are mentioned at: 24 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 25 | # 26 | # Pods/ 27 | 28 | # Carthage 29 | # 30 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 31 | # Carthage/Checkouts 32 | 33 | Carthage/Build 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 MadAppGang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /MAGPagedScrollView.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "MAGPagedScrollView" 3 | s.version = "0.1.1" 4 | s.summary = "Paged managed scroll view from MadAppGang." 5 | 6 | s.description = <<-DESC 7 | MAGPagedScrollView is scroll view that managed subviews as pages 8 | 9 | Custom transitions: 10 | * None - regilar scroll 11 | * Slide 12 | * Dice 13 | * Roll 14 | * Cards 15 | * Custom 16 | 17 | ### YouTube: 18 | [![youtube](http://img.youtube.com/vi/4xZoOypS128/0.jpg)](http://www.youtube.com/watch?v=4xZoOypS128) 19 | DESC 20 | 21 | s.homepage = "https://github.com/MadAppGang/MAGPagedScrollView" 22 | 23 | s.license = "MIT" 24 | s.author = { "Ievgen Rudenko" => "i@madappgang.com" } 25 | 26 | s.platform = :ios, "8.0" 27 | s.source = { :git => "https://github.com/MadAppGang/MAGPagedScrollView.git", :tag => "0.1.1" } 28 | s.source_files = "MAGPagedScrollView", "MAGPagedScrollView/**/*.{swift}" 29 | s.requires_arc = true 30 | end 31 | -------------------------------------------------------------------------------- /MAGPagedScrollView/PagedParallaxScrollView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PagedParallaxScrollView.swift 3 | // MAGPagedScrollViewDemo 4 | // 5 | // Created by Ievgen Rudenko on 26/08/15. 6 | // Copyright (c) 2015 MadAppGang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | 12 | @objc public protocol PagedScrollViewParallaxDelegate: class { 13 | //parallax from -100 to 100. 0 is central position. 14 | func parallaxProgressChanged(progress:Int) 15 | } 16 | 17 | public class PagedParallaxScrollView: PagedReusableScrollView { 18 | 19 | override public func layoutSubviews() { 20 | super.layoutSubviews() 21 | for view in viewsOnScreen() { 22 | if let parallaxView = view as? PagedScrollViewParallaxDelegate { 23 | let oldTransform = view.layer.transform 24 | view.layer.transform = CATransform3DIdentity 25 | let centerDX = Int((view.frame.origin.x - contentOffset.x) * 100 / CGRectGetWidth(frame)) 26 | view.layer.transform = oldTransform 27 | parallaxView.parallaxProgressChanged(centerDX) 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /MAGPagedScrollView/PagedReusableScrollView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MAGPagedReusableScrollView.swift 3 | // MAGPagedScrollViewDemo 4 | // 5 | // Created by Ievgen Rudenko on 21/08/15. 6 | // Copyright (c) 2015 MadAppGang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @objc public protocol PagedReusableScrollViewDataSource { 12 | func scrollView(scrollView: PagedReusableScrollView, viewIndex index: Int) -> ViewProvider 13 | func numberOfViews(forScrollView scrollView: PagedReusableScrollView) -> Int 14 | 15 | optional func scrollView(scrollView scrollView: PagedReusableScrollView, willShowView view:ViewProvider) 16 | optional func scrollView(scrollView scrollView: PagedReusableScrollView, willHideView view:ViewProvider) 17 | optional func scrollView(scrollView scrollView: PagedReusableScrollView, didShowView view:ViewProvider) 18 | optional func scrollView(scrollView scrollView: PagedReusableScrollView, didHideView view:ViewProvider) 19 | 20 | } 21 | 22 | public class PagedReusableScrollView: PagedScrollView { 23 | 24 | @IBOutlet public weak var dataSource:PagedReusableScrollViewDataSource! { 25 | didSet { 26 | reload() 27 | } 28 | } 29 | 30 | 31 | 32 | override init(frame: CGRect) { 33 | super.init(frame: frame) 34 | reload() 35 | } 36 | 37 | required public init?(coder aDecoder: NSCoder) { 38 | super.init(coder: aDecoder) 39 | reload() 40 | } 41 | 42 | 43 | public func reload() { 44 | clearAllViews() 45 | if let ds = dataSource { 46 | viewsCount = ds.numberOfViews(forScrollView: self) 47 | resizeContent() 48 | reloadVisisbleViews() 49 | } 50 | setNeedsLayout() 51 | } 52 | 53 | 54 | public var visibleIndexes:[Int] { 55 | if let viewsCount = viewsCount { 56 | var result = [Int]() 57 | //Add previous page 58 | if pageNumber > 0 && (pageNumber-1) < viewsCount { 59 | result.append(pageNumber-1) 60 | } 61 | //Add curent page 62 | if pageNumber < viewsCount { 63 | result.append(pageNumber) 64 | } 65 | //Add next page 66 | if (pageNumber+1) < viewsCount { 67 | result.append(pageNumber+1) 68 | } 69 | return result 70 | } else { 71 | return [] 72 | } 73 | } 74 | 75 | override public func viewsOnScreen() -> [UIView] { 76 | return visibleIndexes.sort{ $0 > $1 }.map{ self.activeViews[$0]!.view } 77 | } 78 | 79 | 80 | public func dequeueReusableView(tag tag:Int) -> ViewProvider? { 81 | for (index, view) in dirtyViews.enumerate() { 82 | if view.view.tag == tag { 83 | dirtyViews.removeAtIndex(index) 84 | view.prepareForReuse?() 85 | return view 86 | } 87 | } 88 | return nil 89 | } 90 | 91 | public func dequeueReusableView(viewClass viewClass:AnyClass) -> ViewProvider? { 92 | for (index, view) in dirtyViews.enumerate() { 93 | if view.view.isKindOfClass(viewClass) { 94 | dirtyViews.removeAtIndex(index) 95 | view.prepareForReuse?() 96 | return view 97 | } 98 | } 99 | return nil 100 | } 101 | 102 | 103 | override public func didMoveToSuperview() { 104 | super.didMoveToSuperview(); 105 | if superview != nil { 106 | reload() 107 | } 108 | } 109 | 110 | //MARK: private data 111 | private(set) public var activeViews:[Int:ViewProvider] = [:] 112 | private var dirtyViews:[ViewProvider] = [] 113 | private var viewsCount:Int? 114 | private var itemSize:CGSize = CGSizeZero 115 | 116 | private func reloadVisisbleViews() { 117 | let visibleIdx = visibleIndexes.sort{ $0 > $1 } 118 | let activeIdx = activeViews.keys.sort{ $0 > $1 } 119 | if visibleIdx != activeIdx { 120 | //get views to make them dirty 121 | _ = activeIdx.substract(visibleIdx).map { self.makeViewDirty(index:$0) } 122 | // add new views 123 | _ = visibleIdx.substract(activeIdx).map { self.addView(index:$0) } 124 | setNeedsLayout() 125 | } 126 | } 127 | 128 | override public func layoutSubviews() { 129 | if itemSize != UIEdgeInsetsInsetRect(frame, contentInset).size { 130 | reload() 131 | return 132 | } 133 | reloadVisisbleViews() 134 | super.layoutSubviews() 135 | } 136 | 137 | 138 | private func makeViewDirty(index index:Int) { 139 | if let view = activeViews[index] { 140 | dataSource?.scrollView?(scrollView: self, willHideView: view) 141 | view.view.removeFromSuperview() 142 | dataSource?.scrollView?(scrollView: self, didHideView: view) 143 | view.view.layer.transform = CATransform3DIdentity 144 | dirtyViews.append(view) 145 | activeViews.removeValueForKey(index) 146 | } 147 | } 148 | 149 | private func addView(index index:Int) { 150 | 151 | if let view = dataSource?.scrollView(self, viewIndex: index) { 152 | view.view.removeFromSuperview() 153 | let frameI = UIEdgeInsetsInsetRect(frame, contentInset) 154 | let width = CGRectGetWidth(frameI) 155 | let height = CGRectGetHeight(frameI) 156 | let x:CGFloat = CGFloat(index) * width 157 | view.view.frame = CGRectMake(x, 0, width, height) 158 | dataSource?.scrollView?(scrollView: self, willShowView: view) 159 | addSubview(view.view) 160 | dataSource?.scrollView?(scrollView: self, didShowView: view) 161 | view.view.layer.transform = CATransform3DIdentity 162 | activeViews[index] = view 163 | } 164 | } 165 | 166 | private func clearAllViews () { 167 | for (_ , value) in activeViews { 168 | dataSource?.scrollView?(scrollView: self, willHideView: value) 169 | value.view.removeFromSuperview() 170 | dataSource?.scrollView?(scrollView: self, didHideView: value) 171 | } 172 | activeViews = [:] 173 | dirtyViews = [] 174 | viewsCount = nil 175 | itemSize = CGSizeZero 176 | resizeContent() 177 | } 178 | 179 | private func resizeContent() { 180 | if let viewsCount = viewsCount { 181 | let frameI = UIEdgeInsetsInsetRect(frame, contentInset) 182 | let width = CGRectGetWidth(frameI) 183 | let height = CGRectGetHeight(frameI) 184 | let x:CGFloat = CGFloat(viewsCount) * width 185 | contentSize = CGSizeMake(x, height) 186 | itemSize = frameI.size 187 | } else { 188 | contentSize = CGSizeZero 189 | itemSize = CGSizeZero 190 | } 191 | contentOffset = CGPointZero 192 | } 193 | } 194 | 195 | 196 | 197 | extension Array { 198 | 199 | func substract (values: [T]...) -> [T] { 200 | var result = [T]() 201 | elements: for e in self { 202 | if let element = e as? T { 203 | for value in values { 204 | //if our internal element is present in substract array 205 | //exclude it from result 206 | if value.contains(element) { 207 | continue elements 208 | } 209 | } 210 | 211 | // element it's only in self, so return it 212 | result.append(element) 213 | } 214 | } 215 | return result 216 | } 217 | 218 | } 219 | -------------------------------------------------------------------------------- /MAGPagedScrollView/PagedScrollView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PagedScrollView.swift 3 | // MAGPagedScrollViewDemo 4 | // 5 | // Created by Ievgen Rudenko on 21/08/15. 6 | // Copyright (c) 2015 MadAppGang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public enum PagedScrollViewTransitionType { 12 | case None 13 | case Slide 14 | case Dive 15 | case Roll 16 | case Cards 17 | case Custom 18 | } 19 | 20 | @objc public protocol ViewProvider { 21 | 22 | /// View Provider should return the view to display 23 | var view: UIView! { get } 24 | 25 | /** 26 | Send to ViewProver, when reuse, to reset state 27 | */ 28 | optional func prepareForReuse() 29 | 30 | } 31 | 32 | 33 | 34 | public class PagedScrollView: UIScrollView { 35 | 36 | /// Transition type 37 | public var transition: PagedScrollViewTransitionType = .None { 38 | didSet { 39 | setNeedsLayout() 40 | } 41 | } 42 | /// currentPage Number 43 | public var pageNumber:Int { 44 | let pageWidth = CGRectGetWidth(self.frame) 45 | let factionalPage = self.contentOffset.x / pageWidth 46 | return lround(Double(factionalPage)) 47 | } 48 | /// Custom transition 49 | public var customTransition = PagedScrollViewTransitionProperties() 50 | 51 | private var transitionProperties:[PagedScrollViewTransitionType:PagedScrollViewTransitionProperties]! 52 | 53 | override init(frame: CGRect) { 54 | super.init(frame: frame) 55 | commonInit() 56 | } 57 | 58 | required public init?(coder aDecoder: NSCoder) { 59 | super.init(coder: aDecoder) 60 | commonInit() 61 | } 62 | 63 | public func commonInit() { 64 | pagingEnabled = true 65 | clipsToBounds = false 66 | showsHorizontalScrollIndicator = false 67 | showsVerticalScrollIndicator = false 68 | 69 | transitionProperties = [ 70 | .None: PagedScrollViewTransitionProperties(), 71 | .Slide: PagedScrollViewTransitionProperties(angleRatio: 0.0, translation: CGVector(dx:0.25,dy:0.25), rotation: Rotation3D()), 72 | .Dive: PagedScrollViewTransitionProperties(angleRatio: 0.5, translation: CGVector(dx:0.25,dy:0.0), rotation: Rotation3D(x:-1.0,y:0.0,z:0.0)), 73 | .Roll: PagedScrollViewTransitionProperties(angleRatio: 0.5, translation: CGVector(dx:0.25,dy:0.25), rotation: Rotation3D(x:-1.0,y:0.0,z:0.0)), 74 | .Cards: PagedScrollViewTransitionProperties(angleRatio: 0.5, translation: CGVector(dx:0.25,dy:0.25), rotation: Rotation3D(x:-1.0,y:-1.0,z:0.0)), 75 | .Custom:PagedScrollViewTransitionProperties() 76 | ] 77 | } 78 | 79 | 80 | public func addSubviews(aSubviews: [ViewProvider]) { 81 | let frameI = UIEdgeInsetsInsetRect(frame, contentInset) 82 | let width = CGRectGetWidth(frameI) 83 | let height = CGRectGetHeight(frameI) 84 | 85 | var x:CGFloat = 0 86 | 87 | for view in aSubviews { 88 | view.view.frame = CGRectMake(x, 0.0, width, height) 89 | addSubview(view.view) 90 | x += width 91 | } 92 | 93 | contentSize = CGSizeMake(x, height) 94 | } 95 | 96 | public func goNext() { 97 | self.goToPage(self.pageNumber + 1, animated: true) 98 | } 99 | 100 | public func goPrevious() { 101 | self.goToPage(self.pageNumber - 1, animated: true) 102 | } 103 | 104 | public func goToPage(page:Int, animated:Bool) { 105 | var newFrame = frame 106 | let newX = frame.size.width * CGFloat(page) 107 | newFrame.origin = CGPoint(x:newX, y:0.0) 108 | scrollRectToVisible(newFrame, animated: animated) 109 | } 110 | 111 | override public func layoutSubviews() { 112 | super.layoutSubviews() 113 | 114 | let tr = transition == .Custom ? customTransition : transitionProperties[transition]! 115 | 116 | //Get previous view, current view and next view 117 | 118 | 119 | for view in viewsOnScreen() { 120 | //save tramsform state 121 | let oldTransform = view.layer.transform 122 | view.layer.transform = CATransform3DIdentity 123 | 124 | let centerDX = (view.frame.origin.x - contentOffset.x) * 100 / CGRectGetWidth(frame) 125 | view.layer.transform = oldTransform 126 | 127 | let angle = centerDX * tr.angleRatio 128 | let translateX = CGRectGetWidth(frame) * tr.translation.dx * centerDX / 100.0 129 | let translateY = CGRectGetWidth(frame) * tr.translation.dy * abs(centerDX) / 100.0 130 | let transform3D = CATransform3DMakeTranslation(translateX, translateY, 0.0) 131 | 132 | view.layer.transform = CATransform3DRotate(transform3D, angle.degreesToRadians, tr.rotation.x, tr.rotation.y, tr.rotation.z) 133 | } 134 | } 135 | 136 | public func viewsOnScreen() -> [UIView] { 137 | var result = [UIView]() 138 | let page = pageNumber 139 | if page > 0 && (page-1) < subviews.count { 140 | result.append(subviews[page-1] ) 141 | } 142 | if page < subviews.count { 143 | result.append(subviews[page] ) 144 | } 145 | if (page+1) < subviews.count { 146 | result.append(subviews[page+1] ) 147 | } 148 | 149 | 150 | return result 151 | } 152 | 153 | 154 | } 155 | 156 | public struct PagedScrollViewTransitionProperties { 157 | var angleRatio: CGFloat = 0.0 158 | var translation: CGVector = CGVector(dx:0.0, dy:0.0) 159 | var rotation: Rotation3D = Rotation3D() 160 | } 161 | 162 | public struct Rotation3D { 163 | var x:CGFloat = 0.0 164 | var y:CGFloat = 0.0 165 | var z:CGFloat = 0.0 166 | } 167 | 168 | 169 | extension CGFloat { 170 | 171 | var degreesToRadians : CGFloat { 172 | return CGFloat(self) * CGFloat(M_PI) / 180.0 173 | } 174 | 175 | var radiansToDegrees : CGFloat { 176 | return CGFloat(self) / CGFloat(M_PI) * 180.0 177 | } 178 | } 179 | 180 | extension UIView: ViewProvider { 181 | public var view: UIView! { return self } 182 | } 183 | 184 | 185 | // MARK: - UIViewController as View Provider 186 | extension UIViewController: ViewProvider { } 187 | -------------------------------------------------------------------------------- /MAGPagedScrollView/PagedScrollViewContainerViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PagedScrollViewContainerViewController.swift 3 | // MAGPagedScrollViewDemo 4 | // 5 | // Created by Ievgen Rudenko on 28/08/15. 6 | // Copyright (c) 2015 MadAppGang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | 12 | /// Base class for implementing ViewController as container 13 | /// If you want owner (ViewController) of PagedScrollView to be a container 14 | /// just make your view controller subclass of PagedScrollViewContainerViewController 15 | 16 | public class PagedScrollViewContainerViewController: UIViewController, PagedReusableScrollViewDataSource { 17 | 18 | override public func viewDidLoad() { 19 | super.viewDidLoad() 20 | 21 | // Do any additional setup after loading the view. 22 | } 23 | 24 | override public func didReceiveMemoryWarning() { 25 | super.didReceiveMemoryWarning() 26 | // Dispose of any resources that can be recreated. 27 | } 28 | 29 | 30 | // MARK: - PagedReusableScrollViewDataSource 31 | public func scrollView(scrollView: PagedReusableScrollView, viewIndex index: Int) -> ViewProvider { 32 | assertionFailure("have to be implemented in subclass") 33 | //just have to return something 34 | return self 35 | } 36 | 37 | public func numberOfViews(forScrollView scrollView: PagedReusableScrollView) -> Int { 38 | assertionFailure("have to be implemented in subclass") 39 | return 0 40 | } 41 | 42 | public func scrollView(scrollView scrollView: PagedReusableScrollView, willShowView view:ViewProvider) { 43 | if let vc = view as? UIViewController { 44 | self.addChildViewController(vc) 45 | } 46 | } 47 | 48 | public func scrollView(scrollView scrollView: PagedReusableScrollView, willHideView view:ViewProvider) { 49 | if let vc = view as? UIViewController { 50 | vc.willMoveToParentViewController(nil) 51 | } 52 | } 53 | 54 | public func scrollView(scrollView scrollView: PagedReusableScrollView, didShowView view:ViewProvider) { 55 | if let vc = view as? UIViewController { 56 | vc.didMoveToParentViewController(self) 57 | } 58 | } 59 | 60 | public func scrollView(scrollView scrollView: PagedReusableScrollView, didHideView view:ViewProvider) { 61 | if let vc = view as? UIViewController { 62 | vc.removeFromParentViewController() 63 | } 64 | } 65 | 66 | 67 | 68 | } 69 | -------------------------------------------------------------------------------- /MAGPagedScrollView/ParallaxViewProxy.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ParallaxViewProxy.swift 3 | // MAGPagedScrollViewDemo 4 | // 5 | // Created by Ievgen Rudenko on 26/08/15. 6 | // Copyright (c) 2015 MadAppGang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public class ParallaxViewProxy: UIView, PagedScrollViewParallaxDelegate { 12 | 13 | 14 | @IBOutlet public weak var parallaxController:PagedScrollViewParallaxDelegate? = nil 15 | 16 | public func parallaxProgressChanged(progress:Int) { 17 | if let pc = parallaxController { 18 | pc.parallaxProgressChanged(progress) 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /MAGPagedScrollViewDemo/MAGPagedScrollViewDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | BD1C388C1B8D6F20007D9A2F /* ViewController4.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD1C388B1B8D6F20007D9A2F /* ViewController4.swift */; }; 11 | BD1C388E1B8D82F9007D9A2F /* PagedParallaxScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD1C388D1B8D82F9007D9A2F /* PagedParallaxScrollView.swift */; }; 12 | BD1C38911B8D873D007D9A2F /* ParralaxCardViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD1C388F1B8D873D007D9A2F /* ParralaxCardViewController.swift */; }; 13 | BD1C38921B8D873D007D9A2F /* ParralaxCardViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = BD1C38901B8D873D007D9A2F /* ParralaxCardViewController.xib */; }; 14 | BD1C38941B8D959C007D9A2F /* ParallaxViewProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD1C38931B8D959C007D9A2F /* ParallaxViewProxy.swift */; }; 15 | BD1ED9301B870ED70035D46C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD1ED92F1B870ED70035D46C /* AppDelegate.swift */; }; 16 | BD1ED9321B870ED70035D46C /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD1ED9311B870ED70035D46C /* ViewController.swift */; }; 17 | BD1ED9351B870ED70035D46C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BD1ED9331B870ED70035D46C /* Main.storyboard */; }; 18 | BD1ED9371B870ED70035D46C /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = BD1ED9361B870ED70035D46C /* Images.xcassets */; }; 19 | BD1ED93A1B870ED70035D46C /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = BD1ED9381B870ED70035D46C /* LaunchScreen.xib */; }; 20 | BD1ED9461B870ED70035D46C /* MAGPagedScrollViewDemoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD1ED9451B870ED70035D46C /* MAGPagedScrollViewDemoTests.swift */; }; 21 | BD1ED9511B870F9E0035D46C /* PagedScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD1ED9501B870F9E0035D46C /* PagedScrollView.swift */; }; 22 | BD1ED9531B873AAD0035D46C /* PagedReusableScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD1ED9521B873AAD0035D46C /* PagedReusableScrollView.swift */; }; 23 | BD7A9FFE1B88BB7100953466 /* ViewController3.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD7A9FFD1B88BB7100953466 /* ViewController3.swift */; }; 24 | BD7AA0011B88BBDE00953466 /* SimpleCardViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD7A9FFF1B88BBDE00953466 /* SimpleCardViewController.swift */; }; 25 | BD7AA0021B88BBDE00953466 /* SimpleCardViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = BD7AA0001B88BBDE00953466 /* SimpleCardViewController.xib */; }; 26 | BDEEA4651B87771000D50545 /* ViewController2.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDEEA4641B87771000D50545 /* ViewController2.swift */; }; 27 | BDFC7F911B8F572900743C98 /* PagedScrollViewContainerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDFC7F901B8F572900743C98 /* PagedScrollViewContainerViewController.swift */; }; 28 | /* End PBXBuildFile section */ 29 | 30 | /* Begin PBXContainerItemProxy section */ 31 | BD1ED9401B870ED70035D46C /* PBXContainerItemProxy */ = { 32 | isa = PBXContainerItemProxy; 33 | containerPortal = BD1ED9221B870ED70035D46C /* Project object */; 34 | proxyType = 1; 35 | remoteGlobalIDString = BD1ED9291B870ED70035D46C; 36 | remoteInfo = MAGPagedScrollViewDemo; 37 | }; 38 | /* End PBXContainerItemProxy section */ 39 | 40 | /* Begin PBXFileReference section */ 41 | BD1C388B1B8D6F20007D9A2F /* ViewController4.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewController4.swift; sourceTree = ""; }; 42 | BD1C388D1B8D82F9007D9A2F /* PagedParallaxScrollView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PagedParallaxScrollView.swift; sourceTree = ""; }; 43 | BD1C388F1B8D873D007D9A2F /* ParralaxCardViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ParralaxCardViewController.swift; sourceTree = ""; }; 44 | BD1C38901B8D873D007D9A2F /* ParralaxCardViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ParralaxCardViewController.xib; sourceTree = ""; }; 45 | BD1C38931B8D959C007D9A2F /* ParallaxViewProxy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ParallaxViewProxy.swift; sourceTree = ""; }; 46 | BD1ED92A1B870ED70035D46C /* MAGPagedScrollViewDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MAGPagedScrollViewDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 47 | BD1ED92E1B870ED70035D46C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 48 | BD1ED92F1B870ED70035D46C /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 49 | BD1ED9311B870ED70035D46C /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 50 | BD1ED9341B870ED70035D46C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 51 | BD1ED9361B870ED70035D46C /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 52 | BD1ED9391B870ED70035D46C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 53 | BD1ED93F1B870ED70035D46C /* MAGPagedScrollViewDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MAGPagedScrollViewDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 54 | BD1ED9441B870ED70035D46C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 55 | BD1ED9451B870ED70035D46C /* MAGPagedScrollViewDemoTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MAGPagedScrollViewDemoTests.swift; sourceTree = ""; }; 56 | BD1ED9501B870F9E0035D46C /* PagedScrollView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PagedScrollView.swift; sourceTree = ""; }; 57 | BD1ED9521B873AAD0035D46C /* PagedReusableScrollView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PagedReusableScrollView.swift; sourceTree = ""; }; 58 | BD7A9FFD1B88BB7100953466 /* ViewController3.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewController3.swift; sourceTree = ""; }; 59 | BD7A9FFF1B88BBDE00953466 /* SimpleCardViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SimpleCardViewController.swift; sourceTree = ""; }; 60 | BD7AA0001B88BBDE00953466 /* SimpleCardViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SimpleCardViewController.xib; sourceTree = ""; }; 61 | BDEEA4641B87771000D50545 /* ViewController2.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewController2.swift; sourceTree = ""; }; 62 | BDFC7F901B8F572900743C98 /* PagedScrollViewContainerViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PagedScrollViewContainerViewController.swift; sourceTree = ""; }; 63 | /* End PBXFileReference section */ 64 | 65 | /* Begin PBXFrameworksBuildPhase section */ 66 | BD1ED9271B870ED70035D46C /* Frameworks */ = { 67 | isa = PBXFrameworksBuildPhase; 68 | buildActionMask = 2147483647; 69 | files = ( 70 | ); 71 | runOnlyForDeploymentPostprocessing = 0; 72 | }; 73 | BD1ED93C1B870ED70035D46C /* Frameworks */ = { 74 | isa = PBXFrameworksBuildPhase; 75 | buildActionMask = 2147483647; 76 | files = ( 77 | ); 78 | runOnlyForDeploymentPostprocessing = 0; 79 | }; 80 | /* End PBXFrameworksBuildPhase section */ 81 | 82 | /* Begin PBXGroup section */ 83 | BD1ED9211B870ED70035D46C = { 84 | isa = PBXGroup; 85 | children = ( 86 | BD1ED92C1B870ED70035D46C /* MAGPagedScrollViewDemo */, 87 | BD1ED9421B870ED70035D46C /* MAGPagedScrollViewDemoTests */, 88 | BD1ED92B1B870ED70035D46C /* Products */, 89 | ); 90 | sourceTree = ""; 91 | }; 92 | BD1ED92B1B870ED70035D46C /* Products */ = { 93 | isa = PBXGroup; 94 | children = ( 95 | BD1ED92A1B870ED70035D46C /* MAGPagedScrollViewDemo.app */, 96 | BD1ED93F1B870ED70035D46C /* MAGPagedScrollViewDemoTests.xctest */, 97 | ); 98 | name = Products; 99 | sourceTree = ""; 100 | }; 101 | BD1ED92C1B870ED70035D46C /* MAGPagedScrollViewDemo */ = { 102 | isa = PBXGroup; 103 | children = ( 104 | BD1ED94F1B870F530035D46C /* PagedScrollView */, 105 | BD1ED92F1B870ED70035D46C /* AppDelegate.swift */, 106 | BD1ED9311B870ED70035D46C /* ViewController.swift */, 107 | BD1ED9331B870ED70035D46C /* Main.storyboard */, 108 | BD1ED9361B870ED70035D46C /* Images.xcassets */, 109 | BD1ED9381B870ED70035D46C /* LaunchScreen.xib */, 110 | BD1ED92D1B870ED70035D46C /* Supporting Files */, 111 | BDEEA4641B87771000D50545 /* ViewController2.swift */, 112 | BD7A9FFD1B88BB7100953466 /* ViewController3.swift */, 113 | BD7A9FFF1B88BBDE00953466 /* SimpleCardViewController.swift */, 114 | BD7AA0001B88BBDE00953466 /* SimpleCardViewController.xib */, 115 | BD1C388B1B8D6F20007D9A2F /* ViewController4.swift */, 116 | BD1C388F1B8D873D007D9A2F /* ParralaxCardViewController.swift */, 117 | BD1C38901B8D873D007D9A2F /* ParralaxCardViewController.xib */, 118 | ); 119 | path = MAGPagedScrollViewDemo; 120 | sourceTree = ""; 121 | }; 122 | BD1ED92D1B870ED70035D46C /* Supporting Files */ = { 123 | isa = PBXGroup; 124 | children = ( 125 | BD1ED92E1B870ED70035D46C /* Info.plist */, 126 | ); 127 | name = "Supporting Files"; 128 | sourceTree = ""; 129 | }; 130 | BD1ED9421B870ED70035D46C /* MAGPagedScrollViewDemoTests */ = { 131 | isa = PBXGroup; 132 | children = ( 133 | BD1ED9451B870ED70035D46C /* MAGPagedScrollViewDemoTests.swift */, 134 | BD1ED9431B870ED70035D46C /* Supporting Files */, 135 | ); 136 | path = MAGPagedScrollViewDemoTests; 137 | sourceTree = ""; 138 | }; 139 | BD1ED9431B870ED70035D46C /* Supporting Files */ = { 140 | isa = PBXGroup; 141 | children = ( 142 | BD1ED9441B870ED70035D46C /* Info.plist */, 143 | ); 144 | name = "Supporting Files"; 145 | sourceTree = ""; 146 | }; 147 | BD1ED94F1B870F530035D46C /* PagedScrollView */ = { 148 | isa = PBXGroup; 149 | children = ( 150 | BD1ED9501B870F9E0035D46C /* PagedScrollView.swift */, 151 | BD1ED9521B873AAD0035D46C /* PagedReusableScrollView.swift */, 152 | BD1C388D1B8D82F9007D9A2F /* PagedParallaxScrollView.swift */, 153 | BD1C38931B8D959C007D9A2F /* ParallaxViewProxy.swift */, 154 | BDFC7F901B8F572900743C98 /* PagedScrollViewContainerViewController.swift */, 155 | ); 156 | name = PagedScrollView; 157 | path = ../../MAGPagedScrollView; 158 | sourceTree = ""; 159 | }; 160 | /* End PBXGroup section */ 161 | 162 | /* Begin PBXNativeTarget section */ 163 | BD1ED9291B870ED70035D46C /* MAGPagedScrollViewDemo */ = { 164 | isa = PBXNativeTarget; 165 | buildConfigurationList = BD1ED9491B870ED70035D46C /* Build configuration list for PBXNativeTarget "MAGPagedScrollViewDemo" */; 166 | buildPhases = ( 167 | BD1ED9261B870ED70035D46C /* Sources */, 168 | BD1ED9271B870ED70035D46C /* Frameworks */, 169 | BD1ED9281B870ED70035D46C /* Resources */, 170 | ); 171 | buildRules = ( 172 | ); 173 | dependencies = ( 174 | ); 175 | name = MAGPagedScrollViewDemo; 176 | productName = MAGPagedScrollViewDemo; 177 | productReference = BD1ED92A1B870ED70035D46C /* MAGPagedScrollViewDemo.app */; 178 | productType = "com.apple.product-type.application"; 179 | }; 180 | BD1ED93E1B870ED70035D46C /* MAGPagedScrollViewDemoTests */ = { 181 | isa = PBXNativeTarget; 182 | buildConfigurationList = BD1ED94C1B870ED70035D46C /* Build configuration list for PBXNativeTarget "MAGPagedScrollViewDemoTests" */; 183 | buildPhases = ( 184 | BD1ED93B1B870ED70035D46C /* Sources */, 185 | BD1ED93C1B870ED70035D46C /* Frameworks */, 186 | BD1ED93D1B870ED70035D46C /* Resources */, 187 | ); 188 | buildRules = ( 189 | ); 190 | dependencies = ( 191 | BD1ED9411B870ED70035D46C /* PBXTargetDependency */, 192 | ); 193 | name = MAGPagedScrollViewDemoTests; 194 | productName = MAGPagedScrollViewDemoTests; 195 | productReference = BD1ED93F1B870ED70035D46C /* MAGPagedScrollViewDemoTests.xctest */; 196 | productType = "com.apple.product-type.bundle.unit-test"; 197 | }; 198 | /* End PBXNativeTarget section */ 199 | 200 | /* Begin PBXProject section */ 201 | BD1ED9221B870ED70035D46C /* Project object */ = { 202 | isa = PBXProject; 203 | attributes = { 204 | LastSwiftMigration = 0700; 205 | LastSwiftUpdateCheck = 0700; 206 | LastUpgradeCheck = 0700; 207 | ORGANIZATIONNAME = MadAppGang; 208 | TargetAttributes = { 209 | BD1ED9291B870ED70035D46C = { 210 | CreatedOnToolsVersion = 6.4; 211 | }; 212 | BD1ED93E1B870ED70035D46C = { 213 | CreatedOnToolsVersion = 6.4; 214 | TestTargetID = BD1ED9291B870ED70035D46C; 215 | }; 216 | }; 217 | }; 218 | buildConfigurationList = BD1ED9251B870ED70035D46C /* Build configuration list for PBXProject "MAGPagedScrollViewDemo" */; 219 | compatibilityVersion = "Xcode 3.2"; 220 | developmentRegion = English; 221 | hasScannedForEncodings = 0; 222 | knownRegions = ( 223 | en, 224 | Base, 225 | ); 226 | mainGroup = BD1ED9211B870ED70035D46C; 227 | productRefGroup = BD1ED92B1B870ED70035D46C /* Products */; 228 | projectDirPath = ""; 229 | projectRoot = ""; 230 | targets = ( 231 | BD1ED9291B870ED70035D46C /* MAGPagedScrollViewDemo */, 232 | BD1ED93E1B870ED70035D46C /* MAGPagedScrollViewDemoTests */, 233 | ); 234 | }; 235 | /* End PBXProject section */ 236 | 237 | /* Begin PBXResourcesBuildPhase section */ 238 | BD1ED9281B870ED70035D46C /* Resources */ = { 239 | isa = PBXResourcesBuildPhase; 240 | buildActionMask = 2147483647; 241 | files = ( 242 | BD7AA0021B88BBDE00953466 /* SimpleCardViewController.xib in Resources */, 243 | BD1ED9351B870ED70035D46C /* Main.storyboard in Resources */, 244 | BD1C38921B8D873D007D9A2F /* ParralaxCardViewController.xib in Resources */, 245 | BD1ED93A1B870ED70035D46C /* LaunchScreen.xib in Resources */, 246 | BD1ED9371B870ED70035D46C /* Images.xcassets in Resources */, 247 | ); 248 | runOnlyForDeploymentPostprocessing = 0; 249 | }; 250 | BD1ED93D1B870ED70035D46C /* Resources */ = { 251 | isa = PBXResourcesBuildPhase; 252 | buildActionMask = 2147483647; 253 | files = ( 254 | ); 255 | runOnlyForDeploymentPostprocessing = 0; 256 | }; 257 | /* End PBXResourcesBuildPhase section */ 258 | 259 | /* Begin PBXSourcesBuildPhase section */ 260 | BD1ED9261B870ED70035D46C /* Sources */ = { 261 | isa = PBXSourcesBuildPhase; 262 | buildActionMask = 2147483647; 263 | files = ( 264 | BD1C38911B8D873D007D9A2F /* ParralaxCardViewController.swift in Sources */, 265 | BDEEA4651B87771000D50545 /* ViewController2.swift in Sources */, 266 | BD7AA0011B88BBDE00953466 /* SimpleCardViewController.swift in Sources */, 267 | BD1ED9531B873AAD0035D46C /* PagedReusableScrollView.swift in Sources */, 268 | BD1C388C1B8D6F20007D9A2F /* ViewController4.swift in Sources */, 269 | BD7A9FFE1B88BB7100953466 /* ViewController3.swift in Sources */, 270 | BD1ED9321B870ED70035D46C /* ViewController.swift in Sources */, 271 | BD1C38941B8D959C007D9A2F /* ParallaxViewProxy.swift in Sources */, 272 | BDFC7F911B8F572900743C98 /* PagedScrollViewContainerViewController.swift in Sources */, 273 | BD1ED9511B870F9E0035D46C /* PagedScrollView.swift in Sources */, 274 | BD1ED9301B870ED70035D46C /* AppDelegate.swift in Sources */, 275 | BD1C388E1B8D82F9007D9A2F /* PagedParallaxScrollView.swift in Sources */, 276 | ); 277 | runOnlyForDeploymentPostprocessing = 0; 278 | }; 279 | BD1ED93B1B870ED70035D46C /* Sources */ = { 280 | isa = PBXSourcesBuildPhase; 281 | buildActionMask = 2147483647; 282 | files = ( 283 | BD1ED9461B870ED70035D46C /* MAGPagedScrollViewDemoTests.swift in Sources */, 284 | ); 285 | runOnlyForDeploymentPostprocessing = 0; 286 | }; 287 | /* End PBXSourcesBuildPhase section */ 288 | 289 | /* Begin PBXTargetDependency section */ 290 | BD1ED9411B870ED70035D46C /* PBXTargetDependency */ = { 291 | isa = PBXTargetDependency; 292 | target = BD1ED9291B870ED70035D46C /* MAGPagedScrollViewDemo */; 293 | targetProxy = BD1ED9401B870ED70035D46C /* PBXContainerItemProxy */; 294 | }; 295 | /* End PBXTargetDependency section */ 296 | 297 | /* Begin PBXVariantGroup section */ 298 | BD1ED9331B870ED70035D46C /* Main.storyboard */ = { 299 | isa = PBXVariantGroup; 300 | children = ( 301 | BD1ED9341B870ED70035D46C /* Base */, 302 | ); 303 | name = Main.storyboard; 304 | sourceTree = ""; 305 | }; 306 | BD1ED9381B870ED70035D46C /* LaunchScreen.xib */ = { 307 | isa = PBXVariantGroup; 308 | children = ( 309 | BD1ED9391B870ED70035D46C /* Base */, 310 | ); 311 | name = LaunchScreen.xib; 312 | sourceTree = ""; 313 | }; 314 | /* End PBXVariantGroup section */ 315 | 316 | /* Begin XCBuildConfiguration section */ 317 | BD1ED9471B870ED70035D46C /* Debug */ = { 318 | isa = XCBuildConfiguration; 319 | buildSettings = { 320 | ALWAYS_SEARCH_USER_PATHS = NO; 321 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 322 | CLANG_CXX_LIBRARY = "libc++"; 323 | CLANG_ENABLE_MODULES = YES; 324 | CLANG_ENABLE_OBJC_ARC = YES; 325 | CLANG_WARN_BOOL_CONVERSION = YES; 326 | CLANG_WARN_CONSTANT_CONVERSION = YES; 327 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 328 | CLANG_WARN_EMPTY_BODY = YES; 329 | CLANG_WARN_ENUM_CONVERSION = YES; 330 | CLANG_WARN_INT_CONVERSION = YES; 331 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 332 | CLANG_WARN_UNREACHABLE_CODE = YES; 333 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 334 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 335 | COPY_PHASE_STRIP = NO; 336 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 337 | ENABLE_STRICT_OBJC_MSGSEND = YES; 338 | ENABLE_TESTABILITY = YES; 339 | GCC_C_LANGUAGE_STANDARD = gnu99; 340 | GCC_DYNAMIC_NO_PIC = NO; 341 | GCC_NO_COMMON_BLOCKS = YES; 342 | GCC_OPTIMIZATION_LEVEL = 0; 343 | GCC_PREPROCESSOR_DEFINITIONS = ( 344 | "DEBUG=1", 345 | "$(inherited)", 346 | ); 347 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 348 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 349 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 350 | GCC_WARN_UNDECLARED_SELECTOR = YES; 351 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 352 | GCC_WARN_UNUSED_FUNCTION = YES; 353 | GCC_WARN_UNUSED_VARIABLE = YES; 354 | IPHONEOS_DEPLOYMENT_TARGET = 8.4; 355 | MTL_ENABLE_DEBUG_INFO = YES; 356 | ONLY_ACTIVE_ARCH = YES; 357 | SDKROOT = iphoneos; 358 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 359 | TARGETED_DEVICE_FAMILY = "1,2"; 360 | }; 361 | name = Debug; 362 | }; 363 | BD1ED9481B870ED70035D46C /* Release */ = { 364 | isa = XCBuildConfiguration; 365 | buildSettings = { 366 | ALWAYS_SEARCH_USER_PATHS = NO; 367 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 368 | CLANG_CXX_LIBRARY = "libc++"; 369 | CLANG_ENABLE_MODULES = YES; 370 | CLANG_ENABLE_OBJC_ARC = YES; 371 | CLANG_WARN_BOOL_CONVERSION = YES; 372 | CLANG_WARN_CONSTANT_CONVERSION = YES; 373 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 374 | CLANG_WARN_EMPTY_BODY = YES; 375 | CLANG_WARN_ENUM_CONVERSION = YES; 376 | CLANG_WARN_INT_CONVERSION = YES; 377 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 378 | CLANG_WARN_UNREACHABLE_CODE = YES; 379 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 380 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 381 | COPY_PHASE_STRIP = NO; 382 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 383 | ENABLE_NS_ASSERTIONS = NO; 384 | ENABLE_STRICT_OBJC_MSGSEND = YES; 385 | GCC_C_LANGUAGE_STANDARD = gnu99; 386 | GCC_NO_COMMON_BLOCKS = YES; 387 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 388 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 389 | GCC_WARN_UNDECLARED_SELECTOR = YES; 390 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 391 | GCC_WARN_UNUSED_FUNCTION = YES; 392 | GCC_WARN_UNUSED_VARIABLE = YES; 393 | IPHONEOS_DEPLOYMENT_TARGET = 8.4; 394 | MTL_ENABLE_DEBUG_INFO = NO; 395 | SDKROOT = iphoneos; 396 | TARGETED_DEVICE_FAMILY = "1,2"; 397 | VALIDATE_PRODUCT = YES; 398 | }; 399 | name = Release; 400 | }; 401 | BD1ED94A1B870ED70035D46C /* Debug */ = { 402 | isa = XCBuildConfiguration; 403 | buildSettings = { 404 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 405 | INFOPLIST_FILE = MAGPagedScrollViewDemo/Info.plist; 406 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 407 | PRODUCT_BUNDLE_IDENTIFIER = "com.madappgang.$(PRODUCT_NAME:rfc1034identifier)"; 408 | PRODUCT_NAME = "$(TARGET_NAME)"; 409 | }; 410 | name = Debug; 411 | }; 412 | BD1ED94B1B870ED70035D46C /* Release */ = { 413 | isa = XCBuildConfiguration; 414 | buildSettings = { 415 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 416 | INFOPLIST_FILE = MAGPagedScrollViewDemo/Info.plist; 417 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 418 | PRODUCT_BUNDLE_IDENTIFIER = "com.madappgang.$(PRODUCT_NAME:rfc1034identifier)"; 419 | PRODUCT_NAME = "$(TARGET_NAME)"; 420 | }; 421 | name = Release; 422 | }; 423 | BD1ED94D1B870ED70035D46C /* Debug */ = { 424 | isa = XCBuildConfiguration; 425 | buildSettings = { 426 | BUNDLE_LOADER = "$(TEST_HOST)"; 427 | FRAMEWORK_SEARCH_PATHS = ( 428 | "$(SDKROOT)/Developer/Library/Frameworks", 429 | "$(inherited)", 430 | ); 431 | GCC_PREPROCESSOR_DEFINITIONS = ( 432 | "DEBUG=1", 433 | "$(inherited)", 434 | ); 435 | INFOPLIST_FILE = MAGPagedScrollViewDemoTests/Info.plist; 436 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 437 | PRODUCT_BUNDLE_IDENTIFIER = "com.madappgang.$(PRODUCT_NAME:rfc1034identifier)"; 438 | PRODUCT_NAME = "$(TARGET_NAME)"; 439 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MAGPagedScrollViewDemo.app/MAGPagedScrollViewDemo"; 440 | }; 441 | name = Debug; 442 | }; 443 | BD1ED94E1B870ED70035D46C /* Release */ = { 444 | isa = XCBuildConfiguration; 445 | buildSettings = { 446 | BUNDLE_LOADER = "$(TEST_HOST)"; 447 | FRAMEWORK_SEARCH_PATHS = ( 448 | "$(SDKROOT)/Developer/Library/Frameworks", 449 | "$(inherited)", 450 | ); 451 | INFOPLIST_FILE = MAGPagedScrollViewDemoTests/Info.plist; 452 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 453 | PRODUCT_BUNDLE_IDENTIFIER = "com.madappgang.$(PRODUCT_NAME:rfc1034identifier)"; 454 | PRODUCT_NAME = "$(TARGET_NAME)"; 455 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MAGPagedScrollViewDemo.app/MAGPagedScrollViewDemo"; 456 | }; 457 | name = Release; 458 | }; 459 | /* End XCBuildConfiguration section */ 460 | 461 | /* Begin XCConfigurationList section */ 462 | BD1ED9251B870ED70035D46C /* Build configuration list for PBXProject "MAGPagedScrollViewDemo" */ = { 463 | isa = XCConfigurationList; 464 | buildConfigurations = ( 465 | BD1ED9471B870ED70035D46C /* Debug */, 466 | BD1ED9481B870ED70035D46C /* Release */, 467 | ); 468 | defaultConfigurationIsVisible = 0; 469 | defaultConfigurationName = Release; 470 | }; 471 | BD1ED9491B870ED70035D46C /* Build configuration list for PBXNativeTarget "MAGPagedScrollViewDemo" */ = { 472 | isa = XCConfigurationList; 473 | buildConfigurations = ( 474 | BD1ED94A1B870ED70035D46C /* Debug */, 475 | BD1ED94B1B870ED70035D46C /* Release */, 476 | ); 477 | defaultConfigurationIsVisible = 0; 478 | defaultConfigurationName = Release; 479 | }; 480 | BD1ED94C1B870ED70035D46C /* Build configuration list for PBXNativeTarget "MAGPagedScrollViewDemoTests" */ = { 481 | isa = XCConfigurationList; 482 | buildConfigurations = ( 483 | BD1ED94D1B870ED70035D46C /* Debug */, 484 | BD1ED94E1B870ED70035D46C /* Release */, 485 | ); 486 | defaultConfigurationIsVisible = 0; 487 | defaultConfigurationName = Release; 488 | }; 489 | /* End XCConfigurationList section */ 490 | }; 491 | rootObject = BD1ED9221B870ED70035D46C /* Project object */; 492 | } 493 | -------------------------------------------------------------------------------- /MAGPagedScrollViewDemo/MAGPagedScrollViewDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /MAGPagedScrollViewDemo/MAGPagedScrollViewDemo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // MAGPagedScrollViewDemo 4 | // 5 | // Created by Ievgen Rudenko on 21/08/15. 6 | // Copyright (c) 2015 MadAppGang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(application: UIApplication) { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(application: UIApplication) { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(application: UIApplication) { 33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(application: UIApplication) { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | func applicationWillTerminate(application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /MAGPagedScrollViewDemo/MAGPagedScrollViewDemo/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 | -------------------------------------------------------------------------------- /MAGPagedScrollViewDemo/MAGPagedScrollViewDemo/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 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 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 | 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 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | -------------------------------------------------------------------------------- /MAGPagedScrollViewDemo/MAGPagedScrollViewDemo/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 | } -------------------------------------------------------------------------------- /MAGPagedScrollViewDemo/MAGPagedScrollViewDemo/Images.xcassets/photo0.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "photo0.jpg" 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 | } -------------------------------------------------------------------------------- /MAGPagedScrollViewDemo/MAGPagedScrollViewDemo/Images.xcassets/photo0.imageset/photo0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MadAppGang/MAGPagedScrollView/df0f51a21c3ce8ae48bf8865b29c0010859988f8/MAGPagedScrollViewDemo/MAGPagedScrollViewDemo/Images.xcassets/photo0.imageset/photo0.jpg -------------------------------------------------------------------------------- /MAGPagedScrollViewDemo/MAGPagedScrollViewDemo/Images.xcassets/photo1.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "photo1.jpg" 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 | } -------------------------------------------------------------------------------- /MAGPagedScrollViewDemo/MAGPagedScrollViewDemo/Images.xcassets/photo1.imageset/photo1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MadAppGang/MAGPagedScrollView/df0f51a21c3ce8ae48bf8865b29c0010859988f8/MAGPagedScrollViewDemo/MAGPagedScrollViewDemo/Images.xcassets/photo1.imageset/photo1.jpg -------------------------------------------------------------------------------- /MAGPagedScrollViewDemo/MAGPagedScrollViewDemo/Images.xcassets/photo2.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "photo2.jpg" 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 | } -------------------------------------------------------------------------------- /MAGPagedScrollViewDemo/MAGPagedScrollViewDemo/Images.xcassets/photo2.imageset/photo2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MadAppGang/MAGPagedScrollView/df0f51a21c3ce8ae48bf8865b29c0010859988f8/MAGPagedScrollViewDemo/MAGPagedScrollViewDemo/Images.xcassets/photo2.imageset/photo2.jpg -------------------------------------------------------------------------------- /MAGPagedScrollViewDemo/MAGPagedScrollViewDemo/Images.xcassets/photo3.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "photo3.jpg" 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 | } -------------------------------------------------------------------------------- /MAGPagedScrollViewDemo/MAGPagedScrollViewDemo/Images.xcassets/photo3.imageset/photo3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MadAppGang/MAGPagedScrollView/df0f51a21c3ce8ae48bf8865b29c0010859988f8/MAGPagedScrollViewDemo/MAGPagedScrollViewDemo/Images.xcassets/photo3.imageset/photo3.jpg -------------------------------------------------------------------------------- /MAGPagedScrollViewDemo/MAGPagedScrollViewDemo/Images.xcassets/photo4.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "photo4.jpg" 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 | } -------------------------------------------------------------------------------- /MAGPagedScrollViewDemo/MAGPagedScrollViewDemo/Images.xcassets/photo4.imageset/photo4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MadAppGang/MAGPagedScrollView/df0f51a21c3ce8ae48bf8865b29c0010859988f8/MAGPagedScrollViewDemo/MAGPagedScrollViewDemo/Images.xcassets/photo4.imageset/photo4.jpg -------------------------------------------------------------------------------- /MAGPagedScrollViewDemo/MAGPagedScrollViewDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | 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 | -------------------------------------------------------------------------------- /MAGPagedScrollViewDemo/MAGPagedScrollViewDemo/ParralaxCardViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ParralaxCardViewController.swift 3 | // MAGPagedScrollViewDemo 4 | // 5 | // Created by Ievgen Rudenko on 26/08/15. 6 | // Copyright (c) 2015 MadAppGang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ParralaxCardViewController: UIViewController { 12 | 13 | 14 | @IBOutlet weak var imageView: UIImageView! 15 | 16 | @IBOutlet weak var detailsCentralConstraint: NSLayoutConstraint! 17 | 18 | @IBOutlet weak var titleTopConstraint: NSLayoutConstraint! 19 | @IBOutlet weak var imageCentralConstraint: NSLayoutConstraint! 20 | 21 | var imageName: String? = nil { 22 | didSet { 23 | if let imageName = imageName { 24 | self.imageView?.image = UIImage(named: imageName) 25 | } else { 26 | self.imageView?.image = nil 27 | } 28 | } 29 | } 30 | 31 | 32 | override func viewDidLoad() { 33 | super.viewDidLoad() 34 | if let imageName = imageName { 35 | self.imageView?.image = UIImage(named: imageName) 36 | } else { 37 | self.imageView?.image = nil 38 | } 39 | // Do any additional setup after loading the view. 40 | } 41 | 42 | override func didReceiveMemoryWarning() { 43 | super.didReceiveMemoryWarning() 44 | 45 | } 46 | 47 | override func loadView() { 48 | NSBundle.mainBundle().loadNibNamed("ParralaxCardViewController", owner: self, options: nil) 49 | if let view = view as? ParallaxViewProxy { 50 | view.parallaxController = self 51 | } 52 | } 53 | 54 | override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) { 55 | print("\(self) viewWillTransitionToSize: \(size) with coordinator: \(coordinator)") 56 | } 57 | 58 | } 59 | 60 | 61 | extension ParralaxCardViewController: PagedScrollViewParallaxDelegate { 62 | 63 | func parallaxProgressChanged(progress:Int) { 64 | self.imageView.bounds = CGRectMake(CGFloat(progress), 0, imageView.bounds.size.width, imageView.bounds.size.height) 65 | detailsCentralConstraint.constant = CGFloat(-progress*4) 66 | imageCentralConstraint.constant = CGFloat(-progress) 67 | titleTopConstraint.constant = CGFloat(abs(progress)) 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /MAGPagedScrollViewDemo/MAGPagedScrollViewDemo/ParralaxCardViewController.xib: -------------------------------------------------------------------------------- 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 | 34 | 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 | -------------------------------------------------------------------------------- /MAGPagedScrollViewDemo/MAGPagedScrollViewDemo/SimpleCardViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SimpleCardViewController.swift 3 | // MAGPagedScrollViewDemo 4 | // 5 | // Created by Ievgen Rudenko on 23/08/15. 6 | // Copyright (c) 2015 MadAppGang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class SimpleCardViewController: UIViewController { 12 | 13 | @IBOutlet weak var imageView: UIImageView! 14 | @IBOutlet weak var label: UILabel! 15 | 16 | var imageName: String? = nil { 17 | didSet { 18 | if let imageName = imageName { 19 | self.imageView?.image = UIImage(named: imageName) 20 | } else { 21 | self.imageView?.image = nil 22 | } 23 | } 24 | } 25 | 26 | 27 | override func viewDidLoad() { 28 | super.viewDidLoad() 29 | if let imageName = imageName { 30 | self.imageView?.image = UIImage(named: imageName) 31 | } else { 32 | self.imageView?.image = nil 33 | } 34 | // Do any additional setup after loading the view. 35 | } 36 | 37 | override func didReceiveMemoryWarning() { 38 | super.didReceiveMemoryWarning() 39 | // Dispose of any resources that can be recreated. 40 | } 41 | 42 | override func loadView() { 43 | NSBundle.mainBundle().loadNibNamed("SimpleCardViewController", owner: self, options: nil) 44 | } 45 | 46 | /* 47 | // MARK: - Navigation 48 | 49 | // In a storyboard-based application, you will often want to do a little preparation before navigation 50 | override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { 51 | // Get the new view controller using segue.destinationViewController. 52 | // Pass the selected object to the new view controller. 53 | } 54 | */ 55 | 56 | } 57 | -------------------------------------------------------------------------------- /MAGPagedScrollViewDemo/MAGPagedScrollViewDemo/SimpleCardViewController.xib: -------------------------------------------------------------------------------- 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 | 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 | -------------------------------------------------------------------------------- /MAGPagedScrollViewDemo/MAGPagedScrollViewDemo/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // MAGPagedScrollViewDemo 4 | // 5 | // Created by Ievgen Rudenko on 21/08/15. 6 | // Copyright (c) 2015 MadAppGang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | @IBOutlet weak var scrollView: PagedScrollView! 14 | 15 | var colors = [ 16 | UIColor.redColor(), 17 | UIColor.blueColor(), 18 | UIColor.greenColor(), 19 | UIColor.magentaColor() 20 | ] 21 | override func viewDidLoad() { 22 | super.viewDidLoad() 23 | // Do any additional setup after loading the view, typically from a nib. 24 | } 25 | 26 | override func viewDidAppear(animated: Bool) { 27 | super.viewDidAppear(animated) 28 | //alternate way to add subviews 29 | // createView(0) 30 | // createView(1) 31 | // createView(2) 32 | // createView(3) 33 | 34 | scrollView.addSubviews([ 35 | createView(0), 36 | createView(1), 37 | createView(2), 38 | createView(3) 39 | ]) 40 | } 41 | 42 | @IBAction func goToLast(sender: AnyObject) { 43 | self.scrollView.goToPage(3, animated: true) 44 | } 45 | 46 | func createView(color: Int) -> UIView { 47 | let view = UIView(frame: CGRectMake(0, 0, 100, 100)) 48 | view.backgroundColor = colors[color] 49 | view.layer.cornerRadius = 10.0 50 | return view 51 | } 52 | 53 | func createAndAddView(color: Int) { 54 | let width = CGRectGetWidth(scrollView.frame) 55 | let height = CGRectGetHeight(scrollView.frame) 56 | 57 | let x = CGFloat(scrollView.subviews.count) * width 58 | 59 | let view = UIView(frame: CGRectMake(x, 0, width, height)) 60 | view.backgroundColor = colors[color] 61 | 62 | view.layer.cornerRadius = 10.0 63 | scrollView.addSubview(view) 64 | scrollView.contentSize = CGSizeMake(x+width, height) 65 | } 66 | 67 | override func didReceiveMemoryWarning() { 68 | super.didReceiveMemoryWarning() 69 | // Dispose of any resources that can be recreated. 70 | } 71 | 72 | 73 | @IBAction func segmentedViewChanged(sender: UISegmentedControl) { 74 | switch sender.selectedSegmentIndex { 75 | case 1: scrollView.transition = .Slide 76 | case 2: scrollView.transition = .Dive 77 | case 3: scrollView.transition = .Roll 78 | case 4: scrollView.transition = .Cards 79 | default: scrollView.transition = .None 80 | } 81 | } 82 | } 83 | 84 | -------------------------------------------------------------------------------- /MAGPagedScrollViewDemo/MAGPagedScrollViewDemo/ViewController2.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController2.swift 3 | // MAGPagedScrollViewDemo 4 | // 5 | // Created by Ievgen Rudenko on 22/08/15. 6 | // Copyright (c) 2015 MadAppGang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController2: UIViewController { 12 | 13 | @IBOutlet weak var scrollView: PagedReusableScrollView! 14 | 15 | var colors = [ 16 | UIColor.redColor(), 17 | UIColor.blueColor(), 18 | UIColor.greenColor(), 19 | UIColor.magentaColor(), 20 | UIColor.lightGrayColor() 21 | ] 22 | 23 | override func viewDidLoad() { 24 | super.viewDidLoad() 25 | scrollView.dataSource = self 26 | // Do any additional setup after loading the view. 27 | } 28 | 29 | 30 | override func didReceiveMemoryWarning() { 31 | super.didReceiveMemoryWarning() 32 | // Dispose of any resources that can be recreated. 33 | } 34 | 35 | @IBAction func styleChanged(sender: UISegmentedControl) { 36 | switch sender.selectedSegmentIndex { 37 | case 1: scrollView.transition = .Slide 38 | case 2: scrollView.transition = .Dive 39 | case 3: scrollView.transition = .Roll 40 | case 4: scrollView.transition = .Cards 41 | default: scrollView.transition = .None 42 | } 43 | } 44 | 45 | @IBAction func goToEnd(sender: AnyObject) { 46 | self.scrollView.goToPage(9, animated: true) 47 | } 48 | } 49 | 50 | 51 | extension ViewController2: PagedReusableScrollViewDataSource { 52 | 53 | func scrollView(scrollView: PagedReusableScrollView, viewIndex index: Int) -> ViewProvider { 54 | var newView = scrollView.dequeueReusableView(tag: index > 4 ? 1 : 2 ) 55 | if newView == nil { 56 | if index > 4 { 57 | newView = UIView(frame: CGRectMake(0, 0, 100, 100)) 58 | } else { 59 | let imageView = UIImageView(frame: CGRectMake(0, 0, 100, 100)) 60 | imageView.contentMode = .ScaleAspectFill 61 | newView = imageView 62 | } 63 | newView?.view.tag = index > 4 ? 1 : 2 64 | } 65 | 66 | if index > 4 { 67 | newView?.view.backgroundColor = colors[ index-5 ] 68 | } else { 69 | let imageView = newView as! UIImageView 70 | imageView.image = UIImage(named:"photo\(index).jpg") 71 | } 72 | newView?.view.clipsToBounds = true 73 | return newView! 74 | } 75 | 76 | func numberOfViews(forScrollView scrollView: PagedReusableScrollView) -> Int { 77 | return 10 78 | } 79 | 80 | } -------------------------------------------------------------------------------- /MAGPagedScrollViewDemo/MAGPagedScrollViewDemo/ViewController3.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController3.swift 3 | // MAGPagedScrollViewDemo 4 | // 5 | // Created by Ievgen Rudenko on 23/08/15. 6 | // Copyright (c) 2015 MadAppGang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController3: UIViewController { 12 | 13 | @IBOutlet weak var scrollView: PagedReusableScrollView! 14 | 15 | var colors = [ 16 | UIColor.redColor(), 17 | UIColor.blueColor(), 18 | UIColor.greenColor(), 19 | UIColor.magentaColor(), 20 | UIColor.lightGrayColor() 21 | ] 22 | 23 | override func viewDidLoad() { 24 | super.viewDidLoad() 25 | scrollView.dataSource = self 26 | // Do any additional setup after loading the view. 27 | } 28 | 29 | 30 | override func didReceiveMemoryWarning() { 31 | super.didReceiveMemoryWarning() 32 | // Dispose of any resources that can be recreated. 33 | } 34 | 35 | @IBAction func styleChanged(sender: UISegmentedControl) { 36 | switch sender.selectedSegmentIndex { 37 | case 1: scrollView.transition = .Slide 38 | case 2: scrollView.transition = .Dive 39 | case 3: scrollView.transition = .Roll 40 | case 4: scrollView.transition = .Cards 41 | default: scrollView.transition = .None 42 | } 43 | } 44 | 45 | 46 | } 47 | 48 | 49 | extension ViewController3: PagedReusableScrollViewDataSource { 50 | 51 | func scrollView(scrollView: PagedReusableScrollView, viewIndex index: Int) -> ViewProvider { 52 | var newView:SimpleCardViewController? = scrollView.dequeueReusableView(tag: 1 ) as? SimpleCardViewController 53 | if newView == nil { 54 | newView = SimpleCardViewController() 55 | } 56 | newView?.imageName = "photo\(index%5).jpg" 57 | return newView! 58 | } 59 | 60 | func numberOfViews(forScrollView scrollView: PagedReusableScrollView) -> Int { 61 | return 10 62 | } 63 | 64 | } -------------------------------------------------------------------------------- /MAGPagedScrollViewDemo/MAGPagedScrollViewDemo/ViewController4.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController4.swift 3 | // MAGPagedScrollViewDemo 4 | // 5 | // Created by Ievgen Rudenko on 26/08/15. 6 | // Copyright (c) 2015 MadAppGang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController4: PagedScrollViewContainerViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | scrollView.dataSource = self 16 | 17 | // Do any additional setup after loading the view. 18 | } 19 | 20 | override func didReceiveMemoryWarning() { 21 | super.didReceiveMemoryWarning() 22 | // Dispose of any resources that can be recreated. 23 | } 24 | 25 | 26 | @IBOutlet weak var scrollView: PagedReusableScrollView! 27 | 28 | 29 | @IBAction func transformChanged(sender: UISegmentedControl) { 30 | 31 | } 32 | 33 | @IBAction func styleChanged(sender: UISegmentedControl) { 34 | switch sender.selectedSegmentIndex { 35 | case 1: scrollView.transition = .Slide 36 | case 2: scrollView.transition = .Dive 37 | case 3: scrollView.transition = .Roll 38 | case 4: scrollView.transition = .Cards 39 | default: scrollView.transition = .None 40 | } 41 | } 42 | 43 | 44 | } 45 | 46 | 47 | extension ViewController4 { 48 | 49 | override func scrollView(scrollView: PagedReusableScrollView, viewIndex index: Int) -> ViewProvider { 50 | var newView:ParralaxCardViewController? = scrollView.dequeueReusableView(tag: 1 ) as? ParralaxCardViewController 51 | if newView == nil { 52 | newView = ParralaxCardViewController() 53 | } 54 | newView?.imageName = "photo\(index%5).jpg" 55 | return newView! 56 | } 57 | 58 | override func numberOfViews(forScrollView scrollView: PagedReusableScrollView) -> Int { 59 | return 15 60 | } 61 | 62 | } -------------------------------------------------------------------------------- /MAGPagedScrollViewDemo/MAGPagedScrollViewDemoTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /MAGPagedScrollViewDemo/MAGPagedScrollViewDemoTests/MAGPagedScrollViewDemoTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MAGPagedScrollViewDemoTests.swift 3 | // MAGPagedScrollViewDemoTests 4 | // 5 | // Created by Ievgen Rudenko on 21/08/15. 6 | // Copyright (c) 2015 MadAppGang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import XCTest 11 | 12 | class MAGPagedScrollViewDemoTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | XCTAssert(true, "Pass") 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measureBlock() { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MAGPagedScrollView 2 | 3 | Now MAGPagedScrollView supports Swift2. If you want to use Swift 1.2, use tag 0.0.6. 4 | MAGPagedScrollView is collection of some scroll classes that orginise views and view controllers as horizontall scroll flow 5 | 6 | - 100% Swift (are you still developing with Objective-C ?) 7 | - reuse behavior as UITabelView (memory efficient) 8 | - easy to use (2 minutes to implement basic app) 9 | - support and bug fixing (we are using this component in our products) 10 | 11 | Please send us link to your apps, and w ewill create app gallery. 12 | 13 | Here is video demo: 14 | 15 | [![youtube](http://img.youtube.com/vi/HgSKxQVIOq0/0.jpg)](http://www.youtube.com/watch?v=HgSKxQVIOq0) 16 | 17 | and real life example of onboarding screens: 18 | 19 | [![youtube](http://img.youtube.com/vi/q18RqlyTpak/0.jpg)](http://www.youtube.com/watch?v=q18RqlyTpak) 20 | 21 | [![youtube](http://img.youtube.com/vi/GzpCboLTPqc/0.jpg)](http://www.youtube.com/watch?v=GzpCboLTPqc) 22 | 23 | ### Installation 24 | 25 | add this line to Podfile: 26 | ``` 27 | pod 'MAGPagedScrollView' 28 | ``` 29 | 30 | ## PagedScrollView 31 | Subclass of UIScrollVeiw, that will orginise it's subviews as scrolled cards. 32 | And it's base class for other guys as well: **PagedReusableScrollView** and **PagedParallaxScrollView**. 33 | 34 | the result looks like that: 35 | 36 | ![ScreenShot](resources/Basic\ Cards.gif) 37 | 38 | to do it, just use this function: 39 | 40 | ```swift 41 | func addSubviews(aSubviews: [ViewProvider]) 42 | ``` 43 | 44 | and add couple lines of code, here is example of code that demonstrate, how to do it: 45 | 46 | ```swift 47 | 48 | override func viewDidAppear(animated: Bool) { 49 | super.viewDidAppear(animated) 50 | 51 | scrollView.addSubviews([ 52 | createView(0), 53 | createView(1), 54 | createView(2), 55 | createView(3) 56 | ]) 57 | } 58 | 59 | 60 | func createView(color: Int) -> UIView { 61 | var view = UIView(frame: CGRectMake(0, 0, 100, 100)) 62 | view.backgroundColor = UIColor.randomColor 63 | view.layer.cornerRadius = 10.0 64 | return view 65 | } 66 | 67 | ``` 68 | 69 | So the **PagedScrollView** operate with **ViewProvider** : 70 | 71 | ```swift 72 | @objc protocol ViewProvider { 73 | var view: UIView! { get } 74 | } 75 | ``` 76 | 77 | so **ViewProvider** is the class that can provide view. **UIViewController** is already could be used, providing it's own view. 78 | **UIView** itself is also a **ViewProvider**, providing itself. 79 | 80 | > Keep in mind, **PagedScrollView** don't keep reference to ViewProviders, so you have to handle ownership of this objects by yourself. But the views, that were provided by ViewProviders will be added as subview, so they will be reverenced by **PagedScrollView** 81 | 82 | ## Transition 83 | 84 | You can use 5 build in transform classes for views sliding 85 | 86 | ### None 87 | 88 | ![ScreenShot](resources/Basic\ Cards.gif) 89 | 90 | ```swift 91 | scrollView.transition = .None 92 | ``` 93 | 94 | ### Slide 95 | 96 | ![ScreenShot](resources/SlideDemo.gif) 97 | 98 | ```swift 99 | scrollView.transition = .Slide 100 | ``` 101 | 102 | ### Dive 103 | 104 | ![ScreenShot](resources/DiveDemo.gif) 105 | 106 | ```swift 107 | scrollView.transition = .Dive 108 | ``` 109 | 110 | ### Roll 111 | 112 | ![ScreenShot](resources/RollDemo.gif) 113 | 114 | ```swift 115 | scrollView.transition = .Roll 116 | ``` 117 | 118 | ### Cards 119 | 120 | ![ScreenShot](resources/CardsDemo.gif) 121 | 122 | ```swift 123 | scrollView.transition = .Cards 124 | ``` 125 | 126 | 127 | ## PagedReusableScrollView 128 | That class works a UITabelViewController, it reuse **ViewProvider**. So you have to implement **PagedReusableScrollViewDataSource** protocol. This class owns the ViewProvider objects and provide two functions for reuse: 129 | 130 | ```swift 131 | func dequeueReusableView(#tag:Int) -> ViewProvider? 132 | func dequeueReusableView(#viewClass:AnyClass) -> ViewProvider? 133 | ``` 134 | 135 | so **ViewProvider** could be reused by tag or class 136 | 137 | **PagedReusableScrollViewDataSource** require that functions: 138 | 139 | ```swift 140 | func scrollView(scrollView: PagedReusableScrollView, viewIndex index: Int) -> ViewProvider 141 | func numberOfViews(forScrollView scrollView: PagedReusableScrollView) -> Int 142 | ``` 143 | 144 | so putting all together, the example implementation could be like that: 145 | 146 | ```swift 147 | extension ViewController3: PagedReusableScrollViewDataSource { 148 | 149 | func scrollView(scrollView: PagedReusableScrollView, viewIndex index: Int) -> ViewProvider { 150 | var newView:SimpleCardViewController? = scrollView.dequeueReusableView(tag: 1 ) as? SimpleCardViewController 151 | if newView == nil { 152 | newView = SimpleCardViewController() 153 | } 154 | newView?.imageName = "photo\(index%5).jpg" 155 | return newView! 156 | } 157 | 158 | func numberOfViews(forScrollView scrollView: PagedReusableScrollView) -> Int { 159 | return 10 160 | } 161 | 162 | } 163 | ``` 164 | 165 | the result will be like that: 166 | 167 | ![ScreenShot](resources/ReusableDemo.gif) 168 | 169 | ## PagedParallaxScrollView 170 | This view is populate to it's views about current parallax progress, from **-100** to **100**, **0** is central position. 171 | So you can adjust constraint, positions, colors etc regarding position. 172 | 173 | So view of **ViewProvider** should confirm protocol: 174 | 175 | ```swift 176 | @objc protocol PagedScrollViewParallaxView: class { 177 | func parallaxProgressChanged(progress:Int) 178 | } 179 | ``` 180 | 181 | If you want use ViewController as ViewProvider, you can make that view as **ParallaxViewProxy** subclass. So **ParallaxViewProxy** redirect all parallax progress to it's parallaxController. 182 | 183 | so ViewControllers's implementation could be like that: 184 | 185 | ```swift 186 | extension ParralaxCardViewController: PagedScrollViewParallaxView { 187 | 188 | func parallaxProgressChanged(progress:Int) { 189 | self.imageView.bounds = CGRectMake(CGFloat(progress), 0, imageView.bounds.size.width, imageView.bounds.size.height) 190 | detailsCentralConstraint.constant = CGFloat(-progress*4) 191 | imageCentralConstraint.constant = CGFloat(-progress) 192 | titleTopConstraint.constant = CGFloat(abs(progress)) 193 | } 194 | 195 | } 196 | ``` 197 | 198 | and result of that: 199 | 200 | ![ScreenShot](resources/ParallaxDemo.gif) 201 | 202 | ## Using ViewController as ViewProvider 203 | So anyone could be ViewProvider, but if you are using **UIViewController** subclass as **ViewProvider** you are expecting to have all View Controller lifecycle works as expected and described in apple doc: 204 | 205 | 206 | [![lyfecycle](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIViewController_Class/Art/UIViewController%20Class%20Reference_2x.png)](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIViewController_Class/index.html) 207 | 208 | 209 | And expecting to get rotation callback for your child view controllers, for example handling it in iOS8+ : 210 | ```swift 211 | func viewWillTransitionToSize(_ size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) 212 | ``` 213 | To implement it, regarding [Aplle Doc](https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/CreatingCustomContainerViewControllers/CreatingCustomContainerViewControllers.html), we have to implement some logic in our container view controller (example from Apple Doc): 214 | 215 | ```Objective-C 216 | - (void) displayContentController: (UIViewController*) content; 217 | { 218 | [self addChildViewController:content]; // 1 219 | content.view.frame = [self frameForContentController]; // 2 220 | [self.view addSubview:self.currentClientView]; 221 | [content didMoveToParentViewController:self]; // 3 222 | } 223 | ``` 224 | The issue is that PagesScrollView is not a view controller and could not be container. Moreover, the view don't have reference to it's view controller, so you have to do it by yourself. 225 | Fortunately, all you need is just inherit the ViewController, that owns PagedScrollView from **PagedScrollViewContainerViewController** : 226 | ```swift 227 | class ViewController4: PagedScrollViewContainerViewController { 228 | ... 229 | ``` 230 | And it will implement optional functions to handle it. So all your child ViewControllers will behave as expected, getting all lifecysle messages like **viewWillAppear** and **viewWillDisappear** and rotation messages. 231 | You can check it in source code in **ParralaxCardViewController**: 232 | ```swift 233 | override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) { 234 | println("\(self) viewWillTransitionToSize: \(size) with coordinator: \(coordinator)") 235 | } 236 | ``` 237 | 238 | ## Custom Transition 239 | 240 | You can assign *customTransition* property to any transofrmation. The transformation is described by **PagedScrollViewTransitionProperties** struct: 241 | 242 | ```swift 243 | struct PagedScrollViewTransitionProperties { 244 | var angleRatio: CGFloat = 0.0 245 | var translation: CGVector = CGVector(dx:0.0, dy:0.0) 246 | var rotation: Rotation3D = Rotation3D() 247 | } 248 | 249 | struct Rotation3D { 250 | var x:CGFloat = 0.0 251 | var y:CGFloat = 0.0 252 | var z:CGFloat = 0.0 253 | } 254 | ``` 255 | 256 | All build in transitions are **PagedScrollViewTransitionProperties** as well. So to create and apply custom property use that code: 257 | 258 | ```swift 259 | scrollView.customGTransition = PagedScrollViewTransitionProperties(angleRatio: 0.5, translation: CGVector(dx:0.25,dy:0.0), rotation: Rotation3D(x:-1.0,y:0.0,z:0.0)) 260 | scrollView.transition = .Custom 261 | ``` 262 | 263 | # Credits 264 | 265 | I'd appreciate it to mention the use of this code somewhere if you use it in an app. On a website, in an about page, in the app itself, whatever. Or let me know by email or through github. It's nice to know where one's code is used. 266 | 267 | Implemented by MadAppGang.com, we do awesome iOS apps. 268 | 269 | # License 270 | 271 | **MAGPagedScrollView** published under the MIT license: 272 | 273 | Copyright (C) 2015, Ievgen Rudenko, MadAppGang 274 | 275 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 276 | 277 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 278 | 279 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 280 | 281 | 282 | 283 | [![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/MadAppGang/magpagedscrollview/trend.png)](https://bitdeli.com/free "Bitdeli Badge") 284 | 285 | -------------------------------------------------------------------------------- /resources/Basic Cards.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MadAppGang/MAGPagedScrollView/df0f51a21c3ce8ae48bf8865b29c0010859988f8/resources/Basic Cards.gif -------------------------------------------------------------------------------- /resources/CardsDemo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MadAppGang/MAGPagedScrollView/df0f51a21c3ce8ae48bf8865b29c0010859988f8/resources/CardsDemo.gif -------------------------------------------------------------------------------- /resources/DiveDemo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MadAppGang/MAGPagedScrollView/df0f51a21c3ce8ae48bf8865b29c0010859988f8/resources/DiveDemo.gif -------------------------------------------------------------------------------- /resources/MAGPagedScrollViewDemo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MadAppGang/MAGPagedScrollView/df0f51a21c3ce8ae48bf8865b29c0010859988f8/resources/MAGPagedScrollViewDemo.gif -------------------------------------------------------------------------------- /resources/MAGPagedScrollViewDemo.mov: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MadAppGang/MAGPagedScrollView/df0f51a21c3ce8ae48bf8865b29c0010859988f8/resources/MAGPagedScrollViewDemo.mov -------------------------------------------------------------------------------- /resources/ParallaxDemo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MadAppGang/MAGPagedScrollView/df0f51a21c3ce8ae48bf8865b29c0010859988f8/resources/ParallaxDemo.gif -------------------------------------------------------------------------------- /resources/ReusableDemo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MadAppGang/MAGPagedScrollView/df0f51a21c3ce8ae48bf8865b29c0010859988f8/resources/ReusableDemo.gif -------------------------------------------------------------------------------- /resources/RollDemo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MadAppGang/MAGPagedScrollView/df0f51a21c3ce8ae48bf8865b29c0010859988f8/resources/RollDemo.gif -------------------------------------------------------------------------------- /resources/SlideDemo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MadAppGang/MAGPagedScrollView/df0f51a21c3ce8ae48bf8865b29c0010859988f8/resources/SlideDemo.gif --------------------------------------------------------------------------------