├── .gitignore ├── ICETutorial.podspec ├── ICETutorial.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ ├── icepat-dev.xcuserdatad │ │ ├── UserInterfaceState.xcuserstate │ │ └── WorkspaceSettings.xcsettings │ │ ├── icepatdev.xcuserdatad │ │ └── UserInterfaceState.xcuserstate │ │ └── patrick.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ ├── icepat-dev.xcuserdatad │ ├── xcdebugger │ │ └── Breakpoints.xcbkptlist │ └── xcschemes │ │ ├── tutorial.xcscheme │ │ └── xcschememanagement.plist │ ├── icepatdev.xcuserdatad │ ├── xcdebugger │ │ └── Breakpoints.xcbkptlist │ └── xcschemes │ │ ├── ICETutorial.xcscheme │ │ └── xcschememanagement.plist │ └── patrick.xcuserdatad │ ├── xcdebugger │ └── Breakpoints.xcbkptlist │ └── xcschemes │ └── xcschememanagement.plist ├── ICETutorial ├── AppDelegate.h ├── AppDelegate.m ├── ICETutorial-Info.plist ├── ICETutorial-Prefix.pch ├── Libraries │ ├── ICETutorialController.h │ ├── ICETutorialController.m │ ├── ICETutorialPage.h │ ├── ICETutorialPage.m │ ├── ICETutorialStyle.h │ └── ICETutorialStyle.m ├── en.lproj │ └── InfoPlist.strings └── main.m ├── LICENSE ├── Podfile ├── README.md ├── Resources ├── Default-568h@2x.png ├── Default.png ├── Default@2x.png ├── background-gradient.png ├── background-gradient@2x.png ├── button-background.png ├── button-background@2x.png ├── tutorial_background_00@2x.jpg ├── tutorial_background_01@2x.jpg ├── tutorial_background_02@2x.jpg ├── tutorial_background_03@2x.jpg └── tutorial_background_04@2x.jpg └── screen_shot.jpg /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .DS_Store 3 | 4 | *.xccheckout 5 | 6 | *.xccheckout 7 | 8 | *.xcscheme 9 | 10 | *.xcbkptlist 11 | 12 | *.xcsettings 13 | 14 | *.xcuserstate 15 | 16 | ICETutorial.xcodeproj/xcuserdata/patrick.trillsam.xcuserdatad/xcschemes/xcschememanagement.plist 17 | 18 | ICETutorial.xcodeproj/xcuserdata/patrick.xcuserdatad/xcschemes/ICETutorial.xcscheme 19 | 20 | ICETutorial.xcodeproj/project.xcworkspace/xcshareddata/ICETutorial.xccheckout 21 | 22 | ICETutorial.xcodeproj/xcuserdata/patrick.xcuserdatad/xcschemes/ICETutorial.xcscheme 23 | 24 | ICETutorial.xcodeproj/project.xcworkspace/xcuserdata/patrick.xcuserdatad/WorkspaceSettings.xcsettings 25 | 26 | ICETutorial.xcodeproj/xcuserdata/patrick.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist 27 | 28 | ICETutorial.xcodeproj/xcuserdata/patrick.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist 29 | 30 | ICETutorial.xcodeproj/xcuserdata/patrick.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist 31 | -------------------------------------------------------------------------------- /ICETutorial.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'ICETutorial' 3 | s.version = '1.1.1' 4 | s.summary = 'An implementation of the in-app tutorial as seen e.g. in Path 3' 5 | s.homepage = 'http://icepat.github.io/ICETutorial' 6 | s.license = { 7 | :type => 'MIT', 8 | :file => 'README.md' 9 | } 10 | s.author = 'Patrick Trillsam' 11 | s.source = { 12 | :git => 'https://github.com/icepat/ICETutorial.git', 13 | :tag => '1.1.1' 14 | } 15 | s.platform = :ios, '6.0' 16 | s.source_files = 'ICETutorial/Libraries' 17 | s.public_header_files = 'ICETutorial/Libraries' 18 | s.frameworks = 'UIKit', 'CoreGraphics' 19 | s.requires_arc = true 20 | s.resources = ['Resources/*.png'] 21 | end 22 | -------------------------------------------------------------------------------- /ICETutorial.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 0C6833CE1747B7B8004F9123 /* ICETutorialController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C6833CD1747B7B8004F9123 /* ICETutorialController.m */; }; 11 | 0C6833D11747B831004F9123 /* ICETutorialPage.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C6833D01747B831004F9123 /* ICETutorialPage.m */; }; 12 | 80A29020171156F6004EA534 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 80A28FF6171156F6004EA534 /* AppDelegate.m */; }; 13 | 80A29041171156F6004EA534 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 80A2901B171156F6004EA534 /* main.m */; }; 14 | CD29BF131952C7B6005A5104 /* ICETutorialStyle.m in Sources */ = {isa = PBXBuildFile; fileRef = CD29BF121952C7B6005A5104 /* ICETutorialStyle.m */; }; 15 | CD6955F217C9120E0003ECA5 /* background-gradient.png in Resources */ = {isa = PBXBuildFile; fileRef = CD6955E617C9120E0003ECA5 /* background-gradient.png */; }; 16 | CD6955F317C9120E0003ECA5 /* background-gradient@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = CD6955E717C9120E0003ECA5 /* background-gradient@2x.png */; }; 17 | CD6955F417C9120E0003ECA5 /* button-background.png in Resources */ = {isa = PBXBuildFile; fileRef = CD6955E817C9120E0003ECA5 /* button-background.png */; }; 18 | CD6955F517C9120E0003ECA5 /* button-background@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = CD6955E917C9120E0003ECA5 /* button-background@2x.png */; }; 19 | CD6955F617C9120E0003ECA5 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = CD6955EA17C9120E0003ECA5 /* Default-568h@2x.png */; }; 20 | CD6955F717C9120E0003ECA5 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = CD6955EB17C9120E0003ECA5 /* Default.png */; }; 21 | CD6955F817C9120E0003ECA5 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = CD6955EC17C9120E0003ECA5 /* Default@2x.png */; }; 22 | CD6955F917C9120E0003ECA5 /* tutorial_background_00@2x.jpg in Resources */ = {isa = PBXBuildFile; fileRef = CD6955ED17C9120E0003ECA5 /* tutorial_background_00@2x.jpg */; }; 23 | CD6955FA17C9120E0003ECA5 /* tutorial_background_01@2x.jpg in Resources */ = {isa = PBXBuildFile; fileRef = CD6955EE17C9120E0003ECA5 /* tutorial_background_01@2x.jpg */; }; 24 | CD6955FB17C9120E0003ECA5 /* tutorial_background_02@2x.jpg in Resources */ = {isa = PBXBuildFile; fileRef = CD6955EF17C9120E0003ECA5 /* tutorial_background_02@2x.jpg */; }; 25 | CD6955FC17C9120E0003ECA5 /* tutorial_background_03@2x.jpg in Resources */ = {isa = PBXBuildFile; fileRef = CD6955F017C9120E0003ECA5 /* tutorial_background_03@2x.jpg */; }; 26 | CD6955FD17C9120E0003ECA5 /* tutorial_background_04@2x.jpg in Resources */ = {isa = PBXBuildFile; fileRef = CD6955F117C9120E0003ECA5 /* tutorial_background_04@2x.jpg */; }; 27 | CDAD68DE17C4CAB600737949 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 80A28FFD171156F6004EA534 /* InfoPlist.strings */; }; 28 | CDC0638B17006175004E4142 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CDC0638A17006175004E4142 /* UIKit.framework */; }; 29 | CDC0638D17006175004E4142 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CDC0638C17006175004E4142 /* Foundation.framework */; }; 30 | CDC0638F17006175004E4142 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CDC0638E17006175004E4142 /* CoreGraphics.framework */; }; 31 | /* End PBXBuildFile section */ 32 | 33 | /* Begin PBXFileReference section */ 34 | 0C6833CC1747B7B8004F9123 /* ICETutorialController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ICETutorialController.h; sourceTree = ""; }; 35 | 0C6833CD1747B7B8004F9123 /* ICETutorialController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ICETutorialController.m; sourceTree = ""; }; 36 | 0C6833CF1747B831004F9123 /* ICETutorialPage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ICETutorialPage.h; sourceTree = ""; }; 37 | 0C6833D01747B831004F9123 /* ICETutorialPage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ICETutorialPage.m; sourceTree = ""; }; 38 | 80A28FF5171156F6004EA534 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 39 | 80A28FF6171156F6004EA534 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 40 | 80A28FFE171156F6004EA534 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 41 | 80A2901B171156F6004EA534 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 42 | 80A2907F171157B9004EA534 /* ICETutorial-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "ICETutorial-Info.plist"; sourceTree = ""; }; 43 | 80A29080171157B9004EA534 /* ICETutorial-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ICETutorial-Prefix.pch"; sourceTree = ""; }; 44 | CD29BF111952C7B6005A5104 /* ICETutorialStyle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ICETutorialStyle.h; sourceTree = ""; }; 45 | CD29BF121952C7B6005A5104 /* ICETutorialStyle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ICETutorialStyle.m; sourceTree = ""; }; 46 | CD6955E617C9120E0003ECA5 /* background-gradient.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "background-gradient.png"; path = "Resources/background-gradient.png"; sourceTree = SOURCE_ROOT; }; 47 | CD6955E717C9120E0003ECA5 /* background-gradient@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "background-gradient@2x.png"; path = "Resources/background-gradient@2x.png"; sourceTree = SOURCE_ROOT; }; 48 | CD6955E817C9120E0003ECA5 /* button-background.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "button-background.png"; path = "Resources/button-background.png"; sourceTree = SOURCE_ROOT; }; 49 | CD6955E917C9120E0003ECA5 /* button-background@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "button-background@2x.png"; path = "Resources/button-background@2x.png"; sourceTree = SOURCE_ROOT; }; 50 | CD6955EA17C9120E0003ECA5 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Default-568h@2x.png"; path = "Resources/Default-568h@2x.png"; sourceTree = SOURCE_ROOT; }; 51 | CD6955EB17C9120E0003ECA5 /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Default.png; path = Resources/Default.png; sourceTree = SOURCE_ROOT; }; 52 | CD6955EC17C9120E0003ECA5 /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Default@2x.png"; path = "Resources/Default@2x.png"; sourceTree = SOURCE_ROOT; }; 53 | CD6955ED17C9120E0003ECA5 /* tutorial_background_00@2x.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; name = "tutorial_background_00@2x.jpg"; path = "Resources/tutorial_background_00@2x.jpg"; sourceTree = SOURCE_ROOT; }; 54 | CD6955EE17C9120E0003ECA5 /* tutorial_background_01@2x.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; name = "tutorial_background_01@2x.jpg"; path = "Resources/tutorial_background_01@2x.jpg"; sourceTree = SOURCE_ROOT; }; 55 | CD6955EF17C9120E0003ECA5 /* tutorial_background_02@2x.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; name = "tutorial_background_02@2x.jpg"; path = "Resources/tutorial_background_02@2x.jpg"; sourceTree = SOURCE_ROOT; }; 56 | CD6955F017C9120E0003ECA5 /* tutorial_background_03@2x.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; name = "tutorial_background_03@2x.jpg"; path = "Resources/tutorial_background_03@2x.jpg"; sourceTree = SOURCE_ROOT; }; 57 | CD6955F117C9120E0003ECA5 /* tutorial_background_04@2x.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; name = "tutorial_background_04@2x.jpg"; path = "Resources/tutorial_background_04@2x.jpg"; sourceTree = SOURCE_ROOT; }; 58 | CDC0638717006175004E4142 /* ICETutorial.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ICETutorial.app; sourceTree = BUILT_PRODUCTS_DIR; }; 59 | CDC0638A17006175004E4142 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 60 | CDC0638C17006175004E4142 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 61 | CDC0638E17006175004E4142 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 62 | /* End PBXFileReference section */ 63 | 64 | /* Begin PBXFrameworksBuildPhase section */ 65 | CDC0638417006175004E4142 /* Frameworks */ = { 66 | isa = PBXFrameworksBuildPhase; 67 | buildActionMask = 2147483647; 68 | files = ( 69 | CDC0638B17006175004E4142 /* UIKit.framework in Frameworks */, 70 | CDC0638D17006175004E4142 /* Foundation.framework in Frameworks */, 71 | CDC0638F17006175004E4142 /* CoreGraphics.framework in Frameworks */, 72 | ); 73 | runOnlyForDeploymentPostprocessing = 0; 74 | }; 75 | /* End PBXFrameworksBuildPhase section */ 76 | 77 | /* Begin PBXGroup section */ 78 | 0C6833CB1747B7B8004F9123 /* Libraries */ = { 79 | isa = PBXGroup; 80 | children = ( 81 | 0C6833CF1747B831004F9123 /* ICETutorialPage.h */, 82 | 0C6833D01747B831004F9123 /* ICETutorialPage.m */, 83 | CD29BF111952C7B6005A5104 /* ICETutorialStyle.h */, 84 | CD29BF121952C7B6005A5104 /* ICETutorialStyle.m */, 85 | 0C6833CC1747B7B8004F9123 /* ICETutorialController.h */, 86 | 0C6833CD1747B7B8004F9123 /* ICETutorialController.m */, 87 | ); 88 | name = Libraries; 89 | path = ICETutorial/Libraries; 90 | sourceTree = ""; 91 | }; 92 | 80A28FF4171156F6004EA534 /* ICETutorial */ = { 93 | isa = PBXGroup; 94 | children = ( 95 | 80A2907F171157B9004EA534 /* ICETutorial-Info.plist */, 96 | 80A29080171157B9004EA534 /* ICETutorial-Prefix.pch */, 97 | 80A28FF5171156F6004EA534 /* AppDelegate.h */, 98 | 80A28FF6171156F6004EA534 /* AppDelegate.m */, 99 | 80A28FFD171156F6004EA534 /* InfoPlist.strings */, 100 | 80A2901B171156F6004EA534 /* main.m */, 101 | ); 102 | path = ICETutorial; 103 | sourceTree = ""; 104 | }; 105 | 80A2904417115756004EA534 /* Resources */ = { 106 | isa = PBXGroup; 107 | children = ( 108 | CD6955E617C9120E0003ECA5 /* background-gradient.png */, 109 | CD6955E717C9120E0003ECA5 /* background-gradient@2x.png */, 110 | CD6955E817C9120E0003ECA5 /* button-background.png */, 111 | CD6955E917C9120E0003ECA5 /* button-background@2x.png */, 112 | CD6955EA17C9120E0003ECA5 /* Default-568h@2x.png */, 113 | CD6955EB17C9120E0003ECA5 /* Default.png */, 114 | CD6955EC17C9120E0003ECA5 /* Default@2x.png */, 115 | CD6955ED17C9120E0003ECA5 /* tutorial_background_00@2x.jpg */, 116 | CD6955EE17C9120E0003ECA5 /* tutorial_background_01@2x.jpg */, 117 | CD6955EF17C9120E0003ECA5 /* tutorial_background_02@2x.jpg */, 118 | CD6955F017C9120E0003ECA5 /* tutorial_background_03@2x.jpg */, 119 | CD6955F117C9120E0003ECA5 /* tutorial_background_04@2x.jpg */, 120 | ); 121 | path = Resources; 122 | sourceTree = ""; 123 | }; 124 | CDC0637E17006174004E4142 = { 125 | isa = PBXGroup; 126 | children = ( 127 | 80A2904417115756004EA534 /* Resources */, 128 | 0C6833CB1747B7B8004F9123 /* Libraries */, 129 | 80A28FF4171156F6004EA534 /* ICETutorial */, 130 | CDC0638917006175004E4142 /* Frameworks */, 131 | CDC0638817006175004E4142 /* Products */, 132 | ); 133 | sourceTree = ""; 134 | }; 135 | CDC0638817006175004E4142 /* Products */ = { 136 | isa = PBXGroup; 137 | children = ( 138 | CDC0638717006175004E4142 /* ICETutorial.app */, 139 | ); 140 | name = Products; 141 | sourceTree = ""; 142 | }; 143 | CDC0638917006175004E4142 /* Frameworks */ = { 144 | isa = PBXGroup; 145 | children = ( 146 | CDC0638A17006175004E4142 /* UIKit.framework */, 147 | CDC0638C17006175004E4142 /* Foundation.framework */, 148 | CDC0638E17006175004E4142 /* CoreGraphics.framework */, 149 | ); 150 | name = Frameworks; 151 | sourceTree = ""; 152 | }; 153 | /* End PBXGroup section */ 154 | 155 | /* Begin PBXNativeTarget section */ 156 | CDC0638617006175004E4142 /* ICETutorial */ = { 157 | isa = PBXNativeTarget; 158 | buildConfigurationList = CDC063AD17006175004E4142 /* Build configuration list for PBXNativeTarget "ICETutorial" */; 159 | buildPhases = ( 160 | CDC0638317006175004E4142 /* Sources */, 161 | CDC0638417006175004E4142 /* Frameworks */, 162 | CDC0638517006175004E4142 /* Resources */, 163 | ); 164 | buildRules = ( 165 | ); 166 | dependencies = ( 167 | ); 168 | name = ICETutorial; 169 | productName = tutorial; 170 | productReference = CDC0638717006175004E4142 /* ICETutorial.app */; 171 | productType = "com.apple.product-type.application"; 172 | }; 173 | /* End PBXNativeTarget section */ 174 | 175 | /* Begin PBXProject section */ 176 | CDC0637F17006174004E4142 /* Project object */ = { 177 | isa = PBXProject; 178 | attributes = { 179 | LastUpgradeCheck = 0460; 180 | ORGANIZATIONNAME = "Patrick Trillsam"; 181 | }; 182 | buildConfigurationList = CDC0638217006174004E4142 /* Build configuration list for PBXProject "ICETutorial" */; 183 | compatibilityVersion = "Xcode 3.2"; 184 | developmentRegion = English; 185 | hasScannedForEncodings = 0; 186 | knownRegions = ( 187 | en, 188 | ); 189 | mainGroup = CDC0637E17006174004E4142; 190 | productRefGroup = CDC0638817006175004E4142 /* Products */; 191 | projectDirPath = ""; 192 | projectRoot = ""; 193 | targets = ( 194 | CDC0638617006175004E4142 /* ICETutorial */, 195 | ); 196 | }; 197 | /* End PBXProject section */ 198 | 199 | /* Begin PBXResourcesBuildPhase section */ 200 | CDC0638517006175004E4142 /* Resources */ = { 201 | isa = PBXResourcesBuildPhase; 202 | buildActionMask = 2147483647; 203 | files = ( 204 | CDAD68DE17C4CAB600737949 /* InfoPlist.strings in Resources */, 205 | CD6955F217C9120E0003ECA5 /* background-gradient.png in Resources */, 206 | CD6955F317C9120E0003ECA5 /* background-gradient@2x.png in Resources */, 207 | CD6955F417C9120E0003ECA5 /* button-background.png in Resources */, 208 | CD6955F517C9120E0003ECA5 /* button-background@2x.png in Resources */, 209 | CD6955F617C9120E0003ECA5 /* Default-568h@2x.png in Resources */, 210 | CD6955F717C9120E0003ECA5 /* Default.png in Resources */, 211 | CD6955F817C9120E0003ECA5 /* Default@2x.png in Resources */, 212 | CD6955F917C9120E0003ECA5 /* tutorial_background_00@2x.jpg in Resources */, 213 | CD6955FA17C9120E0003ECA5 /* tutorial_background_01@2x.jpg in Resources */, 214 | CD6955FB17C9120E0003ECA5 /* tutorial_background_02@2x.jpg in Resources */, 215 | CD6955FC17C9120E0003ECA5 /* tutorial_background_03@2x.jpg in Resources */, 216 | CD6955FD17C9120E0003ECA5 /* tutorial_background_04@2x.jpg in Resources */, 217 | ); 218 | runOnlyForDeploymentPostprocessing = 0; 219 | }; 220 | /* End PBXResourcesBuildPhase section */ 221 | 222 | /* Begin PBXSourcesBuildPhase section */ 223 | CDC0638317006175004E4142 /* Sources */ = { 224 | isa = PBXSourcesBuildPhase; 225 | buildActionMask = 2147483647; 226 | files = ( 227 | 80A29020171156F6004EA534 /* AppDelegate.m in Sources */, 228 | 80A29041171156F6004EA534 /* main.m in Sources */, 229 | 0C6833CE1747B7B8004F9123 /* ICETutorialController.m in Sources */, 230 | CD29BF131952C7B6005A5104 /* ICETutorialStyle.m in Sources */, 231 | 0C6833D11747B831004F9123 /* ICETutorialPage.m in Sources */, 232 | ); 233 | runOnlyForDeploymentPostprocessing = 0; 234 | }; 235 | /* End PBXSourcesBuildPhase section */ 236 | 237 | /* Begin PBXVariantGroup section */ 238 | 80A28FFD171156F6004EA534 /* InfoPlist.strings */ = { 239 | isa = PBXVariantGroup; 240 | children = ( 241 | 80A28FFE171156F6004EA534 /* en */, 242 | ); 243 | name = InfoPlist.strings; 244 | sourceTree = ""; 245 | }; 246 | /* End PBXVariantGroup section */ 247 | 248 | /* Begin XCBuildConfiguration section */ 249 | CDC063AB17006175004E4142 /* Debug */ = { 250 | isa = XCBuildConfiguration; 251 | buildSettings = { 252 | ALWAYS_SEARCH_USER_PATHS = NO; 253 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 254 | CLANG_CXX_LIBRARY = "libc++"; 255 | CLANG_ENABLE_OBJC_ARC = YES; 256 | CLANG_WARN_CONSTANT_CONVERSION = YES; 257 | CLANG_WARN_EMPTY_BODY = YES; 258 | CLANG_WARN_ENUM_CONVERSION = YES; 259 | CLANG_WARN_INT_CONVERSION = YES; 260 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 261 | CODE_SIGN_IDENTITY = ""; 262 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 263 | COPY_PHASE_STRIP = NO; 264 | GCC_C_LANGUAGE_STANDARD = gnu99; 265 | GCC_DYNAMIC_NO_PIC = NO; 266 | GCC_OPTIMIZATION_LEVEL = 0; 267 | GCC_PREPROCESSOR_DEFINITIONS = ( 268 | "DEBUG=1", 269 | "$(inherited)", 270 | ); 271 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 272 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 273 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 274 | GCC_WARN_UNUSED_VARIABLE = YES; 275 | IPHONEOS_DEPLOYMENT_TARGET = 6.1; 276 | ONLY_ACTIVE_ARCH = YES; 277 | SDKROOT = iphoneos; 278 | TARGETED_DEVICE_FAMILY = "1,2"; 279 | }; 280 | name = Debug; 281 | }; 282 | CDC063AC17006175004E4142 /* Release */ = { 283 | isa = XCBuildConfiguration; 284 | buildSettings = { 285 | ALWAYS_SEARCH_USER_PATHS = NO; 286 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 287 | CLANG_CXX_LIBRARY = "libc++"; 288 | CLANG_ENABLE_OBJC_ARC = YES; 289 | CLANG_WARN_CONSTANT_CONVERSION = YES; 290 | CLANG_WARN_EMPTY_BODY = YES; 291 | CLANG_WARN_ENUM_CONVERSION = YES; 292 | CLANG_WARN_INT_CONVERSION = YES; 293 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 294 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 295 | COPY_PHASE_STRIP = YES; 296 | GCC_C_LANGUAGE_STANDARD = gnu99; 297 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 298 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 299 | GCC_WARN_UNUSED_VARIABLE = YES; 300 | IPHONEOS_DEPLOYMENT_TARGET = 6.1; 301 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 302 | SDKROOT = iphoneos; 303 | TARGETED_DEVICE_FAMILY = "1,2"; 304 | VALIDATE_PRODUCT = YES; 305 | }; 306 | name = Release; 307 | }; 308 | CDC063AE17006175004E4142 /* Debug */ = { 309 | isa = XCBuildConfiguration; 310 | buildSettings = { 311 | CLANG_ENABLE_MODULES = YES; 312 | DEFINES_MODULE = NO; 313 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 314 | GCC_PREFIX_HEADER = "ICETutorial/ICETutorial-Prefix.pch"; 315 | INFOPLIST_FILE = "ICETutorial/ICETutorial-Info.plist"; 316 | PRODUCT_NAME = ICETutorial; 317 | WRAPPER_EXTENSION = app; 318 | }; 319 | name = Debug; 320 | }; 321 | CDC063AF17006175004E4142 /* Release */ = { 322 | isa = XCBuildConfiguration; 323 | buildSettings = { 324 | CLANG_ENABLE_MODULES = YES; 325 | DEFINES_MODULE = NO; 326 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 327 | GCC_PREFIX_HEADER = "ICETutorial/ICETutorial-Prefix.pch"; 328 | INFOPLIST_FILE = "ICETutorial/ICETutorial-Info.plist"; 329 | PRODUCT_NAME = ICETutorial; 330 | WRAPPER_EXTENSION = app; 331 | }; 332 | name = Release; 333 | }; 334 | /* End XCBuildConfiguration section */ 335 | 336 | /* Begin XCConfigurationList section */ 337 | CDC0638217006174004E4142 /* Build configuration list for PBXProject "ICETutorial" */ = { 338 | isa = XCConfigurationList; 339 | buildConfigurations = ( 340 | CDC063AB17006175004E4142 /* Debug */, 341 | CDC063AC17006175004E4142 /* Release */, 342 | ); 343 | defaultConfigurationIsVisible = 0; 344 | defaultConfigurationName = Release; 345 | }; 346 | CDC063AD17006175004E4142 /* Build configuration list for PBXNativeTarget "ICETutorial" */ = { 347 | isa = XCConfigurationList; 348 | buildConfigurations = ( 349 | CDC063AE17006175004E4142 /* Debug */, 350 | CDC063AF17006175004E4142 /* Release */, 351 | ); 352 | defaultConfigurationIsVisible = 0; 353 | defaultConfigurationName = Release; 354 | }; 355 | /* End XCConfigurationList section */ 356 | }; 357 | rootObject = CDC0637F17006174004E4142 /* Project object */; 358 | } 359 | -------------------------------------------------------------------------------- /ICETutorial.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ICETutorial.xcodeproj/project.xcworkspace/xcuserdata/icepat-dev.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icepat/ICETutorial/2e7a26289e8a4ff35d3f2b1c098a38476f68a578/ICETutorial.xcodeproj/project.xcworkspace/xcuserdata/icepat-dev.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /ICETutorial.xcodeproj/project.xcworkspace/xcuserdata/icepat-dev.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges 6 | 7 | SnapshotAutomaticallyBeforeSignificantChanges 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ICETutorial.xcodeproj/project.xcworkspace/xcuserdata/icepatdev.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icepat/ICETutorial/2e7a26289e8a4ff35d3f2b1c098a38476f68a578/ICETutorial.xcodeproj/project.xcworkspace/xcuserdata/icepatdev.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /ICETutorial.xcodeproj/project.xcworkspace/xcuserdata/patrick.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icepat/ICETutorial/2e7a26289e8a4ff35d3f2b1c098a38476f68a578/ICETutorial.xcodeproj/project.xcworkspace/xcuserdata/patrick.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /ICETutorial.xcodeproj/xcuserdata/icepat-dev.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /ICETutorial.xcodeproj/xcuserdata/icepat-dev.xcuserdatad/xcschemes/tutorial.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /ICETutorial.xcodeproj/xcuserdata/icepat-dev.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | tutorial.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | CDC0638617006175004E4142 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /ICETutorial.xcodeproj/xcuserdata/icepatdev.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /ICETutorial.xcodeproj/xcuserdata/icepatdev.xcuserdatad/xcschemes/ICETutorial.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /ICETutorial.xcodeproj/xcuserdata/icepatdev.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | ICETutorial.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | CDC0638617006175004E4142 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /ICETutorial.xcodeproj/xcuserdata/patrick.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /ICETutorial.xcodeproj/xcuserdata/patrick.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | ICETutorial.xcscheme 8 | 9 | orderHint 10 | 1 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | CDC0638617006175004E4142 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /ICETutorial/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // ICETutorial 4 | // 5 | // Created by Patrick Trillsam on 25/03/13. 6 | // Copyright (c) 2014 https://github.com/icepat/ICETutorial. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | #import "ICETutorialController.h" 11 | 12 | @interface AppDelegate : UIResponder 13 | 14 | @property (strong, nonatomic) UIWindow *window; 15 | @property (strong, nonatomic) ICETutorialController *viewController; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /ICETutorial/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // ICETutorial 4 | // 5 | // Created by Patrick Trillsam on 25/03/13. 6 | // Copyright (c) 2014 https://github.com/icepat/ICETutorial. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @implementation AppDelegate 12 | 13 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 14 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 15 | 16 | // Init the pages texts, and pictures. 17 | ICETutorialPage *layer1 = [[ICETutorialPage alloc] initWithTitle:@"Picture 1" 18 | subTitle:@"Champs-Elysées by night" 19 | pictureName:@"tutorial_background_00@2x.jpg" 20 | duration:3.0]; 21 | ICETutorialPage *layer2 = [[ICETutorialPage alloc] initWithTitle:@"Picture 2" 22 | subTitle:@"The Eiffel Tower with\n cloudy weather" 23 | pictureName:@"tutorial_background_01@2x.jpg" 24 | duration:3.0]; 25 | ICETutorialPage *layer3 = [[ICETutorialPage alloc] initWithTitle:@"Picture 3" 26 | subTitle:@"An other famous street of Paris" 27 | pictureName:@"tutorial_background_02@2x.jpg" 28 | duration:3.0]; 29 | ICETutorialPage *layer4 = [[ICETutorialPage alloc] initWithTitle:@"Picture 4" 30 | subTitle:@"The Eiffel Tower with a better weather" 31 | pictureName:@"tutorial_background_03@2x.jpg" 32 | duration:3.0]; 33 | ICETutorialPage *layer5 = [[ICETutorialPage alloc] initWithTitle:@"Picture 5" 34 | subTitle:@"The Louvre's Museum Pyramide" 35 | pictureName:@"tutorial_background_04@2x.jpg" 36 | duration:3.0]; 37 | NSArray *tutorialLayers = @[layer1,layer2,layer3,layer4,layer5]; 38 | 39 | // Set the common style for the title. 40 | ICETutorialLabelStyle *titleStyle = [[ICETutorialLabelStyle alloc] init]; 41 | [titleStyle setFont:[UIFont fontWithName:@"Helvetica-Bold" size:17.0f]]; 42 | [titleStyle setTextColor:[UIColor whiteColor]]; 43 | [titleStyle setLinesNumber:1]; 44 | [titleStyle setOffset:180]; 45 | [[ICETutorialStyle sharedInstance] setTitleStyle:titleStyle]; 46 | 47 | // Set the subTitles style with few properties and let the others by default. 48 | [[ICETutorialStyle sharedInstance] setSubTitleColor:[UIColor whiteColor]]; 49 | [[ICETutorialStyle sharedInstance] setSubTitleOffset:150]; 50 | 51 | // Init tutorial. 52 | self.viewController = [[ICETutorialController alloc] initWithPages:tutorialLayers 53 | delegate:self]; 54 | 55 | // Run it. 56 | [self.viewController startScrolling]; 57 | 58 | self.window.rootViewController = self.viewController; 59 | [self.window makeKeyAndVisible]; 60 | return YES; 61 | } 62 | 63 | #pragma mark - ICETutorialController delegate 64 | - (void)tutorialController:(ICETutorialController *)tutorialController scrollingFromPageIndex:(NSUInteger)fromIndex toPageIndex:(NSUInteger)toIndex { 65 | NSLog(@"Scrolling from page %lu to page %lu.", (unsigned long)fromIndex, (unsigned long)toIndex); 66 | } 67 | 68 | - (void)tutorialControllerDidReachLastPage:(ICETutorialController *)tutorialController { 69 | NSLog(@"Tutorial reached the last page."); 70 | } 71 | 72 | - (void)tutorialController:(ICETutorialController *)tutorialController didClickOnLeftButton:(UIButton *)sender { 73 | NSLog(@"Button 1 pressed."); 74 | } 75 | 76 | - (void)tutorialController:(ICETutorialController *)tutorialController didClickOnRightButton:(UIButton *)sender { 77 | NSLog(@"Button 2 pressed."); 78 | NSLog(@"Auto-scrolling stopped."); 79 | 80 | [self.viewController stopScrolling]; 81 | } 82 | 83 | - (void)applicationWillResignActive:(UIApplication *)application 84 | { 85 | // 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. 86 | // 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. 87 | } 88 | 89 | - (void)applicationDidEnterBackground:(UIApplication *)application 90 | { 91 | // 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. 92 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 93 | } 94 | 95 | - (void)applicationWillEnterForeground:(UIApplication *)application 96 | { 97 | // 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. 98 | } 99 | 100 | - (void)applicationDidBecomeActive:(UIApplication *)application 101 | { 102 | // 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. 103 | } 104 | 105 | - (void)applicationWillTerminate:(UIApplication *)application 106 | { 107 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 108 | } 109 | 110 | @end 111 | -------------------------------------------------------------------------------- /ICETutorial/ICETutorial-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | com.icepat.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.1.1 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.1.1 25 | LSRequiresIPhoneOS 26 | 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /ICETutorial/ICETutorial-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'tutorial' target in the 'tutorial' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_4_0 8 | #warning "This project uses features only available in iOS SDK 4.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /ICETutorial/Libraries/ICETutorialController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ICETutorialController.h 3 | // ICETutorial 4 | // 5 | // Created by Patrick Trillsam on 25/03/13. 6 | // Copyright (c) 2014 https://github.com/icepat/ICETutorial. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | #import "ICETutorialPage.h" 11 | #import "ICETutorialStyle.h" 12 | 13 | #define TUTORIAL_LABEL_TEXT_COLOR [UIColor whiteColor] 14 | #define TUTORIAL_LABEL_HEIGHT 45 15 | #define TUTORIAL_TITLE_FONT [UIFont fontWithName:@"Helvetica-Bold" size:17.0f] 16 | #define TUTORIAL_TITLE_LINES_NUMBER 1 17 | #define TUTORIAL_TITLE_OFFSET 180 18 | #define TUTORIAL_SUB_TITLE_FONT [UIFont fontWithName:@"Helvetica" size:15.0f] 19 | #define TUTORIAL_SUB_TITLE_LINES_NUMBER 2 20 | #define TUTORIAL_SUB_TITLE_OFFSET 150 21 | 22 | // Scrolling state. 23 | typedef NS_OPTIONS(NSUInteger, ScrollingState) { 24 | ScrollingStateAuto = 1 << 0, 25 | ScrollingStateManual = 1 << 1, 26 | ScrollingStateLooping = 1 << 2, 27 | }; 28 | 29 | typedef void (^ButtonBlock)(UIButton *button); 30 | 31 | @protocol ICETutorialControllerDelegate; 32 | @interface ICETutorialController : UIViewController 33 | 34 | @property (nonatomic, assign) BOOL autoScrollEnabled; 35 | @property (nonatomic, weak) id delegate; 36 | 37 | // Inits. 38 | - (instancetype)initWithPages:(NSArray *)pages; 39 | - (instancetype)initWithPages:(NSArray *)pages 40 | delegate:(id)delegate; 41 | 42 | // Pages management. 43 | - (void)setPages:(NSArray*)pages; 44 | - (NSUInteger)numberOfPages; 45 | 46 | // Scrolling. 47 | - (void)startScrolling; 48 | - (void)stopScrolling; 49 | 50 | // State. 51 | - (ScrollingState)getCurrentState; 52 | 53 | @end 54 | 55 | @protocol ICETutorialControllerDelegate 56 | 57 | @optional 58 | - (void)tutorialController:(ICETutorialController *)tutorialController scrollingFromPageIndex:(NSUInteger)fromIndex toPageIndex:(NSUInteger)toIndex; 59 | - (void)tutorialControllerDidReachLastPage:(ICETutorialController *)tutorialController; 60 | - (void)tutorialController:(ICETutorialController *)tutorialController didClickOnLeftButton:(UIButton *)sender; 61 | - (void)tutorialController:(ICETutorialController *)tutorialController didClickOnRightButton:(UIButton *)sender; 62 | @end 63 | -------------------------------------------------------------------------------- /ICETutorial/Libraries/ICETutorialController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ICETutorialController.m 3 | // ICETutorial 4 | // 5 | // Created by Patrick Trillsam on 25/03/13. 6 | // Copyright (c) 2014 https://github.com/icepat/ICETutorial. All rights reserved. 7 | // 8 | 9 | #import "ICETutorialController.h" 10 | 11 | @interface ICETutorialController () 12 | @property (nonatomic, strong, readonly) UIImageView *frontLayerView; 13 | @property (nonatomic, strong, readonly) UIImageView *backLayerView; 14 | @property (nonatomic, strong, readonly) UIImageView *gradientView; 15 | @property (nonatomic, strong, readonly) UIScrollView *scrollView; 16 | @property (nonatomic, strong, readonly) UILabel *overlayTitle; 17 | @property (nonatomic, strong, readonly) UIPageControl *pageControl; 18 | @property (nonatomic, strong, readonly) UIButton *leftButton; 19 | @property (nonatomic, strong, readonly) UIButton *rightButton; 20 | 21 | @property (nonatomic, assign) ScrollingState currentState; 22 | @property (nonatomic, strong) NSArray *pages; 23 | @property (nonatomic, assign) NSInteger currentPageIndex; 24 | @property (nonatomic, assign) NSInteger nextPageIndex; 25 | 26 | @end 27 | 28 | @implementation ICETutorialController 29 | 30 | - (instancetype)initWithPages:(NSArray *)pages { 31 | self = [self init]; 32 | if (self) { 33 | _autoScrollEnabled = YES; 34 | _pages = pages; 35 | 36 | _frontLayerView = [[UIImageView alloc] init]; 37 | _backLayerView = [[UIImageView alloc] init]; 38 | _gradientView = [[UIImageView alloc] init]; 39 | _scrollView = [[UIScrollView alloc] init]; 40 | 41 | _overlayTitle = [[UILabel alloc] init]; 42 | _pageControl = [[UIPageControl alloc] init]; 43 | _leftButton = [[UIButton alloc] init]; 44 | _rightButton = [[UIButton alloc] init]; 45 | } 46 | return self; 47 | } 48 | 49 | - (instancetype)initWithPages:(NSArray *)pages 50 | delegate:(id)delegate { 51 | self = [self initWithPages:pages]; 52 | if (self) { 53 | _delegate = delegate; 54 | } 55 | return self; 56 | } 57 | 58 | - (void)viewDidLoad { 59 | [super viewDidLoad]; 60 | [self.view setBackgroundColor:[UIColor blackColor]]; 61 | 62 | [self setupView]; 63 | 64 | // Overlays. 65 | [self setOverlayTexts]; 66 | [self setOverlayTitle]; 67 | 68 | // Preset the origin state. 69 | [self setOriginLayersState]; 70 | } 71 | 72 | - (void)setupView { 73 | [self.frontLayerView setFrame:self.view.bounds]; 74 | [self.backLayerView setFrame:self.view.bounds]; 75 | 76 | // Decoration. 77 | [self.gradientView setImage:[UIImage imageNamed:@"background-gradient.png"]]; 78 | 79 | // ScrollView configuration. 80 | [self.scrollView setFrame:self.view.bounds]; 81 | [self.scrollView setDelegate:self]; 82 | [self.scrollView setPagingEnabled:YES]; 83 | [self.scrollView setContentSize:CGSizeMake([self numberOfPages] * self.view.frame.size.width, 84 | self.scrollView.contentSize.height)]; 85 | 86 | // Title. 87 | [self.overlayTitle setTextColor:[UIColor whiteColor]]; 88 | [self.overlayTitle setFont:[UIFont fontWithName:@"Helvetica-Bold" size:32.0]]; 89 | [self.overlayTitle setTextAlignment:NSTextAlignmentCenter]; 90 | 91 | // PageControl configuration. 92 | [self.pageControl setNumberOfPages:[self numberOfPages]]; 93 | [self.pageControl setCurrentPage:0]; 94 | [self.pageControl addTarget:self 95 | action:@selector(didClickOnPageControl:) 96 | forControlEvents:UIControlEventValueChanged]; 97 | 98 | // UIButtons. 99 | [self.leftButton setBackgroundColor:[UIColor darkGrayColor]]; 100 | [self.rightButton setBackgroundColor:[UIColor darkGrayColor]]; 101 | [self.leftButton setTitle:@"Button 1" forState:UIControlStateNormal]; 102 | [self.rightButton setTitle:@"Button 2" forState:UIControlStateNormal]; 103 | [self.leftButton addTarget:self 104 | action:@selector(didClickOnButton1:) 105 | forControlEvents:UIControlEventTouchUpInside]; 106 | [self.rightButton addTarget:self 107 | action:@selector(didClickOnButton2:) 108 | forControlEvents:UIControlEventTouchUpInside]; 109 | 110 | [self.view addSubview:self.frontLayerView]; 111 | [self.view addSubview:self.backLayerView]; 112 | [self.view addSubview:self.gradientView]; 113 | [self.view addSubview:self.scrollView]; 114 | [self.view addSubview:self.overlayTitle]; 115 | [self.view addSubview:self.pageControl]; 116 | [self.view addSubview:self.leftButton]; 117 | [self.view addSubview:self.rightButton]; 118 | 119 | [self addAllConstraints]; 120 | } 121 | 122 | #pragma mark - Constraints management. 123 | - (void)addAllConstraints { 124 | [self.frontLayerView setAutoresizingMask:UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight]; 125 | [self.backLayerView setAutoresizingMask:UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight]; 126 | 127 | NSDictionary *views = NSDictionaryOfVariableBindings(_overlayTitle, _leftButton, _rightButton, _pageControl, _gradientView); 128 | NSMutableArray *constraints = [NSMutableArray array]; 129 | 130 | // Overlay title. 131 | [self.overlayTitle setTranslatesAutoresizingMaskIntoConstraints:NO]; 132 | [constraints addObject:@"V:|-116-[_overlayTitle(==50)]"]; 133 | [constraints addObject:@"H:|-54-[_overlayTitle(==212)]-|"]; 134 | 135 | // Buttons. 136 | [self.leftButton setTranslatesAutoresizingMaskIntoConstraints:NO]; 137 | [self.rightButton setTranslatesAutoresizingMaskIntoConstraints:NO]; 138 | [constraints addObject:@"V:[_leftButton(==36)]-20-|"]; 139 | [constraints addObject:@"V:[_rightButton(==36)]-20-|"]; 140 | [constraints addObject:@"H:|-20-[_leftButton(==_rightButton)]-20-[_rightButton(>=130)]-20-|"]; 141 | 142 | // PageControl. 143 | [self.pageControl setTranslatesAutoresizingMaskIntoConstraints:NO]; 144 | [constraints addObject:@"V:[_pageControl(==32)]-60-|"]; 145 | [constraints addObject:@"H:|-140-[_pageControl(==40)]"]; 146 | 147 | // GradientView. 148 | [self.gradientView setTranslatesAutoresizingMaskIntoConstraints:NO]; 149 | [constraints addObject:@"V:[_gradientView(==200)]-0-|"]; 150 | [constraints addObject:@"H:|-0-[_gradientView(==320)]-0-|"]; 151 | 152 | // Set constraints. 153 | for (NSString *string in constraints) { 154 | [self.view addConstraints:[NSLayoutConstraint 155 | constraintsWithVisualFormat:string 156 | options:0 metrics:nil 157 | views:views]]; 158 | } 159 | } 160 | 161 | #pragma mark - Actions 162 | - (IBAction)didClickOnButton1:(id)sender { 163 | if ([self.delegate respondsToSelector:@selector(tutorialController:didClickOnLeftButton:)]) { 164 | [self.delegate tutorialController:self didClickOnLeftButton:sender]; 165 | } 166 | } 167 | 168 | - (IBAction)didClickOnButton2:(id)sender { 169 | if ([self.delegate respondsToSelector:@selector(tutorialController:didClickOnRightButton:)]) { 170 | [self.delegate tutorialController:self didClickOnRightButton:sender]; 171 | } 172 | } 173 | 174 | - (IBAction)didClickOnPageControl:(UIPageControl *)sender { 175 | [self stopScrolling]; 176 | 177 | // Make the scrollView animation. 178 | [self scrollToNextPageIndex:sender.currentPage]; 179 | } 180 | 181 | #pragma mark - Pages 182 | // Set the list of pages (ICETutorialPage). 183 | - (void)setPages:(NSArray *)pages { 184 | _pages = pages; 185 | } 186 | 187 | - (NSUInteger)numberOfPages { 188 | if (self.pages) { 189 | return [self.pages count]; 190 | } 191 | 192 | return 0; 193 | } 194 | 195 | #pragma mark - Animations 196 | - (void)animateScrolling { 197 | if (self.currentState & ScrollingStateManual) { 198 | return; 199 | } 200 | 201 | // Jump to the next page... 202 | NSInteger nextPage = self.currentPageIndex + 1; 203 | if (nextPage == [self numberOfPages]) { 204 | // ...stop the auto-scrolling or... 205 | if (!self.autoScrollEnabled) { 206 | self.currentState = ScrollingStateManual; 207 | return; 208 | } 209 | 210 | // ...jump to the first page. 211 | nextPage = 0; 212 | self.currentState = ScrollingStateLooping; 213 | 214 | // Set alpha on layers. 215 | [self setOriginLayerAlpha]; 216 | [self setBackLayerPictureWithPageIndex:-1]; 217 | } else { 218 | self.currentState = ScrollingStateAuto; 219 | } 220 | 221 | // Make the scrollView animation. 222 | [self scrollToNextPageIndex:nextPage]; 223 | 224 | // Call the next animation after X seconds. 225 | [self autoScrollToNextPage]; 226 | } 227 | 228 | // Call the next animation after X seconds. 229 | - (void)autoScrollToNextPage { 230 | ICETutorialPage *page = self.pages[self.currentPageIndex]; 231 | 232 | if (self.autoScrollEnabled) { 233 | [self performSelector:@selector(animateScrolling) 234 | withObject:nil 235 | afterDelay:page.duration]; 236 | } 237 | } 238 | 239 | - (void)scrollToNextPageIndex:(NSUInteger)nextPageIndex { 240 | // Make the scrollView animation. 241 | [self.scrollView setContentOffset:CGPointMake(nextPageIndex * self.view.frame.size.width,0) 242 | animated:YES]; 243 | 244 | // Set the PageControl on the right page. 245 | [self.pageControl setCurrentPage:nextPageIndex]; 246 | } 247 | 248 | #pragma mark - Scrolling management 249 | // Run it. 250 | - (void)startScrolling { 251 | [self autoScrollToNextPage]; 252 | } 253 | 254 | // Manually stop the scrolling 255 | - (void)stopScrolling { 256 | self.currentState = ScrollingStateManual; 257 | } 258 | 259 | #pragma mark - State management 260 | // State. 261 | - (ScrollingState)getCurrentState { 262 | return self.currentState; 263 | } 264 | 265 | #pragma mark - Overlay management 266 | // Setup the Title Label. 267 | - (void)setOverlayTitle { 268 | // ...or change by an UIImageView if you need it. 269 | [self.overlayTitle setText:@"Welcome"]; 270 | } 271 | 272 | // Setup the Title/Subtitle style/text. 273 | - (void)setOverlayTexts { 274 | int index = 0; 275 | for (ICETutorialPage *page in self.pages) { 276 | // SubTitles. 277 | if ([[[page title] text] length]) { 278 | [self overlayLabelWithStyle:[page title] 279 | commonStyle:[[ICETutorialStyle sharedInstance] titleStyle] 280 | index:index]; 281 | } 282 | // Description. 283 | if ([[[page subTitle] text] length]) { 284 | [self overlayLabelWithStyle:[page subTitle] 285 | commonStyle:[[ICETutorialStyle sharedInstance] subTitleStyle] 286 | index:index]; 287 | } 288 | 289 | index++; 290 | } 291 | } 292 | 293 | - (void)overlayLabelWithStyle:(ICETutorialLabelStyle *)style 294 | commonStyle:(ICETutorialLabelStyle *)commonStyle 295 | index:(NSUInteger)index { 296 | // SubTitles. 297 | UILabel *overlayLabel = [[UILabel alloc] initWithFrame:CGRectMake((index * self.view.frame.size.width), 298 | self.view.frame.size.height - [commonStyle offset], 299 | self.view.frame.size.width, 300 | TUTORIAL_LABEL_HEIGHT)]; 301 | [overlayLabel setNumberOfLines:[commonStyle linesNumber]]; 302 | [overlayLabel setBackgroundColor:[UIColor clearColor]]; 303 | [overlayLabel setTextAlignment:NSTextAlignmentCenter]; 304 | 305 | // Datas and style. 306 | [overlayLabel setText:[style text]]; 307 | [style font] ? [overlayLabel setFont:[style font]] : 308 | [overlayLabel setFont:[commonStyle font]]; 309 | [style textColor] ? [overlayLabel setTextColor:[style textColor]] : 310 | [overlayLabel setTextColor:[commonStyle textColor]]; 311 | 312 | [self.scrollView addSubview:overlayLabel]; 313 | } 314 | 315 | #pragma mark - Layers management 316 | // Handle the background layer image switch. 317 | - (void)setBackLayerPictureWithPageIndex:(NSInteger)index { 318 | [self setBackgroundImage:self.backLayerView withIndex:index + 1]; 319 | } 320 | 321 | // Handle the front layer image switch. 322 | - (void)setFrontLayerPictureWithPageIndex:(NSInteger)index { 323 | [self setBackgroundImage:self.frontLayerView withIndex:index]; 324 | } 325 | 326 | // Handle page image's loading 327 | - (void)setBackgroundImage:(UIImageView *)imageView withIndex:(NSInteger)index { 328 | if (index >= [self.pages count]) { 329 | [imageView setImage:nil]; 330 | return; 331 | } 332 | 333 | [imageView setImage:[UIImage imageNamed:[self.pages[index] pictureName]]]; 334 | } 335 | 336 | // Setup lapyer's alpha. 337 | - (void)setOriginLayerAlpha { 338 | [self.frontLayerView setAlpha:1]; 339 | [self.backLayerView setAlpha:0]; 340 | } 341 | 342 | // Preset the origin state. 343 | - (void)setOriginLayersState { 344 | self.currentState = ScrollingStateAuto; 345 | [self.backLayerView setBackgroundColor:[UIColor blackColor]]; 346 | [self.frontLayerView setBackgroundColor:[UIColor blackColor]]; 347 | [self setLayersPicturesWithIndex:0]; 348 | } 349 | 350 | // Setup the layers with the page index. 351 | - (void)setLayersPicturesWithIndex:(NSInteger)index { 352 | self.currentPageIndex = index; 353 | [self setOriginLayerAlpha]; 354 | [self setFrontLayerPictureWithPageIndex:index]; 355 | [self setBackLayerPictureWithPageIndex:index]; 356 | } 357 | 358 | // Animate the fade-in/out (Cross-disolve) with the scrollView translation. 359 | - (void)disolveBackgroundWithContentOffset:(float)offset { 360 | if (self.currentState & ScrollingStateLooping){ 361 | // Jump from the last page to the first. 362 | [self scrollingToFirstPageWithOffset:offset]; 363 | } else { 364 | // Or just scroll to the next/previous page. 365 | [self scrollingToNextPageWithOffset:offset]; 366 | } 367 | } 368 | 369 | // Handle alpha on layers when the auto-scrolling is looping to the first page. 370 | - (void)scrollingToFirstPageWithOffset:(float)offset { 371 | // Compute the scrolling percentage on all the page. 372 | offset = (offset * self.view.frame.size.width) / (self.view.frame.size.width * [self numberOfPages]); 373 | 374 | // Scrolling finished... 375 | if (!offset){ 376 | // ...reset to the origin state. 377 | [self setOriginLayersState]; 378 | return; 379 | } 380 | 381 | // Invert alpha for the back picture. 382 | float backLayerAlpha = (1 - offset); 383 | float frontLayerAlpha = offset; 384 | 385 | // Set alpha. 386 | [self.backLayerView setAlpha:backLayerAlpha]; 387 | [self.frontLayerView setAlpha:frontLayerAlpha]; 388 | } 389 | 390 | // Handle alpha on layers when we are scrolling to the next/previous page. 391 | - (void)scrollingToNextPageWithOffset:(float)offset { 392 | // Current page index in scrolling. 393 | NSInteger nextPage = (int)offset; 394 | 395 | // Keep only the float value. 396 | float alphaValue = offset - nextPage; 397 | 398 | // This is only when you scroll to the right on the first page. 399 | // That will fade-in black the first picture. 400 | if (alphaValue < 0 && self.currentPageIndex == 0){ 401 | [self.backLayerView setImage:nil]; 402 | [self.frontLayerView setAlpha:(1 + alphaValue)]; 403 | return; 404 | } 405 | 406 | // Switch pictures, and imageView alpha. 407 | if (nextPage != self.currentPageIndex || 408 | ((nextPage == self.currentPageIndex) && (0.0 < offset) && (offset < 1.0))) 409 | [self setLayersPicturesWithIndex:nextPage]; 410 | 411 | // Invert alpha for the front picture. 412 | float backLayerAlpha = alphaValue; 413 | float frontLayerAlpha = (1 - alphaValue); 414 | 415 | // Set alpha. 416 | [self.backLayerView setAlpha:backLayerAlpha]; 417 | [self.frontLayerView setAlpha:frontLayerAlpha]; 418 | } 419 | 420 | #pragma mark - ScrollView delegate 421 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView { 422 | // Get scrolling position, and nextPageindex. 423 | float scrollingPosition = scrollView.contentOffset.x / self.view.frame.size.width; 424 | int nextPageIndex = (int)scrollingPosition; 425 | 426 | // If we are looping, we reset the indexPage. 427 | if (self.currentState & ScrollingStateLooping) { 428 | nextPageIndex = 0; 429 | } 430 | 431 | // If we are going to the next page, let's call the delegate. 432 | if (nextPageIndex != self.nextPageIndex) { 433 | if ([self.delegate respondsToSelector:@selector(tutorialController:scrollingFromPageIndex:toPageIndex:)]) { 434 | [self.delegate tutorialController:self scrollingFromPageIndex:self.currentPageIndex toPageIndex:nextPageIndex]; 435 | } 436 | 437 | self.nextPageIndex = nextPageIndex; 438 | } 439 | 440 | // Delegate when we reach the end. 441 | if (self.nextPageIndex == [self numberOfPages] - 1) { 442 | if ([self.delegate respondsToSelector:@selector(tutorialControllerDidReachLastPage:)]) { 443 | [self.delegate tutorialControllerDidReachLastPage:self]; 444 | } 445 | } 446 | 447 | // Animate. 448 | [self disolveBackgroundWithContentOffset:scrollingPosition]; 449 | } 450 | 451 | - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { 452 | // At the first user interaction, we disable the auto scrolling. 453 | if (self.scrollView.isTracking) { 454 | [self stopScrolling]; 455 | } 456 | } 457 | 458 | - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { 459 | // Update the page index. 460 | [self.pageControl setCurrentPage:self.currentPageIndex]; 461 | } 462 | 463 | @end 464 | -------------------------------------------------------------------------------- /ICETutorial/Libraries/ICETutorialPage.h: -------------------------------------------------------------------------------- 1 | // 2 | // ICETutorialPage.h 3 | // ICETutorial 4 | // 5 | // Created by Patrick Trillsam on 25/03/13. 6 | // Copyright (c) 2014 https://github.com/icepat/ICETutorial. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | @import UIKit; 11 | 12 | @interface ICETutorialLabelStyle : NSObject 13 | 14 | @property (nonatomic, retain) NSString *text; 15 | @property (nonatomic, retain) UIFont *font; 16 | @property (nonatomic, retain) UIColor *textColor; 17 | @property (nonatomic, assign) NSUInteger linesNumber; 18 | @property (nonatomic, assign) NSUInteger offset; 19 | 20 | // Init. 21 | - (instancetype)initWithText:(NSString *)text; 22 | - (instancetype)initWithFont:(UIFont *)font 23 | textColor:(UIColor *)color 24 | linesNumber:(NSUInteger)linesNumber 25 | offset:(NSUInteger)offset; 26 | @end 27 | 28 | @interface ICETutorialPage : NSObject 29 | 30 | @property (nonatomic, retain) ICETutorialLabelStyle *title; 31 | @property (nonatomic, retain) ICETutorialLabelStyle *subTitle; 32 | @property (nonatomic, retain) NSString *pictureName; 33 | @property (nonatomic, assign) NSTimeInterval duration; 34 | 35 | // Init. 36 | - (instancetype)initWithTitle:(NSString *)title 37 | subTitle:(NSString *)subTitle 38 | pictureName:(NSString *)pictureName 39 | duration:(NSTimeInterval)duration; 40 | 41 | - (void)setTitleStyle:(ICETutorialLabelStyle *)style; 42 | - (void)setSubTitleStyle:(ICETutorialLabelStyle *)style; 43 | 44 | @end 45 | 46 | -------------------------------------------------------------------------------- /ICETutorial/Libraries/ICETutorialPage.m: -------------------------------------------------------------------------------- 1 | // 2 | // ICETutorialPage.m 3 | // ICETutorial 4 | // 5 | // Created by Patrick Trillsam on 25/03/13. 6 | // Copyright (c) 2014 https://github.com/icepat/ICETutorial. All rights reserved. 7 | // 8 | 9 | #import "ICETutorialPage.h" 10 | 11 | @implementation ICETutorialLabelStyle 12 | 13 | // Init. 14 | - (instancetype)initWithText:(NSString *)text { 15 | self = [super init]; 16 | if (self){ 17 | _text = text; 18 | } 19 | return self; 20 | } 21 | 22 | - (instancetype)initWithFont:(UIFont *)font 23 | textColor:(UIColor *)color 24 | linesNumber:(NSUInteger)linesNumber 25 | offset:(NSUInteger)offset { 26 | self = [self init]; 27 | if (self){ 28 | _font = font; 29 | _textColor = color; 30 | _linesNumber = linesNumber; 31 | _offset = offset; 32 | } 33 | return self; 34 | } 35 | 36 | @end 37 | 38 | @implementation ICETutorialPage 39 | 40 | // Init. 41 | - (instancetype)initWithTitle:(NSString *)title 42 | subTitle:(NSString *)subTitle 43 | pictureName:(NSString *)pictureName 44 | duration:(NSTimeInterval)duration { 45 | self = [super init]; 46 | if (self){ 47 | _title = [[ICETutorialLabelStyle alloc] initWithText:title]; 48 | _subTitle = [[ICETutorialLabelStyle alloc] initWithText:subTitle]; 49 | _pictureName = pictureName; 50 | _duration = duration; 51 | } 52 | return self; 53 | } 54 | 55 | - (void)setTitleStyle:(ICETutorialLabelStyle *)style { 56 | [self.title setFont:style.font]; 57 | [self.title setTextColor:style.textColor]; 58 | } 59 | 60 | - (void)setSubTitleStyle:(ICETutorialLabelStyle *)style { 61 | [self.subTitle setFont:style.font]; 62 | [self.subTitle setTextColor:style.textColor]; 63 | } 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /ICETutorial/Libraries/ICETutorialStyle.h: -------------------------------------------------------------------------------- 1 | // 2 | // ICETutorialStyle.h 3 | // ICETutorial 4 | // 5 | // Created by Patrick Trillsam on 25/03/13. 6 | // Copyright (c) 2014 https://github.com/icepat/ICETutorial. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | #import "ICETutorialPage.h" 11 | 12 | @interface ICETutorialStyle : NSObject 13 | 14 | @property (nonatomic, strong) UIFont *titleFont; 15 | @property (nonatomic, strong) UIColor *titleColor; 16 | @property (nonatomic, assign) NSUInteger titleLinesNumber; 17 | @property (nonatomic, assign) NSUInteger titleOffset; 18 | @property (nonatomic, strong) UIFont *subTitleFont; 19 | @property (nonatomic, strong) UIColor *subTitleColor; 20 | @property (nonatomic, assign) NSUInteger subTitleLinesNumber; 21 | @property (nonatomic, assign) NSUInteger subTitleOffset; 22 | 23 | @property (nonatomic, strong) ICETutorialLabelStyle *titleStyle; 24 | @property (nonatomic, strong) ICETutorialLabelStyle *subTitleStyle; 25 | 26 | + (instancetype)sharedInstance; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /ICETutorial/Libraries/ICETutorialStyle.m: -------------------------------------------------------------------------------- 1 | // 2 | // ICETutorialStyle.m 3 | // ICETutorial 4 | // 5 | // Created by Patrick Trillsam on 25/03/13. 6 | // Copyright (c) 2014 https://github.com/icepat/ICETutorial. All rights reserved. 7 | // 8 | 9 | #import "ICETutorialStyle.h" 10 | #import "ICETutorialController.h" 11 | 12 | @implementation ICETutorialStyle 13 | 14 | + (instancetype)sharedInstance { 15 | static ICETutorialStyle *sharedInstance = nil; 16 | static dispatch_once_t onceToken = 0; 17 | dispatch_once(&onceToken, ^{ 18 | sharedInstance = [[ICETutorialStyle alloc] init]; 19 | }); 20 | return sharedInstance; 21 | } 22 | 23 | #pragma mark - Properties 24 | - (UIFont *)titleFont { 25 | if (_titleFont) { 26 | return _titleFont; 27 | } 28 | return TUTORIAL_TITLE_FONT; 29 | } 30 | 31 | - (UIColor *)titleColor { 32 | if (_titleColor) { 33 | return _titleColor; 34 | } 35 | return TUTORIAL_LABEL_TEXT_COLOR; 36 | } 37 | 38 | - (NSUInteger)titleLinesNumber { 39 | if (_titleLinesNumber != NSNotFound) { 40 | return _titleLinesNumber; 41 | } 42 | return TUTORIAL_TITLE_LINES_NUMBER; 43 | } 44 | 45 | - (NSUInteger)titleOffset { 46 | if (_titleOffset != NSNotFound) { 47 | return _titleOffset; 48 | } 49 | return TUTORIAL_TITLE_OFFSET; 50 | } 51 | 52 | - (UIFont *)subTitleFont { 53 | if (_subTitleFont) { 54 | return _subTitleFont; 55 | } 56 | return TUTORIAL_SUB_TITLE_FONT; 57 | } 58 | 59 | - (UIColor *)subTitleColor { 60 | if (_subTitleColor) { 61 | return _subTitleColor; 62 | } 63 | return TUTORIAL_LABEL_TEXT_COLOR; 64 | } 65 | 66 | - (NSUInteger)subTitleLinesNumber { 67 | if (_titleLinesNumber != NSNotFound) { 68 | return _titleLinesNumber; 69 | } 70 | return TUTORIAL_SUB_TITLE_LINES_NUMBER; 71 | } 72 | 73 | - (NSUInteger)subTitleOffset { 74 | if (_subTitleOffset != NSNotFound) { 75 | return _subTitleOffset; 76 | } 77 | return TUTORIAL_SUB_TITLE_OFFSET; 78 | } 79 | 80 | #pragma mark - Styles 81 | - (ICETutorialLabelStyle *)titleStyle { 82 | if (_titleStyle) { 83 | return _titleStyle; 84 | } 85 | 86 | return [[ICETutorialLabelStyle alloc] initWithFont:self.titleFont 87 | textColor:self.titleColor 88 | linesNumber:self.titleLinesNumber 89 | offset:self.titleOffset]; 90 | } 91 | 92 | - (ICETutorialLabelStyle *)subTitleStyle { 93 | if (_subTitleStyle) { 94 | return _subTitleStyle; 95 | } 96 | 97 | return [[ICETutorialLabelStyle alloc] initWithFont:self.subTitleFont 98 | textColor:self.subTitleColor 99 | linesNumber:self.subTitleLinesNumber 100 | offset:self.subTitleOffset]; 101 | } 102 | 103 | @end 104 | -------------------------------------------------------------------------------- /ICETutorial/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /ICETutorial/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // ICETutorial 4 | // 5 | // Created by Patrick Trillsam on 25/03/13. 6 | // Copyright (c) 2014 https://github.com/icepat/ICETutorial. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "AppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2013 Patrick Trillsam - ICETutorial 4 | 5 | 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: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | 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 NON INFRINGEMENT. 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. -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | # platform :ios, "6.0" 3 | 4 | source 'https://github.com/CocoaPods/Specs.git' 5 | 6 | target "ICETutorial" do 7 | 8 | end 9 | 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ICETutorial 2 | =========== 3 | 4 | ### Welcome to ICETutorial. 5 | This small project is an implementation of the newly tutorial introduced by the Path 3.X app. 6 | Very simple and efficient tutorial, composed with N full-screen pictures that you can swipe for switching to the next/previous page. 7 | 8 | Here are the features : 9 | * Compose your own tutorial with N pictures 10 | * Fixed incrusted title (can be easily replaced by an UIImageView, or just removed) 11 | * Scrolling sub-titles for page, with associated descriptions (change the texts, font, color...) 12 | * Auto-scrolling (enable/disable, loop, setup duration) 13 | * Cross fade between next/previous background 14 | * Easy to use block access to button's events. 15 | 16 | ![ICETutorial](https://github.com/icepat/ICETutorial/blob/master/screen_shot.jpg?raw=true) 17 | 18 | ### Installation 19 | 20 | With [CocoaPods](http://cocoapods.org/), add this line to your Podfile. 21 | 22 | pod 'ICETutorial', '~> 1.1.1' 23 | 24 | Or add the files manually into your project. 25 | 26 | ### Setting-up the ICETutorial 27 | The code is commented, and I guess, easy to read/understand/modify. 28 | All the available settings for the scrolling are located in the header : ICETutorial.h : 29 | 30 | **Texts and pictures :** 31 | ```objective-c 32 | // Init the pages texts, and pictures. 33 | ICETutorialPage *layer1 = [[ICETutorialPage alloc] initWithSubTitle:@"Picture 1" 34 | description:@"Champs-Elysées by night" 35 | pictureName:@"tutorial_background_00@2x.jpg"]; 36 | ICETutorialPage *layer2 = [[ICETutorialPage alloc] initWithSubTitle:@"Picture 2" 37 | description:@"The Eiffel Tower with\n cloudy weather" 38 | pictureName:@"tutorial_background_01@2x.jpg"]; 39 | [...] 40 | ``` 41 | 42 | **Common styles for SubTitles and Descriptions :** 43 | ```objective-c 44 | // Set the common style for SubTitles and Description (can be overrided on each page). 45 | ICETutorialLabelStyle *subStyle = [[ICETutorialLabelStyle alloc] init]; 46 | [subStyle setFont:TUTORIAL_SUB_TITLE_FONT]; 47 | [subStyle setTextColor:TUTORIAL_LABEL_TEXT_COLOR]; 48 | [subStyle setLinesNumber:TUTORIAL_SUB_TITLE_LINES_NUMBER]; 49 | [subStyle setOffset:TUTORIAL_SUB_TITLE_OFFSET]; 50 | 51 | ICETutorialLabelStyle *descStyle = [[ICETutorialLabelStyle alloc] init]; 52 | [descStyle setFont:TUTORIAL_DESC_FONT]; 53 | [descStyle setTextColor:TUTORIAL_LABEL_TEXT_COLOR]; 54 | [descStyle setLinesNumber:TUTORIAL_DESC_LINES_NUMBER]; 55 | [descStyle setOffset:TUTORIAL_DESC_OFFSET]; 56 | 57 | // Load into an array. 58 | NSArray *tutorialLayers = @[layer1,layer2,layer3,layer4,layer5]; 59 | 60 | ``` 61 | 62 | **Init and load :** 63 | ```objective-c 64 | self.viewController = [[ICETutorialController alloc] initWithNibName:@"ICETutorialController_iPhone" 65 | bundle:nil 66 | andPages:tutorialLayers]; 67 | 68 | // Set the common styles, and start scrolling (auto scroll, and looping enabled by default) 69 | [self.viewController setCommonPageSubTitleStyle:subStyle]; 70 | [self.viewController setCommonPageDescriptionStyle:descStyle]; 71 | 72 | // Set button 1 action. 73 | [self.viewController setButton1Block:^(UIButton *button){ 74 | NSLog(@"Button 1 pressed."); 75 | }]; 76 | 77 | // Set button 2 action, stop the scrolling. 78 | __unsafe_unretained typeof(self) weakSelf = self; 79 | [self.viewController setButton2Block:^(UIButton *button){ 80 | NSLog(@"Button 2 pressed."); 81 | NSLog(@"Auto-scrolling stopped."); 82 | 83 | [weakSelf.viewController stopScrolling]; 84 | }]; 85 | 86 | // Run it. 87 | [self.viewController startScrolling]; 88 | ``` 89 | 90 | **The title is located in the ICETutorial.m :** 91 | ```objective-c 92 | // Setup the Title Label. 93 | - (void)setOverlayTitle{ 94 | // ...or change by an UIImageView if you need it. 95 | [_overlayTitle setText:@"Welcome"]; 96 | } 97 | ``` 98 | 99 | Checkout the others projects available on my account [@Icepat](https://github.com/icepat/) : 100 | 101 | [ICETutorial](https://github.com/icepat/ICETutorial) 102 | 103 | A nice tutorial like the one introduced in the Path 3.X App 104 | 105 | [ICETutorialSwift](https://github.com/icepat/ICETutorialSwift) 106 | 107 | A nice tutorial like the one introduced in the Path 3.X App (in Swift) 108 | 109 | 110 | Questions or ideas : patrick.trillsam@gmail.com. 111 | 112 | 113 | ### License : 114 | 115 | The MIT License 116 | 117 | Copyright (c) 2015 Patrick Trillsam - ICETutorial 118 | 119 | 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: 120 | 121 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 122 | 123 | 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 NON INFRINGEMENT. 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. 124 | -------------------------------------------------------------------------------- /Resources/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icepat/ICETutorial/2e7a26289e8a4ff35d3f2b1c098a38476f68a578/Resources/Default-568h@2x.png -------------------------------------------------------------------------------- /Resources/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icepat/ICETutorial/2e7a26289e8a4ff35d3f2b1c098a38476f68a578/Resources/Default.png -------------------------------------------------------------------------------- /Resources/Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icepat/ICETutorial/2e7a26289e8a4ff35d3f2b1c098a38476f68a578/Resources/Default@2x.png -------------------------------------------------------------------------------- /Resources/background-gradient.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icepat/ICETutorial/2e7a26289e8a4ff35d3f2b1c098a38476f68a578/Resources/background-gradient.png -------------------------------------------------------------------------------- /Resources/background-gradient@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icepat/ICETutorial/2e7a26289e8a4ff35d3f2b1c098a38476f68a578/Resources/background-gradient@2x.png -------------------------------------------------------------------------------- /Resources/button-background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icepat/ICETutorial/2e7a26289e8a4ff35d3f2b1c098a38476f68a578/Resources/button-background.png -------------------------------------------------------------------------------- /Resources/button-background@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icepat/ICETutorial/2e7a26289e8a4ff35d3f2b1c098a38476f68a578/Resources/button-background@2x.png -------------------------------------------------------------------------------- /Resources/tutorial_background_00@2x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icepat/ICETutorial/2e7a26289e8a4ff35d3f2b1c098a38476f68a578/Resources/tutorial_background_00@2x.jpg -------------------------------------------------------------------------------- /Resources/tutorial_background_01@2x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icepat/ICETutorial/2e7a26289e8a4ff35d3f2b1c098a38476f68a578/Resources/tutorial_background_01@2x.jpg -------------------------------------------------------------------------------- /Resources/tutorial_background_02@2x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icepat/ICETutorial/2e7a26289e8a4ff35d3f2b1c098a38476f68a578/Resources/tutorial_background_02@2x.jpg -------------------------------------------------------------------------------- /Resources/tutorial_background_03@2x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icepat/ICETutorial/2e7a26289e8a4ff35d3f2b1c098a38476f68a578/Resources/tutorial_background_03@2x.jpg -------------------------------------------------------------------------------- /Resources/tutorial_background_04@2x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icepat/ICETutorial/2e7a26289e8a4ff35d3f2b1c098a38476f68a578/Resources/tutorial_background_04@2x.jpg -------------------------------------------------------------------------------- /screen_shot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icepat/ICETutorial/2e7a26289e8a4ff35d3f2b1c098a38476f68a578/screen_shot.jpg --------------------------------------------------------------------------------