├── .circleci └── config.yml ├── .gitignore ├── LICENSE ├── MyPlayground.playground ├── Contents.swift └── contents.xcplayground ├── README.md ├── SimplePagedView.podspec ├── SimplePagedViewFramework.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── xcshareddata │ └── xcschemes │ │ ├── SimplePagedViewFramework.xcscheme │ │ └── SimplePagedViewFrameworkTests.xcscheme └── xcuserdata │ └── newuser.xcuserdatad │ └── xcschemes │ └── xcschememanagement.plist ├── SimplePagedViewFramework ├── Example │ └── SimplePagedViewExample │ │ ├── SimplePagedViewExample.xcodeproj │ │ └── project.pbxproj │ │ └── SimplePagedViewExample │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── Contents.json │ │ └── add.imageset │ │ │ ├── Contents.json │ │ │ └── add.pdf │ │ ├── Base.lproj │ │ └── LaunchScreen.storyboard │ │ ├── Info.plist │ │ └── ViewController.swift ├── Info.plist └── Source │ ├── Errors │ └── DotsError.swift │ ├── Extensions │ ├── NSLayoutConstraint.swift │ ├── UIImage.swift │ ├── UIView.swift │ └── UIViewController.swift │ ├── SimplePagedView.swift │ └── Views │ ├── DotView.swift │ └── PageDotsView.swift └── SimplePagedViewFrameworkTests ├── Info.plist └── SimplePagedViewFrameworkTests.swift /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | workflows: 4 | version: 2 5 | main: 6 | jobs: 7 | - hold: 8 | type: approval 9 | - build: 10 | requires: [hold] 11 | 12 | jobs: 13 | build: 14 | requires: hold 15 | # Specify the Xcode version to use 16 | macos: 17 | xcode: "10.1.0" 18 | 19 | steps: 20 | - checkout 21 | 22 | - attach_workspace: 23 | at: . 24 | 25 | - run: 26 | name: Build and run tests 27 | command: fastlane scan 28 | environment: 29 | SCAN_DEVICE: iPhone 7 30 | SCAN_SCHEME: SimplePagedViewFrameworkTests 31 | SCAN_DERIVED_DATA_PATH: build/DerivedData 32 | SCAN_OUTPUT_DIRECTORY: build/Output 33 | 34 | - persist_to_workspace: 35 | root: . 36 | paths: 37 | - 'build' 38 | 39 | # Collect XML test results data to show in the UI, 40 | # and save the same XML files under test-results folder 41 | # in the Artifacts tab 42 | - store_test_results: 43 | path: test_output/report.xml 44 | - store_artifacts: 45 | path: /tmp/test-results 46 | destination: scan-test-results 47 | - store_artifacts: 48 | path: ~/Library/Logs/scan 49 | destination: scan-logs 50 | 51 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xccheckout 23 | *.xcscmblueprint 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | *.ipa 28 | *.dSYM.zip 29 | *.dSYM 30 | 31 | ## Playgrounds 32 | timeline.xctimeline 33 | playground.xcworkspace 34 | 35 | # Swift Package Manager 36 | # 37 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 38 | # Packages/ 39 | # Package.pins 40 | # Package.resolved 41 | .build/ 42 | 43 | # CocoaPods 44 | # 45 | # We recommend against adding the Pods directory to your .gitignore. However 46 | # you should judge for yourself, the pros and cons are mentioned at: 47 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 48 | # 49 | # Pods/ 50 | # 51 | # Add this line if you want to avoid checking in source code from the Xcode workspace 52 | # *.xcworkspace 53 | 54 | # Carthage 55 | # 56 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 57 | # Carthage/Checkouts 58 | 59 | Carthage/Build 60 | 61 | # fastlane 62 | # 63 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 64 | # screenshots whenever they are needed. 65 | # For more information about the recommended setup visit: 66 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 67 | 68 | fastlane/report.xml 69 | fastlane/Preview.html 70 | fastlane/screenshots/**/*.png 71 | fastlane/test_output 72 | 73 | # Code Injection 74 | # 75 | # After new code Injection tools there's a generated folder /iOSInjectionProject 76 | # https://github.com/johnno1962/injectionforxcode 77 | 78 | iOSInjectionProject/ 79 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2018 Air Computing Inc 2 | 3 | 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: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | 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. 8 | -------------------------------------------------------------------------------- /MyPlayground.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import SimplePagedViewFramework 3 | import PlaygroundSupport 4 | 5 | let green = UIView() 6 | green.backgroundColor = .green 7 | 8 | let red = UIView() 9 | red.backgroundColor = .red 10 | 11 | let orange = UIView() 12 | orange.backgroundColor = .orange 13 | 14 | let pagedView = SimplePagedView( 15 | // indicatorColor: .cyan, 16 | // dotSize: 20, 17 | with: green, red, orange 18 | ) 19 | 20 | pagedView.frame = CGRect(x: 0, y: 0, width: 350, height: 700) 21 | 22 | pagedView.pageIndicatorIsInteractive = true 23 | 24 | PlaygroundPage.current.liveView = pagedView 25 | -------------------------------------------------------------------------------- /MyPlayground.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SimplePagedView 2 | 3 | SimplePagedView is an iOS component that makes it as easy as possible to set up a page view for things like onboarding or presenting information. 4 | 5 | simulator screen shot - iphone 8 - 2018-12-12 at 12 54 46 6 | 7 | ## Installation 8 | 9 | ```ruby 10 | pod 'SimplePagedView' 11 | ``` 12 | 13 | ## Usage 14 | 15 | ### Programmatic setup 16 | ```swift 17 | // Create a PagedViewController by providing it with a view for each page you'd like it to contain 18 | let simplePagedView = SimplePagedView(with: 19 | LogoView(presenter: welcomePresenter), 20 | CardPageView(image: ThemeManager.Images.welcomeTourSlide1, 21 | subtitle: "Complete and resolve tasks on the go"), 22 | CardPageView(image: ThemeManager.Images.welcomeTourSlide2, 23 | subtitle: "Comment on tasks and conversations"), 24 | CardPageView(image: ThemeManager.Images.welcomeTourSlide3, 25 | subtitle: "Add files and pictures in seconds") 26 | ) 27 | 28 | // Add as subview and setup constraints/frame 29 | ``` 30 | -------------------------------------------------------------------------------- /SimplePagedView.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | 3 | s.name = "SimplePagedView" 4 | s.version = "1.1.0" 5 | s.summary = "A PageViewController replacement built to be as simple as possible" 6 | 7 | s.description = <<-DESC 8 | A PageViewController replacement built to be as simple as possible to use. Supports easy insertion of views and the classic page dots. Also supports many customization points alongside reasonable defaults. 9 | DESC 10 | 11 | s.homepage = "http://github.com/redbooth/SimplePagedView" 12 | 13 | s.license = "MIT" 14 | 15 | s.author = { "Alex Reilly" => "alexander.r.reilly@gmail.com" } 16 | s.social_media_url = "https://twitter.com/TheWisestFools" 17 | 18 | s.platform = :ios, "10.3" 19 | 20 | 21 | s.source = { :git => "https://github.com/redbooth/SimplePagedView.git", :tag => s.version } 22 | 23 | s.source_files = "SimplePagedViewFramework/Source/**/*{swift}" 24 | 25 | s.swift_version = "4.2" 26 | 27 | end 28 | -------------------------------------------------------------------------------- /SimplePagedViewFramework.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | B206EB0D21D69F1E00F39BD3 /* UIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B206EB0C21D69F1E00F39BD3 /* UIView.swift */; }; 11 | B2C6870F21C191F2000031AB /* SimplePagedViewFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B2C6870521C191F2000031AB /* SimplePagedViewFramework.framework */; }; 12 | B2C6871421C191F2000031AB /* SimplePagedViewFrameworkTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2C6871321C191F2000031AB /* SimplePagedViewFrameworkTests.swift */; }; 13 | B2C6872821C19218000031AB /* NSLayoutConstraint.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2C6872021C19217000031AB /* NSLayoutConstraint.swift */; }; 14 | B2C6872921C19218000031AB /* UIImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2C6872121C19217000031AB /* UIImage.swift */; }; 15 | B2C6872C21C19218000031AB /* SimplePagedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2C6872521C19218000031AB /* SimplePagedView.swift */; }; 16 | B2C6873121C1AE10000031AB /* UIViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2C6873021C1AE10000031AB /* UIViewController.swift */; }; 17 | B2C6898421C342D5000031AB /* PageDotsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2C6898321C342D5000031AB /* PageDotsView.swift */; }; 18 | B2C6898721C9806F000031AB /* DotsError.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2C6898621C9806E000031AB /* DotsError.swift */; }; 19 | B2C689B221CA12E0000031AB /* DotView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2C689B121CA12E0000031AB /* DotView.swift */; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXContainerItemProxy section */ 23 | B2C6871021C191F2000031AB /* PBXContainerItemProxy */ = { 24 | isa = PBXContainerItemProxy; 25 | containerPortal = B2C686FC21C191F2000031AB /* Project object */; 26 | proxyType = 1; 27 | remoteGlobalIDString = B2C6870421C191F2000031AB; 28 | remoteInfo = SimplePagedViewFramework; 29 | }; 30 | B2C689AC21C9993E000031AB /* PBXContainerItemProxy */ = { 31 | isa = PBXContainerItemProxy; 32 | containerPortal = B2C689A821C9993B000031AB /* SimplePagedViewExample.xcodeproj */; 33 | proxyType = 2; 34 | remoteGlobalIDString = B2C6899321C99938000031AB; 35 | remoteInfo = SimplePagedViewExample; 36 | }; 37 | /* End PBXContainerItemProxy section */ 38 | 39 | /* Begin PBXFileReference section */ 40 | B206EB0C21D69F1E00F39BD3 /* UIView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIView.swift; sourceTree = ""; }; 41 | B2C6870521C191F2000031AB /* SimplePagedViewFramework.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SimplePagedViewFramework.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 42 | B2C6870921C191F2000031AB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 43 | B2C6870E21C191F2000031AB /* SimplePagedViewFrameworkTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SimplePagedViewFrameworkTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 44 | B2C6871321C191F2000031AB /* SimplePagedViewFrameworkTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimplePagedViewFrameworkTests.swift; sourceTree = ""; }; 45 | B2C6871521C191F2000031AB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 46 | B2C6872021C19217000031AB /* NSLayoutConstraint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NSLayoutConstraint.swift; sourceTree = ""; }; 47 | B2C6872121C19217000031AB /* UIImage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIImage.swift; sourceTree = ""; }; 48 | B2C6872521C19218000031AB /* SimplePagedView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SimplePagedView.swift; sourceTree = ""; }; 49 | B2C6873021C1AE10000031AB /* UIViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIViewController.swift; sourceTree = ""; }; 50 | B2C6898321C342D5000031AB /* PageDotsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PageDotsView.swift; sourceTree = ""; }; 51 | B2C6898621C9806E000031AB /* DotsError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DotsError.swift; sourceTree = ""; }; 52 | B2C6898821C987EB000031AB /* MyPlayground.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = MyPlayground.playground; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; 53 | B2C689A821C9993B000031AB /* SimplePagedViewExample.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = SimplePagedViewExample.xcodeproj; path = SimplePagedViewExample/SimplePagedViewExample.xcodeproj; sourceTree = ""; }; 54 | B2C689B121CA12E0000031AB /* DotView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DotView.swift; sourceTree = ""; }; 55 | /* End PBXFileReference section */ 56 | 57 | /* Begin PBXFrameworksBuildPhase section */ 58 | B2C6870221C191F2000031AB /* Frameworks */ = { 59 | isa = PBXFrameworksBuildPhase; 60 | buildActionMask = 2147483647; 61 | files = ( 62 | ); 63 | runOnlyForDeploymentPostprocessing = 0; 64 | }; 65 | B2C6870B21C191F2000031AB /* Frameworks */ = { 66 | isa = PBXFrameworksBuildPhase; 67 | buildActionMask = 2147483647; 68 | files = ( 69 | B2C6870F21C191F2000031AB /* SimplePagedViewFramework.framework in Frameworks */, 70 | ); 71 | runOnlyForDeploymentPostprocessing = 0; 72 | }; 73 | /* End PBXFrameworksBuildPhase section */ 74 | 75 | /* Begin PBXGroup section */ 76 | B2C686FB21C191F2000031AB = { 77 | isa = PBXGroup; 78 | children = ( 79 | B2C6898821C987EB000031AB /* MyPlayground.playground */, 80 | B2C6870721C191F2000031AB /* SimplePagedViewFramework */, 81 | B2C6871221C191F2000031AB /* SimplePagedViewFrameworkTests */, 82 | B2C6870621C191F2000031AB /* Products */, 83 | ); 84 | sourceTree = ""; 85 | }; 86 | B2C6870621C191F2000031AB /* Products */ = { 87 | isa = PBXGroup; 88 | children = ( 89 | B2C6870521C191F2000031AB /* SimplePagedViewFramework.framework */, 90 | B2C6870E21C191F2000031AB /* SimplePagedViewFrameworkTests.xctest */, 91 | ); 92 | name = Products; 93 | sourceTree = ""; 94 | }; 95 | B2C6870721C191F2000031AB /* SimplePagedViewFramework */ = { 96 | isa = PBXGroup; 97 | children = ( 98 | B2C6898921C998FE000031AB /* Example */, 99 | B2C6872F21C1A8C8000031AB /* Source */, 100 | B2C6870921C191F2000031AB /* Info.plist */, 101 | ); 102 | path = SimplePagedViewFramework; 103 | sourceTree = ""; 104 | }; 105 | B2C6871221C191F2000031AB /* SimplePagedViewFrameworkTests */ = { 106 | isa = PBXGroup; 107 | children = ( 108 | B2C6871321C191F2000031AB /* SimplePagedViewFrameworkTests.swift */, 109 | B2C6871521C191F2000031AB /* Info.plist */, 110 | ); 111 | path = SimplePagedViewFrameworkTests; 112 | sourceTree = ""; 113 | }; 114 | B2C6871F21C19217000031AB /* Extensions */ = { 115 | isa = PBXGroup; 116 | children = ( 117 | B2C6872021C19217000031AB /* NSLayoutConstraint.swift */, 118 | B2C6872121C19217000031AB /* UIImage.swift */, 119 | B2C6873021C1AE10000031AB /* UIViewController.swift */, 120 | B206EB0C21D69F1E00F39BD3 /* UIView.swift */, 121 | ); 122 | path = Extensions; 123 | sourceTree = ""; 124 | }; 125 | B2C6872F21C1A8C8000031AB /* Source */ = { 126 | isa = PBXGroup; 127 | children = ( 128 | B2C6898521C9805B000031AB /* Errors */, 129 | B2C6872521C19218000031AB /* SimplePagedView.swift */, 130 | B2C6898221C342B6000031AB /* Views */, 131 | B2C6871F21C19217000031AB /* Extensions */, 132 | ); 133 | path = Source; 134 | sourceTree = ""; 135 | }; 136 | B2C6898221C342B6000031AB /* Views */ = { 137 | isa = PBXGroup; 138 | children = ( 139 | B2C6898321C342D5000031AB /* PageDotsView.swift */, 140 | B2C689B121CA12E0000031AB /* DotView.swift */, 141 | ); 142 | path = Views; 143 | sourceTree = ""; 144 | }; 145 | B2C6898521C9805B000031AB /* Errors */ = { 146 | isa = PBXGroup; 147 | children = ( 148 | B2C6898621C9806E000031AB /* DotsError.swift */, 149 | ); 150 | path = Errors; 151 | sourceTree = ""; 152 | }; 153 | B2C6898921C998FE000031AB /* Example */ = { 154 | isa = PBXGroup; 155 | children = ( 156 | B2C689A821C9993B000031AB /* SimplePagedViewExample.xcodeproj */, 157 | ); 158 | path = Example; 159 | sourceTree = ""; 160 | }; 161 | B2C689A921C9993B000031AB /* Products */ = { 162 | isa = PBXGroup; 163 | children = ( 164 | B2C689AD21C9993E000031AB /* SimplePagedViewExample.app */, 165 | ); 166 | name = Products; 167 | sourceTree = ""; 168 | }; 169 | /* End PBXGroup section */ 170 | 171 | /* Begin PBXHeadersBuildPhase section */ 172 | B2C6870021C191F2000031AB /* Headers */ = { 173 | isa = PBXHeadersBuildPhase; 174 | buildActionMask = 2147483647; 175 | files = ( 176 | ); 177 | runOnlyForDeploymentPostprocessing = 0; 178 | }; 179 | /* End PBXHeadersBuildPhase section */ 180 | 181 | /* Begin PBXNativeTarget section */ 182 | B2C6870421C191F2000031AB /* SimplePagedViewFramework */ = { 183 | isa = PBXNativeTarget; 184 | buildConfigurationList = B2C6871921C191F2000031AB /* Build configuration list for PBXNativeTarget "SimplePagedViewFramework" */; 185 | buildPhases = ( 186 | B2C6870021C191F2000031AB /* Headers */, 187 | B2C6870121C191F2000031AB /* Sources */, 188 | B2C6870221C191F2000031AB /* Frameworks */, 189 | B2C6870321C191F2000031AB /* Resources */, 190 | ); 191 | buildRules = ( 192 | ); 193 | dependencies = ( 194 | ); 195 | name = SimplePagedViewFramework; 196 | productName = SimplePagedViewFramework; 197 | productReference = B2C6870521C191F2000031AB /* SimplePagedViewFramework.framework */; 198 | productType = "com.apple.product-type.framework"; 199 | }; 200 | B2C6870D21C191F2000031AB /* SimplePagedViewFrameworkTests */ = { 201 | isa = PBXNativeTarget; 202 | buildConfigurationList = B2C6871C21C191F2000031AB /* Build configuration list for PBXNativeTarget "SimplePagedViewFrameworkTests" */; 203 | buildPhases = ( 204 | B2C6870A21C191F2000031AB /* Sources */, 205 | B2C6870B21C191F2000031AB /* Frameworks */, 206 | B2C6870C21C191F2000031AB /* Resources */, 207 | ); 208 | buildRules = ( 209 | ); 210 | dependencies = ( 211 | B2C6871121C191F2000031AB /* PBXTargetDependency */, 212 | ); 213 | name = SimplePagedViewFrameworkTests; 214 | productName = SimplePagedViewFrameworkTests; 215 | productReference = B2C6870E21C191F2000031AB /* SimplePagedViewFrameworkTests.xctest */; 216 | productType = "com.apple.product-type.bundle.unit-test"; 217 | }; 218 | /* End PBXNativeTarget section */ 219 | 220 | /* Begin PBXProject section */ 221 | B2C686FC21C191F2000031AB /* Project object */ = { 222 | isa = PBXProject; 223 | attributes = { 224 | LastSwiftUpdateCheck = 1010; 225 | LastUpgradeCheck = 1010; 226 | ORGANIZATIONNAME = twof; 227 | TargetAttributes = { 228 | B2C6870421C191F2000031AB = { 229 | CreatedOnToolsVersion = 10.1; 230 | LastSwiftMigration = 1010; 231 | }; 232 | B2C6870D21C191F2000031AB = { 233 | CreatedOnToolsVersion = 10.1; 234 | }; 235 | }; 236 | }; 237 | buildConfigurationList = B2C686FF21C191F2000031AB /* Build configuration list for PBXProject "SimplePagedViewFramework" */; 238 | compatibilityVersion = "Xcode 9.3"; 239 | developmentRegion = en; 240 | hasScannedForEncodings = 0; 241 | knownRegions = ( 242 | en, 243 | ); 244 | mainGroup = B2C686FB21C191F2000031AB; 245 | productRefGroup = B2C6870621C191F2000031AB /* Products */; 246 | projectDirPath = ""; 247 | projectReferences = ( 248 | { 249 | ProductGroup = B2C689A921C9993B000031AB /* Products */; 250 | ProjectRef = B2C689A821C9993B000031AB /* SimplePagedViewExample.xcodeproj */; 251 | }, 252 | ); 253 | projectRoot = ""; 254 | targets = ( 255 | B2C6870421C191F2000031AB /* SimplePagedViewFramework */, 256 | B2C6870D21C191F2000031AB /* SimplePagedViewFrameworkTests */, 257 | ); 258 | }; 259 | /* End PBXProject section */ 260 | 261 | /* Begin PBXReferenceProxy section */ 262 | B2C689AD21C9993E000031AB /* SimplePagedViewExample.app */ = { 263 | isa = PBXReferenceProxy; 264 | fileType = wrapper.application; 265 | path = SimplePagedViewExample.app; 266 | remoteRef = B2C689AC21C9993E000031AB /* PBXContainerItemProxy */; 267 | sourceTree = BUILT_PRODUCTS_DIR; 268 | }; 269 | /* End PBXReferenceProxy section */ 270 | 271 | /* Begin PBXResourcesBuildPhase section */ 272 | B2C6870321C191F2000031AB /* Resources */ = { 273 | isa = PBXResourcesBuildPhase; 274 | buildActionMask = 2147483647; 275 | files = ( 276 | ); 277 | runOnlyForDeploymentPostprocessing = 0; 278 | }; 279 | B2C6870C21C191F2000031AB /* Resources */ = { 280 | isa = PBXResourcesBuildPhase; 281 | buildActionMask = 2147483647; 282 | files = ( 283 | ); 284 | runOnlyForDeploymentPostprocessing = 0; 285 | }; 286 | /* End PBXResourcesBuildPhase section */ 287 | 288 | /* Begin PBXSourcesBuildPhase section */ 289 | B2C6870121C191F2000031AB /* Sources */ = { 290 | isa = PBXSourcesBuildPhase; 291 | buildActionMask = 2147483647; 292 | files = ( 293 | B206EB0D21D69F1E00F39BD3 /* UIView.swift in Sources */, 294 | B2C6898721C9806F000031AB /* DotsError.swift in Sources */, 295 | B2C6872821C19218000031AB /* NSLayoutConstraint.swift in Sources */, 296 | B2C689B221CA12E0000031AB /* DotView.swift in Sources */, 297 | B2C6898421C342D5000031AB /* PageDotsView.swift in Sources */, 298 | B2C6872C21C19218000031AB /* SimplePagedView.swift in Sources */, 299 | B2C6872921C19218000031AB /* UIImage.swift in Sources */, 300 | B2C6873121C1AE10000031AB /* UIViewController.swift in Sources */, 301 | ); 302 | runOnlyForDeploymentPostprocessing = 0; 303 | }; 304 | B2C6870A21C191F2000031AB /* Sources */ = { 305 | isa = PBXSourcesBuildPhase; 306 | buildActionMask = 2147483647; 307 | files = ( 308 | B2C6871421C191F2000031AB /* SimplePagedViewFrameworkTests.swift in Sources */, 309 | ); 310 | runOnlyForDeploymentPostprocessing = 0; 311 | }; 312 | /* End PBXSourcesBuildPhase section */ 313 | 314 | /* Begin PBXTargetDependency section */ 315 | B2C6871121C191F2000031AB /* PBXTargetDependency */ = { 316 | isa = PBXTargetDependency; 317 | target = B2C6870421C191F2000031AB /* SimplePagedViewFramework */; 318 | targetProxy = B2C6871021C191F2000031AB /* PBXContainerItemProxy */; 319 | }; 320 | /* End PBXTargetDependency section */ 321 | 322 | /* Begin XCBuildConfiguration section */ 323 | B2C6871721C191F2000031AB /* Debug */ = { 324 | isa = XCBuildConfiguration; 325 | buildSettings = { 326 | ALWAYS_SEARCH_USER_PATHS = NO; 327 | CLANG_ANALYZER_NONNULL = YES; 328 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 329 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 330 | CLANG_CXX_LIBRARY = "libc++"; 331 | CLANG_ENABLE_MODULES = YES; 332 | CLANG_ENABLE_OBJC_ARC = YES; 333 | CLANG_ENABLE_OBJC_WEAK = YES; 334 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 335 | CLANG_WARN_BOOL_CONVERSION = YES; 336 | CLANG_WARN_COMMA = YES; 337 | CLANG_WARN_CONSTANT_CONVERSION = YES; 338 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 339 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 340 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 341 | CLANG_WARN_EMPTY_BODY = YES; 342 | CLANG_WARN_ENUM_CONVERSION = YES; 343 | CLANG_WARN_INFINITE_RECURSION = YES; 344 | CLANG_WARN_INT_CONVERSION = YES; 345 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 346 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 347 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 348 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 349 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 350 | CLANG_WARN_STRICT_PROTOTYPES = YES; 351 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 352 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 353 | CLANG_WARN_UNREACHABLE_CODE = YES; 354 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 355 | CODE_SIGN_IDENTITY = "iPhone Developer"; 356 | COPY_PHASE_STRIP = NO; 357 | CURRENT_PROJECT_VERSION = 1; 358 | DEBUG_INFORMATION_FORMAT = dwarf; 359 | ENABLE_STRICT_OBJC_MSGSEND = YES; 360 | ENABLE_TESTABILITY = YES; 361 | GCC_C_LANGUAGE_STANDARD = gnu11; 362 | GCC_DYNAMIC_NO_PIC = NO; 363 | GCC_NO_COMMON_BLOCKS = YES; 364 | GCC_OPTIMIZATION_LEVEL = 0; 365 | GCC_PREPROCESSOR_DEFINITIONS = ( 366 | "DEBUG=1", 367 | "$(inherited)", 368 | ); 369 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 370 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 371 | GCC_WARN_UNDECLARED_SELECTOR = YES; 372 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 373 | GCC_WARN_UNUSED_FUNCTION = YES; 374 | GCC_WARN_UNUSED_VARIABLE = YES; 375 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 376 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 377 | MTL_FAST_MATH = YES; 378 | ONLY_ACTIVE_ARCH = YES; 379 | SDKROOT = iphoneos; 380 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 381 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 382 | VERSIONING_SYSTEM = "apple-generic"; 383 | VERSION_INFO_PREFIX = ""; 384 | }; 385 | name = Debug; 386 | }; 387 | B2C6871821C191F2000031AB /* Release */ = { 388 | isa = XCBuildConfiguration; 389 | buildSettings = { 390 | ALWAYS_SEARCH_USER_PATHS = NO; 391 | CLANG_ANALYZER_NONNULL = YES; 392 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 393 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 394 | CLANG_CXX_LIBRARY = "libc++"; 395 | CLANG_ENABLE_MODULES = YES; 396 | CLANG_ENABLE_OBJC_ARC = YES; 397 | CLANG_ENABLE_OBJC_WEAK = YES; 398 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 399 | CLANG_WARN_BOOL_CONVERSION = YES; 400 | CLANG_WARN_COMMA = YES; 401 | CLANG_WARN_CONSTANT_CONVERSION = YES; 402 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 403 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 404 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 405 | CLANG_WARN_EMPTY_BODY = YES; 406 | CLANG_WARN_ENUM_CONVERSION = YES; 407 | CLANG_WARN_INFINITE_RECURSION = YES; 408 | CLANG_WARN_INT_CONVERSION = YES; 409 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 410 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 411 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 412 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 413 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 414 | CLANG_WARN_STRICT_PROTOTYPES = YES; 415 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 416 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 417 | CLANG_WARN_UNREACHABLE_CODE = YES; 418 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 419 | CODE_SIGN_IDENTITY = "iPhone Developer"; 420 | COPY_PHASE_STRIP = NO; 421 | CURRENT_PROJECT_VERSION = 1; 422 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 423 | ENABLE_NS_ASSERTIONS = NO; 424 | ENABLE_STRICT_OBJC_MSGSEND = YES; 425 | GCC_C_LANGUAGE_STANDARD = gnu11; 426 | GCC_NO_COMMON_BLOCKS = YES; 427 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 428 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 429 | GCC_WARN_UNDECLARED_SELECTOR = YES; 430 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 431 | GCC_WARN_UNUSED_FUNCTION = YES; 432 | GCC_WARN_UNUSED_VARIABLE = YES; 433 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 434 | MTL_ENABLE_DEBUG_INFO = NO; 435 | MTL_FAST_MATH = YES; 436 | SDKROOT = iphoneos; 437 | SWIFT_COMPILATION_MODE = wholemodule; 438 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 439 | VALIDATE_PRODUCT = YES; 440 | VERSIONING_SYSTEM = "apple-generic"; 441 | VERSION_INFO_PREFIX = ""; 442 | }; 443 | name = Release; 444 | }; 445 | B2C6871A21C191F2000031AB /* Debug */ = { 446 | isa = XCBuildConfiguration; 447 | buildSettings = { 448 | CLANG_ENABLE_MODULES = YES; 449 | CODE_SIGN_IDENTITY = "iPhone Developer"; 450 | CODE_SIGN_STYLE = Automatic; 451 | DEFINES_MODULE = YES; 452 | DEVELOPMENT_TEAM = P2PP2EM79F; 453 | DYLIB_COMPATIBILITY_VERSION = 1; 454 | DYLIB_CURRENT_VERSION = 1; 455 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 456 | INFOPLIST_FILE = SimplePagedViewFramework/Info.plist; 457 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 458 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 459 | LD_RUNPATH_SEARCH_PATHS = ( 460 | "$(inherited)", 461 | "@executable_path/Frameworks", 462 | "@loader_path/Frameworks", 463 | ); 464 | PRODUCT_BUNDLE_IDENTIFIER = com.twof.SimplePagedViewFramework; 465 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 466 | SKIP_INSTALL = YES; 467 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 468 | SWIFT_VERSION = 4.2; 469 | TARGETED_DEVICE_FAMILY = "1,2"; 470 | }; 471 | name = Debug; 472 | }; 473 | B2C6871B21C191F2000031AB /* Release */ = { 474 | isa = XCBuildConfiguration; 475 | buildSettings = { 476 | CLANG_ENABLE_MODULES = YES; 477 | CODE_SIGN_IDENTITY = ""; 478 | CODE_SIGN_STYLE = Automatic; 479 | DEFINES_MODULE = YES; 480 | DEVELOPMENT_TEAM = P2PP2EM79F; 481 | DYLIB_COMPATIBILITY_VERSION = 1; 482 | DYLIB_CURRENT_VERSION = 1; 483 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 484 | INFOPLIST_FILE = SimplePagedViewFramework/Info.plist; 485 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 486 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 487 | LD_RUNPATH_SEARCH_PATHS = ( 488 | "$(inherited)", 489 | "@executable_path/Frameworks", 490 | "@loader_path/Frameworks", 491 | ); 492 | PRODUCT_BUNDLE_IDENTIFIER = com.twof.SimplePagedViewFramework; 493 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 494 | SKIP_INSTALL = YES; 495 | SWIFT_VERSION = 4.2; 496 | TARGETED_DEVICE_FAMILY = "1,2"; 497 | }; 498 | name = Release; 499 | }; 500 | B2C6871D21C191F2000031AB /* Debug */ = { 501 | isa = XCBuildConfiguration; 502 | buildSettings = { 503 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 504 | CODE_SIGN_STYLE = Automatic; 505 | INFOPLIST_FILE = SimplePagedViewFrameworkTests/Info.plist; 506 | LD_RUNPATH_SEARCH_PATHS = ( 507 | "$(inherited)", 508 | "@executable_path/Frameworks", 509 | "@loader_path/Frameworks", 510 | ); 511 | PRODUCT_BUNDLE_IDENTIFIER = com.twof.SimplePagedViewFrameworkTests; 512 | PRODUCT_NAME = "$(TARGET_NAME)"; 513 | SWIFT_VERSION = 4.2; 514 | TARGETED_DEVICE_FAMILY = "1,2"; 515 | }; 516 | name = Debug; 517 | }; 518 | B2C6871E21C191F2000031AB /* Release */ = { 519 | isa = XCBuildConfiguration; 520 | buildSettings = { 521 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 522 | CODE_SIGN_STYLE = Automatic; 523 | INFOPLIST_FILE = SimplePagedViewFrameworkTests/Info.plist; 524 | LD_RUNPATH_SEARCH_PATHS = ( 525 | "$(inherited)", 526 | "@executable_path/Frameworks", 527 | "@loader_path/Frameworks", 528 | ); 529 | PRODUCT_BUNDLE_IDENTIFIER = com.twof.SimplePagedViewFrameworkTests; 530 | PRODUCT_NAME = "$(TARGET_NAME)"; 531 | SWIFT_VERSION = 4.2; 532 | TARGETED_DEVICE_FAMILY = "1,2"; 533 | }; 534 | name = Release; 535 | }; 536 | /* End XCBuildConfiguration section */ 537 | 538 | /* Begin XCConfigurationList section */ 539 | B2C686FF21C191F2000031AB /* Build configuration list for PBXProject "SimplePagedViewFramework" */ = { 540 | isa = XCConfigurationList; 541 | buildConfigurations = ( 542 | B2C6871721C191F2000031AB /* Debug */, 543 | B2C6871821C191F2000031AB /* Release */, 544 | ); 545 | defaultConfigurationIsVisible = 0; 546 | defaultConfigurationName = Release; 547 | }; 548 | B2C6871921C191F2000031AB /* Build configuration list for PBXNativeTarget "SimplePagedViewFramework" */ = { 549 | isa = XCConfigurationList; 550 | buildConfigurations = ( 551 | B2C6871A21C191F2000031AB /* Debug */, 552 | B2C6871B21C191F2000031AB /* Release */, 553 | ); 554 | defaultConfigurationIsVisible = 0; 555 | defaultConfigurationName = Release; 556 | }; 557 | B2C6871C21C191F2000031AB /* Build configuration list for PBXNativeTarget "SimplePagedViewFrameworkTests" */ = { 558 | isa = XCConfigurationList; 559 | buildConfigurations = ( 560 | B2C6871D21C191F2000031AB /* Debug */, 561 | B2C6871E21C191F2000031AB /* Release */, 562 | ); 563 | defaultConfigurationIsVisible = 0; 564 | defaultConfigurationName = Release; 565 | }; 566 | /* End XCConfigurationList section */ 567 | }; 568 | rootObject = B2C686FC21C191F2000031AB /* Project object */; 569 | } 570 | -------------------------------------------------------------------------------- /SimplePagedViewFramework.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SimplePagedViewFramework.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /SimplePagedViewFramework.xcodeproj/xcshareddata/xcschemes/SimplePagedViewFramework.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 | 67 | 68 | 78 | 79 | 85 | 86 | 87 | 88 | 89 | 90 | 96 | 97 | 103 | 104 | 105 | 106 | 108 | 109 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /SimplePagedViewFramework.xcodeproj/xcshareddata/xcschemes/SimplePagedViewFrameworkTests.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 55 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 74 | 80 | 81 | 82 | 83 | 85 | 86 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /SimplePagedViewFramework.xcodeproj/xcuserdata/newuser.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | SimplePagedViewFramework.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | SimplePagedViewFrameworkTests.xcscheme_^#shared#^_ 13 | 14 | orderHint 15 | 1 16 | 17 | 18 | SuppressBuildableAutocreation 19 | 20 | B2C6870421C191F2000031AB 21 | 22 | primary 23 | 24 | 25 | B2C6870D21C191F2000031AB 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /SimplePagedViewFramework/Example/SimplePagedViewExample/SimplePagedViewExample.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 24E7CF0321FD0407009E6E79 /* SimplePagedViewFramework.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = B2C689AF21C99CC0000031AB /* SimplePagedViewFramework.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 11 | B2C6899721C99938000031AB /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2C6899621C99938000031AB /* AppDelegate.swift */; }; 12 | B2C6899921C99938000031AB /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2C6899821C99938000031AB /* ViewController.swift */; }; 13 | B2C6899E21C9993A000031AB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B2C6899D21C9993A000031AB /* Assets.xcassets */; }; 14 | B2C689A121C9993B000031AB /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B2C6899F21C9993B000031AB /* LaunchScreen.storyboard */; }; 15 | B2C689B021C99CC0000031AB /* SimplePagedViewFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B2C689AF21C99CC0000031AB /* SimplePagedViewFramework.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; 16 | /* End PBXBuildFile section */ 17 | 18 | /* Begin PBXCopyFilesBuildPhase section */ 19 | 24E7CF0221FD03ED009E6E79 /* CopyFiles */ = { 20 | isa = PBXCopyFilesBuildPhase; 21 | buildActionMask = 2147483647; 22 | dstPath = ""; 23 | dstSubfolderSpec = 10; 24 | files = ( 25 | 24E7CF0321FD0407009E6E79 /* SimplePagedViewFramework.framework in CopyFiles */, 26 | ); 27 | runOnlyForDeploymentPostprocessing = 0; 28 | }; 29 | /* End PBXCopyFilesBuildPhase section */ 30 | 31 | /* Begin PBXFileReference section */ 32 | B2C6899321C99938000031AB /* SimplePagedViewExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SimplePagedViewExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 33 | B2C6899621C99938000031AB /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 34 | B2C6899821C99938000031AB /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 35 | B2C6899D21C9993A000031AB /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 36 | B2C689A021C9993B000031AB /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 37 | B2C689A221C9993B000031AB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 38 | B2C689AF21C99CC0000031AB /* SimplePagedViewFramework.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = SimplePagedViewFramework.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 39 | /* End PBXFileReference section */ 40 | 41 | /* Begin PBXFrameworksBuildPhase section */ 42 | B2C6899021C99938000031AB /* Frameworks */ = { 43 | isa = PBXFrameworksBuildPhase; 44 | buildActionMask = 2147483647; 45 | files = ( 46 | B2C689B021C99CC0000031AB /* SimplePagedViewFramework.framework in Frameworks */, 47 | ); 48 | runOnlyForDeploymentPostprocessing = 0; 49 | }; 50 | /* End PBXFrameworksBuildPhase section */ 51 | 52 | /* Begin PBXGroup section */ 53 | B2C6898A21C99938000031AB = { 54 | isa = PBXGroup; 55 | children = ( 56 | B2C6899521C99938000031AB /* SimplePagedViewExample */, 57 | B2C6899421C99938000031AB /* Products */, 58 | B2C689AE21C99CC0000031AB /* Frameworks */, 59 | ); 60 | sourceTree = ""; 61 | }; 62 | B2C6899421C99938000031AB /* Products */ = { 63 | isa = PBXGroup; 64 | children = ( 65 | B2C6899321C99938000031AB /* SimplePagedViewExample.app */, 66 | ); 67 | name = Products; 68 | sourceTree = ""; 69 | }; 70 | B2C6899521C99938000031AB /* SimplePagedViewExample */ = { 71 | isa = PBXGroup; 72 | children = ( 73 | B2C6899621C99938000031AB /* AppDelegate.swift */, 74 | B2C6899821C99938000031AB /* ViewController.swift */, 75 | B2C6899D21C9993A000031AB /* Assets.xcassets */, 76 | B2C6899F21C9993B000031AB /* LaunchScreen.storyboard */, 77 | B2C689A221C9993B000031AB /* Info.plist */, 78 | ); 79 | path = SimplePagedViewExample; 80 | sourceTree = ""; 81 | }; 82 | B2C689AE21C99CC0000031AB /* Frameworks */ = { 83 | isa = PBXGroup; 84 | children = ( 85 | B2C689AF21C99CC0000031AB /* SimplePagedViewFramework.framework */, 86 | ); 87 | name = Frameworks; 88 | sourceTree = ""; 89 | }; 90 | /* End PBXGroup section */ 91 | 92 | /* Begin PBXNativeTarget section */ 93 | B2C6899221C99938000031AB /* SimplePagedViewExample */ = { 94 | isa = PBXNativeTarget; 95 | buildConfigurationList = B2C689A521C9993B000031AB /* Build configuration list for PBXNativeTarget "SimplePagedViewExample" */; 96 | buildPhases = ( 97 | B2C6898F21C99938000031AB /* Sources */, 98 | B2C6899021C99938000031AB /* Frameworks */, 99 | B2C6899121C99938000031AB /* Resources */, 100 | 24E7CF0221FD03ED009E6E79 /* CopyFiles */, 101 | ); 102 | buildRules = ( 103 | ); 104 | dependencies = ( 105 | ); 106 | name = SimplePagedViewExample; 107 | productName = SimplePagedViewExample; 108 | productReference = B2C6899321C99938000031AB /* SimplePagedViewExample.app */; 109 | productType = "com.apple.product-type.application"; 110 | }; 111 | /* End PBXNativeTarget section */ 112 | 113 | /* Begin PBXProject section */ 114 | B2C6898B21C99938000031AB /* Project object */ = { 115 | isa = PBXProject; 116 | attributes = { 117 | LastSwiftUpdateCheck = 1010; 118 | LastUpgradeCheck = 1010; 119 | ORGANIZATIONNAME = twof; 120 | TargetAttributes = { 121 | B2C6899221C99938000031AB = { 122 | CreatedOnToolsVersion = 10.1; 123 | }; 124 | }; 125 | }; 126 | buildConfigurationList = B2C6898E21C99938000031AB /* Build configuration list for PBXProject "SimplePagedViewExample" */; 127 | compatibilityVersion = "Xcode 9.3"; 128 | developmentRegion = en; 129 | hasScannedForEncodings = 0; 130 | knownRegions = ( 131 | en, 132 | Base, 133 | ); 134 | mainGroup = B2C6898A21C99938000031AB; 135 | productRefGroup = B2C6899421C99938000031AB /* Products */; 136 | projectDirPath = ""; 137 | projectRoot = ""; 138 | targets = ( 139 | B2C6899221C99938000031AB /* SimplePagedViewExample */, 140 | ); 141 | }; 142 | /* End PBXProject section */ 143 | 144 | /* Begin PBXResourcesBuildPhase section */ 145 | B2C6899121C99938000031AB /* Resources */ = { 146 | isa = PBXResourcesBuildPhase; 147 | buildActionMask = 2147483647; 148 | files = ( 149 | B2C689A121C9993B000031AB /* LaunchScreen.storyboard in Resources */, 150 | B2C6899E21C9993A000031AB /* Assets.xcassets in Resources */, 151 | ); 152 | runOnlyForDeploymentPostprocessing = 0; 153 | }; 154 | /* End PBXResourcesBuildPhase section */ 155 | 156 | /* Begin PBXSourcesBuildPhase section */ 157 | B2C6898F21C99938000031AB /* Sources */ = { 158 | isa = PBXSourcesBuildPhase; 159 | buildActionMask = 2147483647; 160 | files = ( 161 | B2C6899921C99938000031AB /* ViewController.swift in Sources */, 162 | B2C6899721C99938000031AB /* AppDelegate.swift in Sources */, 163 | ); 164 | runOnlyForDeploymentPostprocessing = 0; 165 | }; 166 | /* End PBXSourcesBuildPhase section */ 167 | 168 | /* Begin PBXVariantGroup section */ 169 | B2C6899F21C9993B000031AB /* LaunchScreen.storyboard */ = { 170 | isa = PBXVariantGroup; 171 | children = ( 172 | B2C689A021C9993B000031AB /* Base */, 173 | ); 174 | name = LaunchScreen.storyboard; 175 | sourceTree = ""; 176 | }; 177 | /* End PBXVariantGroup section */ 178 | 179 | /* Begin XCBuildConfiguration section */ 180 | B2C689A321C9993B000031AB /* Debug */ = { 181 | isa = XCBuildConfiguration; 182 | buildSettings = { 183 | ALWAYS_SEARCH_USER_PATHS = NO; 184 | CLANG_ANALYZER_NONNULL = YES; 185 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 186 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 187 | CLANG_CXX_LIBRARY = "libc++"; 188 | CLANG_ENABLE_MODULES = YES; 189 | CLANG_ENABLE_OBJC_ARC = YES; 190 | CLANG_ENABLE_OBJC_WEAK = YES; 191 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 192 | CLANG_WARN_BOOL_CONVERSION = YES; 193 | CLANG_WARN_COMMA = YES; 194 | CLANG_WARN_CONSTANT_CONVERSION = YES; 195 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 196 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 197 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 198 | CLANG_WARN_EMPTY_BODY = YES; 199 | CLANG_WARN_ENUM_CONVERSION = YES; 200 | CLANG_WARN_INFINITE_RECURSION = YES; 201 | CLANG_WARN_INT_CONVERSION = YES; 202 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 203 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 204 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 205 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 206 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 207 | CLANG_WARN_STRICT_PROTOTYPES = YES; 208 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 209 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 210 | CLANG_WARN_UNREACHABLE_CODE = YES; 211 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 212 | CODE_SIGN_IDENTITY = "iPhone Developer"; 213 | COPY_PHASE_STRIP = NO; 214 | DEBUG_INFORMATION_FORMAT = dwarf; 215 | ENABLE_STRICT_OBJC_MSGSEND = YES; 216 | ENABLE_TESTABILITY = YES; 217 | GCC_C_LANGUAGE_STANDARD = gnu11; 218 | GCC_DYNAMIC_NO_PIC = NO; 219 | GCC_NO_COMMON_BLOCKS = YES; 220 | GCC_OPTIMIZATION_LEVEL = 0; 221 | GCC_PREPROCESSOR_DEFINITIONS = ( 222 | "DEBUG=1", 223 | "$(inherited)", 224 | ); 225 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 226 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 227 | GCC_WARN_UNDECLARED_SELECTOR = YES; 228 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 229 | GCC_WARN_UNUSED_FUNCTION = YES; 230 | GCC_WARN_UNUSED_VARIABLE = YES; 231 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 232 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 233 | MTL_FAST_MATH = YES; 234 | ONLY_ACTIVE_ARCH = YES; 235 | SDKROOT = iphoneos; 236 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 237 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 238 | }; 239 | name = Debug; 240 | }; 241 | B2C689A421C9993B000031AB /* Release */ = { 242 | isa = XCBuildConfiguration; 243 | buildSettings = { 244 | ALWAYS_SEARCH_USER_PATHS = NO; 245 | CLANG_ANALYZER_NONNULL = YES; 246 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 247 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 248 | CLANG_CXX_LIBRARY = "libc++"; 249 | CLANG_ENABLE_MODULES = YES; 250 | CLANG_ENABLE_OBJC_ARC = YES; 251 | CLANG_ENABLE_OBJC_WEAK = YES; 252 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 253 | CLANG_WARN_BOOL_CONVERSION = YES; 254 | CLANG_WARN_COMMA = YES; 255 | CLANG_WARN_CONSTANT_CONVERSION = YES; 256 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 257 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 258 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 259 | CLANG_WARN_EMPTY_BODY = YES; 260 | CLANG_WARN_ENUM_CONVERSION = YES; 261 | CLANG_WARN_INFINITE_RECURSION = YES; 262 | CLANG_WARN_INT_CONVERSION = YES; 263 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 264 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 265 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 266 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 267 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 268 | CLANG_WARN_STRICT_PROTOTYPES = YES; 269 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 270 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 271 | CLANG_WARN_UNREACHABLE_CODE = YES; 272 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 273 | CODE_SIGN_IDENTITY = "iPhone Developer"; 274 | COPY_PHASE_STRIP = NO; 275 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 276 | ENABLE_NS_ASSERTIONS = NO; 277 | ENABLE_STRICT_OBJC_MSGSEND = YES; 278 | GCC_C_LANGUAGE_STANDARD = gnu11; 279 | GCC_NO_COMMON_BLOCKS = YES; 280 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 281 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 282 | GCC_WARN_UNDECLARED_SELECTOR = YES; 283 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 284 | GCC_WARN_UNUSED_FUNCTION = YES; 285 | GCC_WARN_UNUSED_VARIABLE = YES; 286 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 287 | MTL_ENABLE_DEBUG_INFO = NO; 288 | MTL_FAST_MATH = YES; 289 | SDKROOT = iphoneos; 290 | SWIFT_COMPILATION_MODE = wholemodule; 291 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 292 | VALIDATE_PRODUCT = YES; 293 | }; 294 | name = Release; 295 | }; 296 | B2C689A621C9993B000031AB /* Debug */ = { 297 | isa = XCBuildConfiguration; 298 | buildSettings = { 299 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 300 | CODE_SIGN_STYLE = Automatic; 301 | DEVELOPMENT_TEAM = P2PP2EM79F; 302 | INFOPLIST_FILE = SimplePagedViewExample/Info.plist; 303 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 304 | LD_RUNPATH_SEARCH_PATHS = ( 305 | "$(inherited)", 306 | "@executable_path/Frameworks", 307 | ); 308 | PRODUCT_BUNDLE_IDENTIFIER = com.twof.SimplePagedViewExample; 309 | PRODUCT_NAME = "$(TARGET_NAME)"; 310 | SWIFT_VERSION = 4.2; 311 | TARGETED_DEVICE_FAMILY = "1,2"; 312 | }; 313 | name = Debug; 314 | }; 315 | B2C689A721C9993B000031AB /* Release */ = { 316 | isa = XCBuildConfiguration; 317 | buildSettings = { 318 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 319 | CODE_SIGN_STYLE = Automatic; 320 | DEVELOPMENT_TEAM = P2PP2EM79F; 321 | INFOPLIST_FILE = SimplePagedViewExample/Info.plist; 322 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 323 | LD_RUNPATH_SEARCH_PATHS = ( 324 | "$(inherited)", 325 | "@executable_path/Frameworks", 326 | ); 327 | PRODUCT_BUNDLE_IDENTIFIER = com.twof.SimplePagedViewExample; 328 | PRODUCT_NAME = "$(TARGET_NAME)"; 329 | SWIFT_VERSION = 4.2; 330 | TARGETED_DEVICE_FAMILY = "1,2"; 331 | }; 332 | name = Release; 333 | }; 334 | /* End XCBuildConfiguration section */ 335 | 336 | /* Begin XCConfigurationList section */ 337 | B2C6898E21C99938000031AB /* Build configuration list for PBXProject "SimplePagedViewExample" */ = { 338 | isa = XCConfigurationList; 339 | buildConfigurations = ( 340 | B2C689A321C9993B000031AB /* Debug */, 341 | B2C689A421C9993B000031AB /* Release */, 342 | ); 343 | defaultConfigurationIsVisible = 0; 344 | defaultConfigurationName = Release; 345 | }; 346 | B2C689A521C9993B000031AB /* Build configuration list for PBXNativeTarget "SimplePagedViewExample" */ = { 347 | isa = XCConfigurationList; 348 | buildConfigurations = ( 349 | B2C689A621C9993B000031AB /* Debug */, 350 | B2C689A721C9993B000031AB /* Release */, 351 | ); 352 | defaultConfigurationIsVisible = 0; 353 | defaultConfigurationName = Release; 354 | }; 355 | /* End XCConfigurationList section */ 356 | }; 357 | rootObject = B2C6898B21C99938000031AB /* Project object */; 358 | } 359 | -------------------------------------------------------------------------------- /SimplePagedViewFramework/Example/SimplePagedViewExample/SimplePagedViewExample/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // SimplePagedViewExample 4 | // 5 | // Created by New User on 12/18/18. 6 | // Copyright © 2018 twof. 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: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 18 | let frame = UIScreen.main.bounds 19 | window = UIWindow(frame: frame) 20 | 21 | let initialViewController = ViewController() 22 | 23 | window!.rootViewController = initialViewController 24 | window!.makeKeyAndVisible() 25 | 26 | return true 27 | } 28 | 29 | func applicationWillResignActive(_ application: UIApplication) { 30 | // 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. 31 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 32 | } 33 | 34 | func applicationDidEnterBackground(_ application: UIApplication) { 35 | // 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. 36 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 37 | } 38 | 39 | func applicationWillEnterForeground(_ application: UIApplication) { 40 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 41 | } 42 | 43 | func applicationDidBecomeActive(_ application: UIApplication) { 44 | // 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. 45 | } 46 | 47 | func applicationWillTerminate(_ application: UIApplication) { 48 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 49 | } 50 | 51 | 52 | } 53 | 54 | -------------------------------------------------------------------------------- /SimplePagedViewFramework/Example/SimplePagedViewExample/SimplePagedViewExample/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /SimplePagedViewFramework/Example/SimplePagedViewExample/SimplePagedViewExample/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /SimplePagedViewFramework/Example/SimplePagedViewExample/SimplePagedViewExample/Assets.xcassets/add.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "add.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | }, 12 | "properties" : { 13 | "template-rendering-intent" : "template" 14 | } 15 | } -------------------------------------------------------------------------------- /SimplePagedViewFramework/Example/SimplePagedViewExample/SimplePagedViewExample/Assets.xcassets/add.imageset/add.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redbooth/SimplePagedView/57a75ddf833b2b04b43d23421821a705dc60d370/SimplePagedViewFramework/Example/SimplePagedViewExample/SimplePagedViewExample/Assets.xcassets/add.imageset/add.pdf -------------------------------------------------------------------------------- /SimplePagedViewFramework/Example/SimplePagedViewExample/SimplePagedViewExample/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /SimplePagedViewFramework/Example/SimplePagedViewExample/SimplePagedViewExample/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIRequiredDeviceCapabilities 26 | 27 | armv7 28 | 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /SimplePagedViewFramework/Example/SimplePagedViewExample/SimplePagedViewExample/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // SimplePagedViewExample 4 | // 5 | // Created by New User on 12/18/18. 6 | // Copyright © 2018 twof. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import SimplePagedViewFramework 11 | 12 | class ViewController: UIViewController { 13 | 14 | override func viewDidLoad() { 15 | super.viewDidLoad() 16 | // Do any additional setup after loading the view, typically from a nib. 17 | let green = UIView() 18 | green.backgroundColor = .green 19 | 20 | let red = UIView() 21 | red.backgroundColor = .red 22 | 23 | let orange = UIView() 24 | orange.backgroundColor = .orange 25 | 26 | let pagedView = SimplePagedView( 27 | indicatorColor: .purple, 28 | initialPage: 1, 29 | dotSize: 20, 30 | imageIndices: [-1: #imageLiteral(resourceName: "add")], 31 | with: green, red, orange 32 | ) 33 | pagedView.pageIndicatorIsInteractive = true 34 | pagedView.translatesAutoresizingMaskIntoConstraints = false 35 | 36 | self.view.addSubview(pagedView) 37 | 38 | NSLayoutConstraint.activate([ 39 | pagedView.topAnchor.constraint(equalTo: view.topAnchor), 40 | pagedView.bottomAnchor.constraint(equalTo: view.bottomAnchor), 41 | pagedView.leadingAnchor.constraint(equalTo: view.leadingAnchor), 42 | pagedView.trailingAnchor.constraint(equalTo: view.trailingAnchor) 43 | ]) 44 | } 45 | } 46 | 47 | -------------------------------------------------------------------------------- /SimplePagedViewFramework/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | 22 | 23 | -------------------------------------------------------------------------------- /SimplePagedViewFramework/Source/Errors/DotsError.swift: -------------------------------------------------------------------------------- 1 | public extension PageDotsView { 2 | enum DotsError: Error { 3 | case outOfBounds 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /SimplePagedViewFramework/Source/Extensions/NSLayoutConstraint.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | public extension NSLayoutConstraint { 4 | 5 | /// Convenience method that activates each constraint in the list of arrays, in the same manner as setting active=true. This is often more efficient than activating each constraint individually. 6 | /// 7 | /// - Parameter constraintsList: Set of typically related constraints 8 | @available(iOS 8.0, *) 9 | class func activate(_ constraintsList: [NSLayoutConstraint]...) { 10 | let constraints = Array(constraintsList.joined()) 11 | NSLayoutConstraint.activate(constraints) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /SimplePagedViewFramework/Source/Extensions/UIImage.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import UIKit 3 | 4 | public extension UIImage { 5 | 6 | /// Creates a tinted copy of a template asset 7 | /// 8 | /// - Parameter color: The color to set the image to 9 | /// - Returns: A tinted copy of self 10 | func tint(with color: UIColor) -> UIImage { 11 | guard let cgImage = cgImage else { 12 | return self 13 | } 14 | UIGraphicsBeginImageContextWithOptions(size, false, scale) 15 | guard let context = UIGraphicsGetCurrentContext() else { 16 | UIGraphicsEndImageContext() 17 | return self 18 | } 19 | color.setFill() 20 | context.translateBy(x: 0, y: size.height) 21 | context.scaleBy(x: 1.0, y: -1.0) 22 | context.setBlendMode(.normal) 23 | 24 | let rect = CGRect(origin: .zero, size: size) 25 | context.clip(to: rect, mask: cgImage) 26 | context.fill(rect) 27 | 28 | let result = UIGraphicsGetImageFromCurrentImageContext() ?? self 29 | UIGraphicsEndImageContext() 30 | return result 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /SimplePagedViewFramework/Source/Extensions/UIView.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | extension UIView { 4 | public func replace( 5 | subview: UIView, 6 | with other: UIView, 7 | constraints: (_ child: UIView, _ parent: T) -> [NSLayoutConstraint] 8 | ) { 9 | let newConstraints = constraints(other, self as! T) 10 | guard let subviewIndex = subview.superview?.subviews.firstIndex(of: subview) else { fatalError() } 11 | subview.removeFromSuperview() 12 | self.insertSubview(other, at: subviewIndex) 13 | 14 | NSLayoutConstraint.activate(newConstraints) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /SimplePagedViewFramework/Source/Extensions/UIViewController.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | public extension UIViewController { 4 | /// Adds a child ViewController 5 | public func add(_ child: UIViewController) { 6 | addChild(child) 7 | view.addSubview(child.view) 8 | child.didMove(toParent: self) 9 | } 10 | 11 | /// Adds a subViewController and constraints to self 12 | public func add( 13 | _ childViewController: UIViewController, 14 | constraints: (UIView) -> [NSLayoutConstraint] 15 | ) { 16 | addChild(childViewController) 17 | view.addSubview(childViewController.view) 18 | childViewController.view.translatesAutoresizingMaskIntoConstraints = false 19 | childViewController.didMove(toParent: self) 20 | NSLayoutConstraint.activate(constraints(childViewController.view)) 21 | } 22 | 23 | /// Removes a child ViewController 24 | public func removeFromParent() { 25 | guard parent != nil else { return } 26 | 27 | willMove(toParent: nil) 28 | removeFromParent() 29 | view.removeFromSuperview() 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /SimplePagedViewFramework/Source/SimplePagedView.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | public class SimplePagedView: UIView { 4 | // MARK: - Properties 5 | public static func defaultPageControlConstraints(dotsView: UIView, pagedViewController: SimplePagedView) -> ([NSLayoutConstraint]) { 6 | return [ 7 | dotsView.bottomAnchor.constraint(equalTo: pagedViewController.scrollView.bottomAnchor), 8 | dotsView.centerXAnchor.constraint( 9 | equalTo: pagedViewController.centerXAnchor 10 | ), 11 | dotsView.leadingAnchor.constraint(equalTo: pagedViewController.leadingAnchor), 12 | dotsView.trailingAnchor.constraint(equalTo: pagedViewController.trailingAnchor), 13 | dotsView.heightAnchor.constraint(equalToConstant: 44) 14 | ] 15 | } 16 | 17 | fileprivate enum Constants { 18 | static let startingPage = 0 19 | static let pageControllerSpacing: CGFloat = -10 20 | } 21 | 22 | fileprivate var scrollContentView: UIView = { 23 | var scrollingView = UIView() 24 | scrollingView.translatesAutoresizingMaskIntoConstraints = false 25 | return scrollingView 26 | }() 27 | fileprivate var innerPages: [UIView]! 28 | fileprivate var pageControlGestureView: UIView = { 29 | let view = UIView(frame: .zero) 30 | view.translatesAutoresizingMaskIntoConstraints = false 31 | view.accessibilityIdentifier = "DotGestureView" 32 | view.isUserInteractionEnabled = true 33 | 34 | return view 35 | }() 36 | 37 | fileprivate let pageControlConstraints: (UIView, SimplePagedView) -> ([NSLayoutConstraint]) 38 | 39 | fileprivate let initialPage: Int 40 | fileprivate var didScrollToInitialPage = false 41 | fileprivate let dotSize: CGFloat 42 | fileprivate var lastContentOffset: CGFloat = 0 43 | 44 | public var currentPage: Int { 45 | return pageControl.currentDot 46 | } 47 | 48 | /// Can be defined in order to trigger an action when pages are switched. Pages are 0 indexed. 49 | public var didSwitchPages: ((Int) -> Void)? 50 | /// Can be set to allow or disallow user interaction with the page dot indicators. Defaults to false. 51 | public var pageIndicatorIsInteractive: Bool = false { 52 | didSet { 53 | self.setupGestures(pageControlGestureHandler: self.pageControlGestureView) 54 | } 55 | } 56 | /// The last dot can in the page indicator can be replaced with an image by setting this property 57 | public var lastPageIndicator: UIImageView? 58 | /// Executes whenever scrolling ends 59 | public var didFinishScrolling: ((_ pageNumber: Int) -> Void)? 60 | 61 | public var isScrolling = false { 62 | didSet { 63 | if !isScrolling { 64 | self.didFinishScrolling?(currentPage) 65 | } 66 | } 67 | } 68 | 69 | public var scrollView: UIScrollView = { 70 | var scrollView = UIScrollView() 71 | scrollView.translatesAutoresizingMaskIntoConstraints = false 72 | scrollView.isPagingEnabled = true 73 | scrollView.showsHorizontalScrollIndicator = false 74 | scrollView.showsVerticalScrollIndicator = false 75 | scrollView.bounces = false 76 | scrollView.alwaysBounceHorizontal = false 77 | return scrollView 78 | }() 79 | fileprivate var pageControl: PageDotsView = { 80 | var pageControl = PageDotsView(count: 0, frame: .zero) 81 | pageControl.translatesAutoresizingMaskIntoConstraints = false 82 | return pageControl 83 | }() 84 | 85 | public init( 86 | indicatorColor: UIColor = .red, 87 | initialPage: Int = 0, 88 | dotSize: CGFloat = 7, 89 | imageIndices: [Int: UIImage] = [:], 90 | pageControlConstraints: @escaping (UIView, SimplePagedView) -> ([NSLayoutConstraint]) 91 | = SimplePagedView.defaultPageControlConstraints, 92 | with views: UIView... 93 | ) { 94 | self.pageControlConstraints = pageControlConstraints 95 | self.initialPage = initialPage 96 | self.dotSize = dotSize 97 | super.init(frame: .zero) 98 | self.innerPages = setupInnerPages(for: views) 99 | 100 | self.pageControl = setupPageDotsView( 101 | numberOfDots: self.innerPages.count, 102 | color: .gray, 103 | currentColor: indicatorColor, 104 | dotSize: dotSize, 105 | currentDot: initialPage, 106 | imageIndices: imageIndices 107 | ) 108 | 109 | self.scrollView.delegate = self 110 | 111 | self.setupSubviews() 112 | self.setupConstraints() 113 | 114 | self.didSwitchPages?(0) 115 | } 116 | 117 | public init( 118 | indicatorColor: UIColor = .red, 119 | initialPage: Int = 0, 120 | dotSize: CGFloat = 7, 121 | imageIndices: [Int: UIImage] = [:], 122 | pageControlConstraints: @escaping (UIView, SimplePagedView) -> ([NSLayoutConstraint]) 123 | = SimplePagedView.defaultPageControlConstraints, 124 | with views: [UIView] 125 | ) { 126 | self.pageControlConstraints = pageControlConstraints 127 | self.initialPage = initialPage 128 | self.dotSize = dotSize 129 | super.init(frame: .zero) 130 | self.innerPages = setupInnerPages(for: views) 131 | 132 | self.pageControl = setupPageDotsView( 133 | numberOfDots: self.innerPages.count, 134 | color: .gray, 135 | currentColor: indicatorColor, 136 | dotSize: dotSize, 137 | currentDot: initialPage, 138 | imageIndices: imageIndices 139 | ) 140 | 141 | self.scrollView.delegate = self 142 | 143 | self.setupSubviews() 144 | self.setupConstraints() 145 | 146 | self.didSwitchPages?(0) 147 | 148 | self.isUserInteractionEnabled = true 149 | } 150 | 151 | required init?(coder aDecoder: NSCoder) { 152 | fatalError("init(coder:) has not been implemented") 153 | } 154 | 155 | /// Scrolls to the given page 156 | /// 157 | /// - Parameters: 158 | /// - page: 0 indexed page number 159 | /// - animated: should the scrolling be animated 160 | public func scrollTo(page: Int, animated: Bool) { 161 | self.scrollView.setContentOffset( 162 | CGPoint(x: CGFloat(Int(scrollView.frame.size.width) * page), y: 0), 163 | animated: animated 164 | ) 165 | 166 | let newPageControl = try! pageControl.moveTo(index: page) 167 | 168 | self.replace(subview: self.pageControl, with: newPageControl, constraints: self.pageControlConstraints) 169 | self.pageControl = newPageControl 170 | } 171 | 172 | @objc func panned(sender: UIPanGestureRecognizer) { 173 | let cgNumberOfPages: CGFloat = CGFloat(self.innerPages.count) 174 | var page: Int = Int(floor(Double((sender.location(in: self).x/pageControl.frame.width) * cgNumberOfPages))) 175 | 176 | page = (page >= self.innerPages.count) 177 | ? self.innerPages.count - 1 178 | : (page < 0) 179 | ? 0 180 | : page 181 | 182 | scrollTo(page: page, animated: false) 183 | } 184 | 185 | public override func layoutSubviews() { 186 | super.layoutSubviews() 187 | 188 | if !didScrollToInitialPage { 189 | scrollTo(page: self.initialPage, animated: false) 190 | didScrollToInitialPage = true 191 | } 192 | } 193 | } 194 | 195 | // MARK: - View Setup 196 | fileprivate extension SimplePagedView { 197 | 198 | func setupInnerPages(for views: [UIView]) -> [UIView] { 199 | if views.count == 0 { 200 | let view = UIView() 201 | view.translatesAutoresizingMaskIntoConstraints = false 202 | view.backgroundColor = .white 203 | return [view] 204 | } 205 | 206 | return views.map { $0.translatesAutoresizingMaskIntoConstraints = false; return $0 } 207 | } 208 | 209 | func setupGestures(pageControlGestureHandler: UIView) { 210 | if pageIndicatorIsInteractive { 211 | let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.panned(sender:))) 212 | 213 | panGestureRecognizer.maximumNumberOfTouches = 1 214 | panGestureRecognizer.minimumNumberOfTouches = 1 215 | 216 | pageControlGestureHandler.addGestureRecognizer(panGestureRecognizer) 217 | } else { 218 | pageControlGestureHandler.gestureRecognizers = nil 219 | } 220 | } 221 | 222 | func setupSubviews() { 223 | self.addSubview(scrollView) 224 | self.scrollView.addSubview(scrollContentView) 225 | 226 | for page in innerPages { 227 | scrollContentView.addSubview(page) 228 | } 229 | 230 | self.addSubview(pageControl) 231 | self.addSubview(pageControlGestureView) 232 | } 233 | 234 | // swiftlint:disable next function_body_length 235 | func setupConstraints() { 236 | let scrollViewConstraints = [ 237 | scrollView.topAnchor.constraint(equalTo: topAnchor), 238 | scrollView.leadingAnchor.constraint(equalTo: leadingAnchor), 239 | scrollView.trailingAnchor.constraint(equalTo: trailingAnchor), 240 | scrollView.bottomAnchor.constraint(equalTo: bottomAnchor) 241 | ] 242 | 243 | let innerViewConstraints = [ 244 | scrollContentView.centerYAnchor.constraint(equalTo: scrollView.centerYAnchor), 245 | scrollContentView.heightAnchor.constraint(equalTo: heightAnchor), 246 | scrollContentView.widthAnchor.constraint(equalTo: widthAnchor, multiplier: CGFloat(innerPages.count)), 247 | scrollContentView.topAnchor.constraint(equalTo: scrollView.topAnchor), 248 | scrollContentView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor), 249 | scrollContentView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor), 250 | scrollContentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor) 251 | ] 252 | 253 | let pageConstraints: [NSLayoutConstraint] = { 254 | var widthConstraints: [NSLayoutConstraint] = [] 255 | var heightConstraints: [NSLayoutConstraint] = [] 256 | var leadingEdgeConstraints: [NSLayoutConstraint] = [] 257 | var topConstraints: [NSLayoutConstraint] = [] 258 | var bottomConstraints: [NSLayoutConstraint] = [] 259 | 260 | for page in innerPages { 261 | widthConstraints.append(page.widthAnchor.constraint(equalTo: widthAnchor)) 262 | heightConstraints.append(page.heightAnchor.constraint(equalTo: heightAnchor)) 263 | } 264 | 265 | leadingEdgeConstraints.append(innerPages[0].leadingAnchor.constraint(equalTo: scrollView.leadingAnchor)) 266 | 267 | for index in 1.. PageDotsView { 305 | let view = PageDotsView( 306 | count: numberOfDots, 307 | dotColor: color, 308 | currentDotColor: currentColor, 309 | dotSize: dotSize, 310 | currentDot: currentDot, 311 | imageIndices: imageIndices, 312 | frame: .zero 313 | ) 314 | 315 | view.frame = CGRect(x: 0, y: 0, width: view.intrinsicContentSize.width, height: view.intrinsicContentSize.height) 316 | 317 | return view 318 | } 319 | } 320 | 321 | // MARK: - UIScrollViewDelegate Methods 322 | extension SimplePagedView: UIScrollViewDelegate { 323 | public func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { 324 | isScrolling = true 325 | } 326 | 327 | public func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) { 328 | if !decelerate { scrollViewDidEndScrolling(scrollView) } 329 | } 330 | 331 | public func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) { 332 | scrollViewDidEndScrolling(scrollView) 333 | } 334 | 335 | public func scrollViewDidEndScrolling(_ scrollView: UIScrollView) { 336 | isScrolling = false 337 | } 338 | 339 | public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { 340 | let page = Int(scrollView.contentOffset.x / scrollView.frame.size.width) 341 | let newPageControl = try! self.pageControl.moveTo(index: page) 342 | 343 | self.replace(subview: self.pageControl, with: newPageControl, constraints: self.pageControlConstraints) 344 | self.pageControl = newPageControl 345 | 346 | self.didSwitchPages?(page) 347 | 348 | scrollViewDidEndScrolling(scrollView) 349 | } 350 | } 351 | 352 | extension SimplePagedView { 353 | /// Gestures won't be recognized on subviews that are outside the bounds of a view 354 | /// This subclass and override remedies that. 355 | /// We're using it because there are situations where we want the page 356 | /// indicator to be outside the page view 357 | override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { 358 | guard !clipsToBounds && !isHidden && alpha > 0 else { 359 | return nil 360 | } 361 | for member in subviews.reversed() { 362 | let subPoint = member.convert(point, from: self) 363 | guard let result = member.hitTest(subPoint, with: event) else { continue } 364 | return result 365 | } 366 | return nil 367 | } 368 | } 369 | -------------------------------------------------------------------------------- /SimplePagedViewFramework/Source/Views/DotView.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | class DotView: UIControl { 4 | let mainColor: UIColor 5 | 6 | init(frame: CGRect, mainColor: UIColor = .black) { 7 | self.mainColor = mainColor 8 | super.init(frame: frame) 9 | self.translatesAutoresizingMaskIntoConstraints = false 10 | } 11 | 12 | required init?(coder aDecoder: NSCoder) { 13 | fatalError("init(coder:) has not been implemented") 14 | } 15 | 16 | override func draw(_ rect: CGRect) { 17 | let dotPath = UIBezierPath(ovalIn: rect) 18 | let shapeLayer = CAShapeLayer() 19 | shapeLayer.path = dotPath.cgPath 20 | shapeLayer.fillColor = mainColor.cgColor 21 | layer.addSublayer(shapeLayer) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SimplePagedViewFramework/Source/Views/PageDotsView.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | public class PageDotsView: UIView { 4 | let currentDot: Int 5 | 6 | private var dots: [UIView] = [] 7 | private var dotCount: Int 8 | private let dotSize: CGFloat 9 | private let dotColor: UIColor 10 | private let currentDotColor: UIColor 11 | private let imageIndices: [Int: UIImage] 12 | 13 | private let dotContainer: UIView = { 14 | let view = UIView(frame: .zero) 15 | view.translatesAutoresizingMaskIntoConstraints = false 16 | view.accessibilityIdentifier = "DotContainer" 17 | 18 | return view 19 | }() 20 | 21 | public init( 22 | count: Int, 23 | dotColor: UIColor = .gray, 24 | currentDotColor: UIColor = .red, 25 | dotSize: CGFloat = 7, 26 | currentDot: Int = 0, 27 | imageIndices: [Int: UIImage]=[:], 28 | frame: CGRect 29 | ) { 30 | self.dotCount = count 31 | self.dotSize = dotSize 32 | self.currentDot = currentDot 33 | self.dotColor = dotColor 34 | self.currentDotColor = currentDotColor 35 | self.imageIndices = imageIndices 36 | 37 | super.init(frame: frame) 38 | 39 | self.translatesAutoresizingMaskIntoConstraints = false 40 | self.accessibilityIdentifier = "PageDotsView" 41 | 42 | self.dots = setupViews( 43 | count: count, 44 | dotColor: dotColor, 45 | currentDotColor: currentDotColor, 46 | dotSize: dotSize, 47 | imageIndices: imageIndices 48 | ) 49 | setupConstraints(dotSize: dotSize) 50 | } 51 | 52 | required init?(coder aDecoder: NSCoder) { 53 | fatalError("init(coder:) has not been implemented") 54 | } 55 | 56 | public func shiftRight() throws -> PageDotsView { 57 | guard currentDot < dots.count - 1 else { throw DotsError.outOfBounds } 58 | return PageDotsView( 59 | count: self.dotCount, 60 | dotColor: self.dotColor, 61 | currentDotColor: self.currentDotColor, 62 | dotSize: self.dotSize, 63 | currentDot: self.currentDot + 1, 64 | imageIndices: self.imageIndices, 65 | frame: self.frame 66 | ) 67 | } 68 | 69 | public func shiftLeft() throws -> PageDotsView { 70 | guard currentDot > 0 else { throw DotsError.outOfBounds } 71 | return PageDotsView( 72 | count: self.dotCount, 73 | dotColor: self.dotColor, 74 | currentDotColor: self.currentDotColor, 75 | dotSize: self.dotSize, 76 | currentDot: self.currentDot - 1, 77 | imageIndices: self.imageIndices, 78 | frame: self.frame 79 | ) 80 | } 81 | 82 | public func moveTo(index: Int) throws -> PageDotsView { 83 | guard index < self.dotCount, index >= 0 else { throw DotsError.outOfBounds } 84 | return PageDotsView( 85 | count: self.dotCount, 86 | dotColor: self.dotColor, 87 | currentDotColor: self.currentDotColor, 88 | dotSize: self.dotSize, 89 | currentDot: index, 90 | imageIndices: self.imageIndices, 91 | frame: self.frame 92 | ) 93 | } 94 | 95 | override public var intrinsicContentSize: CGSize { 96 | let width = Double(dots.count * (Int(dotSize) * 2) - Int(dotSize)) + 4 97 | let height = Double(dotSize) * 1.50 98 | return CGSize(width: width, height: height) 99 | } 100 | } 101 | 102 | private extension PageDotsView { 103 | func setupViews( 104 | count: Int, 105 | dotColor: UIColor, 106 | currentDotColor: UIColor, 107 | dotSize: CGFloat, 108 | imageIndices: [Int: UIImage] 109 | ) -> [UIView] { 110 | self.addSubview(dotContainer) 111 | 112 | let adjustedImageIndices = imageIndices.reduce(into: [Int: UIImage]()) { (result, keyValue) in 113 | result[keyValue.key < 0 ? count + keyValue.key : keyValue.key] = keyValue.value 114 | } 115 | 116 | return (0.. [NSLayoutConstraint] in 143 | var constraints = [ 144 | dot.heightAnchor.constraint(equalToConstant: dotSize), 145 | dot.widthAnchor.constraint(equalToConstant: dotSize), 146 | dot.centerYAnchor.constraint(equalTo: self.dotContainer.centerYAnchor) 147 | ] 148 | 149 | if let previousDot = previousDot { 150 | constraints.append(dot.leadingAnchor.constraint(equalTo: previousDot.trailingAnchor, constant: dotSize)) 151 | } else { 152 | constraints.append(dot.leadingAnchor.constraint(equalTo: dotContainer.leadingAnchor)) 153 | } 154 | 155 | previousDot = dot 156 | 157 | return constraints 158 | } 159 | 160 | NSLayoutConstraint.activate(dotConstraints) 161 | 162 | NSLayoutConstraint.activate([ 163 | dotContainer.widthAnchor.constraint(equalToConstant: self.intrinsicContentSize.width), 164 | dotContainer.heightAnchor.constraint(equalToConstant: self.intrinsicContentSize.height), 165 | dotContainer.centerXAnchor.constraint(equalTo: self.centerXAnchor), 166 | dotContainer.centerYAnchor.constraint(equalTo: self.centerYAnchor) 167 | ]) 168 | } 169 | 170 | func generateDot( 171 | index: Int, 172 | dotColor: UIColor, 173 | currentDotColor: UIColor, 174 | dotSize: CGFloat 175 | ) -> DotView { 176 | let frame = CGRect(x: 0, y: 0, width: dotSize, height: dotSize) 177 | let color = index == self.currentDot ? currentDotColor : dotColor 178 | let dot: DotView = DotView(frame: frame, mainColor: color) 179 | dot.backgroundColor = .clear 180 | 181 | dot.accessibilityIdentifier = "DotAt\(index)" 182 | 183 | return dot 184 | } 185 | 186 | func prepareImageDot( 187 | image: UIImage, 188 | index: Int, 189 | color: UIColor, 190 | currentColor: UIColor 191 | ) -> UIImageView { 192 | let imageColor = index == self.currentDot ? currentColor : color 193 | let tintedImage = image.tint(with: imageColor) 194 | 195 | let imageView = UIImageView(image: tintedImage) 196 | imageView.accessibilityIdentifier = "ImageAt\(index)" 197 | imageView.translatesAutoresizingMaskIntoConstraints = false 198 | 199 | return imageView 200 | } 201 | } 202 | -------------------------------------------------------------------------------- /SimplePagedViewFrameworkTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /SimplePagedViewFrameworkTests/SimplePagedViewFrameworkTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SimplePagedViewFrameworkTests.swift 3 | // SimplePagedViewFrameworkTests 4 | // 5 | // Created by New User on 12/12/18. 6 | // Copyright © 2018 twof. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import SimplePagedViewFramework 11 | 12 | class SimplePagedViewFrameworkTests: XCTestCase { 13 | 14 | override func setUp() { 15 | // Put setup code here. This method is called before the invocation of each test method in the class. 16 | } 17 | 18 | override func tearDown() { 19 | // Put teardown code here. This method is called after the invocation of each test method in the class. 20 | } 21 | 22 | func testExample() { 23 | // This is an example of a functional test case. 24 | // Use XCTAssert and related functions to verify your tests produce the correct results. 25 | } 26 | 27 | func testPerformanceExample() { 28 | // This is an example of a performance test case. 29 | self.measure { 30 | // Put the code you want to measure the time of here. 31 | } 32 | } 33 | 34 | } 35 | --------------------------------------------------------------------------------