├── HQCardFlowView.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ └── jkdzkj.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── jkdzkj.xcuserdatad │ └── xcschemes │ └── xcschememanagement.plist ├── HQCardFlowView ├── 20180724141023415.gif ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ ├── 1.imageset │ │ ├── 1.jpeg │ │ └── Contents.json │ ├── 22.imageset │ │ ├── 22.jpeg │ │ └── Contents.json │ ├── 33.imageset │ │ ├── 33.jpeg │ │ └── Contents.json │ ├── 44.imageset │ │ ├── 44.jpeg │ │ └── Contents.json │ ├── 55.imageset │ │ ├── 55.jpeg │ │ └── Contents.json │ ├── 66.imageset │ │ ├── 66.jpeg │ │ └── Contents.json │ ├── 77.imageset │ │ ├── 77.jpeg │ │ └── Contents.json │ ├── 88.imageset │ │ ├── 88.jpeg │ │ └── Contents.json │ ├── 99.imageset │ │ ├── 99.jpeg │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Contents.json │ ├── icon_pageWidget.imageset │ │ ├── Contents.json │ │ ├── icon_pageWidget@2x.png │ │ └── icon_pageWidget@3x.png │ └── icon_pageWidget_sign.imageset │ │ ├── Contents.json │ │ ├── icon_pageWidget_sign@2x.png │ │ └── icon_pageWidget_sign@3x.png ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── HQFlowView │ ├── HQFlowView.h │ ├── HQFlowView.m │ ├── HQImagePageControl.h │ ├── HQImagePageControl.m │ ├── HQIndexBannerSubview.h │ └── HQIndexBannerSubview.m ├── Info.plist ├── ViewController.h ├── ViewController.m └── main.m ├── HQCardFlowViewTests ├── HQCardFlowViewTests.m └── Info.plist ├── HQCardFlowViewUITests ├── HQCardFlowViewUITests.m └── Info.plist └── README.md /HQCardFlowView.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 7A2846982106C7E5001298AB /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7A2846972106C7E5001298AB /* AppDelegate.m */; }; 11 | 7A28469B2106C7E5001298AB /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7A28469A2106C7E5001298AB /* ViewController.m */; }; 12 | 7A28469E2106C7E5001298AB /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7A28469C2106C7E5001298AB /* Main.storyboard */; }; 13 | 7A2846A02106C7E6001298AB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7A28469F2106C7E6001298AB /* Assets.xcassets */; }; 14 | 7A2846A32106C7E6001298AB /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7A2846A12106C7E6001298AB /* LaunchScreen.storyboard */; }; 15 | 7A2846A62106C7E6001298AB /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 7A2846A52106C7E6001298AB /* main.m */; }; 16 | 7A2846B02106C7E6001298AB /* HQCardFlowViewTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7A2846AF2106C7E6001298AB /* HQCardFlowViewTests.m */; }; 17 | 7A2846BB2106C7E6001298AB /* HQCardFlowViewUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7A2846BA2106C7E6001298AB /* HQCardFlowViewUITests.m */; }; 18 | 7A2846D12106C86B001298AB /* HQIndexBannerSubview.m in Sources */ = {isa = PBXBuildFile; fileRef = 7A2846D02106C86B001298AB /* HQIndexBannerSubview.m */; }; 19 | 7A2846D42106C87C001298AB /* HQFlowView.m in Sources */ = {isa = PBXBuildFile; fileRef = 7A2846D32106C87C001298AB /* HQFlowView.m */; }; 20 | 7A2846DA2106D047001298AB /* HQImagePageControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 7A2846D92106D047001298AB /* HQImagePageControl.m */; }; 21 | 7AA4DA6F216C90FB0001696A /* 20180724141023415.gif in Resources */ = {isa = PBXBuildFile; fileRef = 7AA4DA6E216C90FB0001696A /* 20180724141023415.gif */; }; 22 | /* End PBXBuildFile section */ 23 | 24 | /* Begin PBXContainerItemProxy section */ 25 | 7A2846AC2106C7E6001298AB /* PBXContainerItemProxy */ = { 26 | isa = PBXContainerItemProxy; 27 | containerPortal = 7A28468B2106C7E5001298AB /* Project object */; 28 | proxyType = 1; 29 | remoteGlobalIDString = 7A2846922106C7E5001298AB; 30 | remoteInfo = HQCardFlowView; 31 | }; 32 | 7A2846B72106C7E6001298AB /* PBXContainerItemProxy */ = { 33 | isa = PBXContainerItemProxy; 34 | containerPortal = 7A28468B2106C7E5001298AB /* Project object */; 35 | proxyType = 1; 36 | remoteGlobalIDString = 7A2846922106C7E5001298AB; 37 | remoteInfo = HQCardFlowView; 38 | }; 39 | /* End PBXContainerItemProxy section */ 40 | 41 | /* Begin PBXFileReference section */ 42 | 7A2846932106C7E5001298AB /* HQCardFlowView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HQCardFlowView.app; sourceTree = BUILT_PRODUCTS_DIR; }; 43 | 7A2846962106C7E5001298AB /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 44 | 7A2846972106C7E5001298AB /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 45 | 7A2846992106C7E5001298AB /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 46 | 7A28469A2106C7E5001298AB /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 47 | 7A28469D2106C7E5001298AB /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 48 | 7A28469F2106C7E6001298AB /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 49 | 7A2846A22106C7E6001298AB /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 50 | 7A2846A42106C7E6001298AB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 51 | 7A2846A52106C7E6001298AB /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 52 | 7A2846AB2106C7E6001298AB /* HQCardFlowViewTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = HQCardFlowViewTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 53 | 7A2846AF2106C7E6001298AB /* HQCardFlowViewTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HQCardFlowViewTests.m; sourceTree = ""; }; 54 | 7A2846B12106C7E6001298AB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 55 | 7A2846B62106C7E6001298AB /* HQCardFlowViewUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = HQCardFlowViewUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 56 | 7A2846BA2106C7E6001298AB /* HQCardFlowViewUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HQCardFlowViewUITests.m; sourceTree = ""; }; 57 | 7A2846BC2106C7E6001298AB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 58 | 7A2846CF2106C86B001298AB /* HQIndexBannerSubview.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HQIndexBannerSubview.h; sourceTree = ""; }; 59 | 7A2846D02106C86B001298AB /* HQIndexBannerSubview.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HQIndexBannerSubview.m; sourceTree = ""; }; 60 | 7A2846D22106C87C001298AB /* HQFlowView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HQFlowView.h; sourceTree = ""; }; 61 | 7A2846D32106C87C001298AB /* HQFlowView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HQFlowView.m; sourceTree = ""; }; 62 | 7A2846D82106D047001298AB /* HQImagePageControl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HQImagePageControl.h; sourceTree = ""; }; 63 | 7A2846D92106D047001298AB /* HQImagePageControl.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HQImagePageControl.m; sourceTree = ""; }; 64 | 7AA4DA6E216C90FB0001696A /* 20180724141023415.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = 20180724141023415.gif; sourceTree = ""; }; 65 | /* End PBXFileReference section */ 66 | 67 | /* Begin PBXFrameworksBuildPhase section */ 68 | 7A2846902106C7E5001298AB /* Frameworks */ = { 69 | isa = PBXFrameworksBuildPhase; 70 | buildActionMask = 2147483647; 71 | files = ( 72 | ); 73 | runOnlyForDeploymentPostprocessing = 0; 74 | }; 75 | 7A2846A82106C7E6001298AB /* Frameworks */ = { 76 | isa = PBXFrameworksBuildPhase; 77 | buildActionMask = 2147483647; 78 | files = ( 79 | ); 80 | runOnlyForDeploymentPostprocessing = 0; 81 | }; 82 | 7A2846B32106C7E6001298AB /* Frameworks */ = { 83 | isa = PBXFrameworksBuildPhase; 84 | buildActionMask = 2147483647; 85 | files = ( 86 | ); 87 | runOnlyForDeploymentPostprocessing = 0; 88 | }; 89 | /* End PBXFrameworksBuildPhase section */ 90 | 91 | /* Begin PBXGroup section */ 92 | 7A28468A2106C7E5001298AB = { 93 | isa = PBXGroup; 94 | children = ( 95 | 7A2846952106C7E5001298AB /* HQCardFlowView */, 96 | 7A2846AE2106C7E6001298AB /* HQCardFlowViewTests */, 97 | 7A2846B92106C7E6001298AB /* HQCardFlowViewUITests */, 98 | 7A2846942106C7E5001298AB /* Products */, 99 | ); 100 | sourceTree = ""; 101 | }; 102 | 7A2846942106C7E5001298AB /* Products */ = { 103 | isa = PBXGroup; 104 | children = ( 105 | 7A2846932106C7E5001298AB /* HQCardFlowView.app */, 106 | 7A2846AB2106C7E6001298AB /* HQCardFlowViewTests.xctest */, 107 | 7A2846B62106C7E6001298AB /* HQCardFlowViewUITests.xctest */, 108 | ); 109 | name = Products; 110 | sourceTree = ""; 111 | }; 112 | 7A2846952106C7E5001298AB /* HQCardFlowView */ = { 113 | isa = PBXGroup; 114 | children = ( 115 | 7A2846C82106C825001298AB /* HQFlowView */, 116 | 7A2846962106C7E5001298AB /* AppDelegate.h */, 117 | 7A2846972106C7E5001298AB /* AppDelegate.m */, 118 | 7A2846992106C7E5001298AB /* ViewController.h */, 119 | 7A28469A2106C7E5001298AB /* ViewController.m */, 120 | 7AA4DA6E216C90FB0001696A /* 20180724141023415.gif */, 121 | 7A28469C2106C7E5001298AB /* Main.storyboard */, 122 | 7A28469F2106C7E6001298AB /* Assets.xcassets */, 123 | 7A2846A12106C7E6001298AB /* LaunchScreen.storyboard */, 124 | 7A2846A42106C7E6001298AB /* Info.plist */, 125 | 7A2846A52106C7E6001298AB /* main.m */, 126 | ); 127 | path = HQCardFlowView; 128 | sourceTree = ""; 129 | }; 130 | 7A2846AE2106C7E6001298AB /* HQCardFlowViewTests */ = { 131 | isa = PBXGroup; 132 | children = ( 133 | 7A2846AF2106C7E6001298AB /* HQCardFlowViewTests.m */, 134 | 7A2846B12106C7E6001298AB /* Info.plist */, 135 | ); 136 | path = HQCardFlowViewTests; 137 | sourceTree = ""; 138 | }; 139 | 7A2846B92106C7E6001298AB /* HQCardFlowViewUITests */ = { 140 | isa = PBXGroup; 141 | children = ( 142 | 7A2846BA2106C7E6001298AB /* HQCardFlowViewUITests.m */, 143 | 7A2846BC2106C7E6001298AB /* Info.plist */, 144 | ); 145 | path = HQCardFlowViewUITests; 146 | sourceTree = ""; 147 | }; 148 | 7A2846C82106C825001298AB /* HQFlowView */ = { 149 | isa = PBXGroup; 150 | children = ( 151 | 7A2846CF2106C86B001298AB /* HQIndexBannerSubview.h */, 152 | 7A2846D02106C86B001298AB /* HQIndexBannerSubview.m */, 153 | 7A2846D22106C87C001298AB /* HQFlowView.h */, 154 | 7A2846D32106C87C001298AB /* HQFlowView.m */, 155 | 7A2846D82106D047001298AB /* HQImagePageControl.h */, 156 | 7A2846D92106D047001298AB /* HQImagePageControl.m */, 157 | ); 158 | path = HQFlowView; 159 | sourceTree = ""; 160 | }; 161 | /* End PBXGroup section */ 162 | 163 | /* Begin PBXNativeTarget section */ 164 | 7A2846922106C7E5001298AB /* HQCardFlowView */ = { 165 | isa = PBXNativeTarget; 166 | buildConfigurationList = 7A2846BF2106C7E6001298AB /* Build configuration list for PBXNativeTarget "HQCardFlowView" */; 167 | buildPhases = ( 168 | 7A28468F2106C7E5001298AB /* Sources */, 169 | 7A2846902106C7E5001298AB /* Frameworks */, 170 | 7A2846912106C7E5001298AB /* Resources */, 171 | ); 172 | buildRules = ( 173 | ); 174 | dependencies = ( 175 | ); 176 | name = HQCardFlowView; 177 | productName = HQCardFlowView; 178 | productReference = 7A2846932106C7E5001298AB /* HQCardFlowView.app */; 179 | productType = "com.apple.product-type.application"; 180 | }; 181 | 7A2846AA2106C7E6001298AB /* HQCardFlowViewTests */ = { 182 | isa = PBXNativeTarget; 183 | buildConfigurationList = 7A2846C22106C7E6001298AB /* Build configuration list for PBXNativeTarget "HQCardFlowViewTests" */; 184 | buildPhases = ( 185 | 7A2846A72106C7E6001298AB /* Sources */, 186 | 7A2846A82106C7E6001298AB /* Frameworks */, 187 | 7A2846A92106C7E6001298AB /* Resources */, 188 | ); 189 | buildRules = ( 190 | ); 191 | dependencies = ( 192 | 7A2846AD2106C7E6001298AB /* PBXTargetDependency */, 193 | ); 194 | name = HQCardFlowViewTests; 195 | productName = HQCardFlowViewTests; 196 | productReference = 7A2846AB2106C7E6001298AB /* HQCardFlowViewTests.xctest */; 197 | productType = "com.apple.product-type.bundle.unit-test"; 198 | }; 199 | 7A2846B52106C7E6001298AB /* HQCardFlowViewUITests */ = { 200 | isa = PBXNativeTarget; 201 | buildConfigurationList = 7A2846C52106C7E6001298AB /* Build configuration list for PBXNativeTarget "HQCardFlowViewUITests" */; 202 | buildPhases = ( 203 | 7A2846B22106C7E6001298AB /* Sources */, 204 | 7A2846B32106C7E6001298AB /* Frameworks */, 205 | 7A2846B42106C7E6001298AB /* Resources */, 206 | ); 207 | buildRules = ( 208 | ); 209 | dependencies = ( 210 | 7A2846B82106C7E6001298AB /* PBXTargetDependency */, 211 | ); 212 | name = HQCardFlowViewUITests; 213 | productName = HQCardFlowViewUITests; 214 | productReference = 7A2846B62106C7E6001298AB /* HQCardFlowViewUITests.xctest */; 215 | productType = "com.apple.product-type.bundle.ui-testing"; 216 | }; 217 | /* End PBXNativeTarget section */ 218 | 219 | /* Begin PBXProject section */ 220 | 7A28468B2106C7E5001298AB /* Project object */ = { 221 | isa = PBXProject; 222 | attributes = { 223 | LastUpgradeCheck = 0940; 224 | ORGANIZATIONNAME = HQ; 225 | TargetAttributes = { 226 | 7A2846922106C7E5001298AB = { 227 | CreatedOnToolsVersion = 9.4; 228 | }; 229 | 7A2846AA2106C7E6001298AB = { 230 | CreatedOnToolsVersion = 9.4; 231 | TestTargetID = 7A2846922106C7E5001298AB; 232 | }; 233 | 7A2846B52106C7E6001298AB = { 234 | CreatedOnToolsVersion = 9.4; 235 | TestTargetID = 7A2846922106C7E5001298AB; 236 | }; 237 | }; 238 | }; 239 | buildConfigurationList = 7A28468E2106C7E5001298AB /* Build configuration list for PBXProject "HQCardFlowView" */; 240 | compatibilityVersion = "Xcode 9.3"; 241 | developmentRegion = en; 242 | hasScannedForEncodings = 0; 243 | knownRegions = ( 244 | en, 245 | Base, 246 | ); 247 | mainGroup = 7A28468A2106C7E5001298AB; 248 | productRefGroup = 7A2846942106C7E5001298AB /* Products */; 249 | projectDirPath = ""; 250 | projectRoot = ""; 251 | targets = ( 252 | 7A2846922106C7E5001298AB /* HQCardFlowView */, 253 | 7A2846AA2106C7E6001298AB /* HQCardFlowViewTests */, 254 | 7A2846B52106C7E6001298AB /* HQCardFlowViewUITests */, 255 | ); 256 | }; 257 | /* End PBXProject section */ 258 | 259 | /* Begin PBXResourcesBuildPhase section */ 260 | 7A2846912106C7E5001298AB /* Resources */ = { 261 | isa = PBXResourcesBuildPhase; 262 | buildActionMask = 2147483647; 263 | files = ( 264 | 7A2846A32106C7E6001298AB /* LaunchScreen.storyboard in Resources */, 265 | 7A2846A02106C7E6001298AB /* Assets.xcassets in Resources */, 266 | 7AA4DA6F216C90FB0001696A /* 20180724141023415.gif in Resources */, 267 | 7A28469E2106C7E5001298AB /* Main.storyboard in Resources */, 268 | ); 269 | runOnlyForDeploymentPostprocessing = 0; 270 | }; 271 | 7A2846A92106C7E6001298AB /* Resources */ = { 272 | isa = PBXResourcesBuildPhase; 273 | buildActionMask = 2147483647; 274 | files = ( 275 | ); 276 | runOnlyForDeploymentPostprocessing = 0; 277 | }; 278 | 7A2846B42106C7E6001298AB /* Resources */ = { 279 | isa = PBXResourcesBuildPhase; 280 | buildActionMask = 2147483647; 281 | files = ( 282 | ); 283 | runOnlyForDeploymentPostprocessing = 0; 284 | }; 285 | /* End PBXResourcesBuildPhase section */ 286 | 287 | /* Begin PBXSourcesBuildPhase section */ 288 | 7A28468F2106C7E5001298AB /* Sources */ = { 289 | isa = PBXSourcesBuildPhase; 290 | buildActionMask = 2147483647; 291 | files = ( 292 | 7A28469B2106C7E5001298AB /* ViewController.m in Sources */, 293 | 7A2846DA2106D047001298AB /* HQImagePageControl.m in Sources */, 294 | 7A2846D12106C86B001298AB /* HQIndexBannerSubview.m in Sources */, 295 | 7A2846A62106C7E6001298AB /* main.m in Sources */, 296 | 7A2846982106C7E5001298AB /* AppDelegate.m in Sources */, 297 | 7A2846D42106C87C001298AB /* HQFlowView.m in Sources */, 298 | ); 299 | runOnlyForDeploymentPostprocessing = 0; 300 | }; 301 | 7A2846A72106C7E6001298AB /* Sources */ = { 302 | isa = PBXSourcesBuildPhase; 303 | buildActionMask = 2147483647; 304 | files = ( 305 | 7A2846B02106C7E6001298AB /* HQCardFlowViewTests.m in Sources */, 306 | ); 307 | runOnlyForDeploymentPostprocessing = 0; 308 | }; 309 | 7A2846B22106C7E6001298AB /* Sources */ = { 310 | isa = PBXSourcesBuildPhase; 311 | buildActionMask = 2147483647; 312 | files = ( 313 | 7A2846BB2106C7E6001298AB /* HQCardFlowViewUITests.m in Sources */, 314 | ); 315 | runOnlyForDeploymentPostprocessing = 0; 316 | }; 317 | /* End PBXSourcesBuildPhase section */ 318 | 319 | /* Begin PBXTargetDependency section */ 320 | 7A2846AD2106C7E6001298AB /* PBXTargetDependency */ = { 321 | isa = PBXTargetDependency; 322 | target = 7A2846922106C7E5001298AB /* HQCardFlowView */; 323 | targetProxy = 7A2846AC2106C7E6001298AB /* PBXContainerItemProxy */; 324 | }; 325 | 7A2846B82106C7E6001298AB /* PBXTargetDependency */ = { 326 | isa = PBXTargetDependency; 327 | target = 7A2846922106C7E5001298AB /* HQCardFlowView */; 328 | targetProxy = 7A2846B72106C7E6001298AB /* PBXContainerItemProxy */; 329 | }; 330 | /* End PBXTargetDependency section */ 331 | 332 | /* Begin PBXVariantGroup section */ 333 | 7A28469C2106C7E5001298AB /* Main.storyboard */ = { 334 | isa = PBXVariantGroup; 335 | children = ( 336 | 7A28469D2106C7E5001298AB /* Base */, 337 | ); 338 | name = Main.storyboard; 339 | sourceTree = ""; 340 | }; 341 | 7A2846A12106C7E6001298AB /* LaunchScreen.storyboard */ = { 342 | isa = PBXVariantGroup; 343 | children = ( 344 | 7A2846A22106C7E6001298AB /* Base */, 345 | ); 346 | name = LaunchScreen.storyboard; 347 | sourceTree = ""; 348 | }; 349 | /* End PBXVariantGroup section */ 350 | 351 | /* Begin XCBuildConfiguration section */ 352 | 7A2846BD2106C7E6001298AB /* Debug */ = { 353 | isa = XCBuildConfiguration; 354 | buildSettings = { 355 | ALWAYS_SEARCH_USER_PATHS = NO; 356 | CLANG_ANALYZER_NONNULL = YES; 357 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 358 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 359 | CLANG_CXX_LIBRARY = "libc++"; 360 | CLANG_ENABLE_MODULES = YES; 361 | CLANG_ENABLE_OBJC_ARC = YES; 362 | CLANG_ENABLE_OBJC_WEAK = YES; 363 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 364 | CLANG_WARN_BOOL_CONVERSION = YES; 365 | CLANG_WARN_COMMA = YES; 366 | CLANG_WARN_CONSTANT_CONVERSION = YES; 367 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 368 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 369 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 370 | CLANG_WARN_EMPTY_BODY = YES; 371 | CLANG_WARN_ENUM_CONVERSION = YES; 372 | CLANG_WARN_INFINITE_RECURSION = YES; 373 | CLANG_WARN_INT_CONVERSION = YES; 374 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 375 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 376 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 377 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 378 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 379 | CLANG_WARN_STRICT_PROTOTYPES = YES; 380 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 381 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 382 | CLANG_WARN_UNREACHABLE_CODE = YES; 383 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 384 | CODE_SIGN_IDENTITY = "iPhone Developer"; 385 | COPY_PHASE_STRIP = NO; 386 | DEBUG_INFORMATION_FORMAT = dwarf; 387 | ENABLE_STRICT_OBJC_MSGSEND = YES; 388 | ENABLE_TESTABILITY = YES; 389 | GCC_C_LANGUAGE_STANDARD = gnu11; 390 | GCC_DYNAMIC_NO_PIC = NO; 391 | GCC_NO_COMMON_BLOCKS = YES; 392 | GCC_OPTIMIZATION_LEVEL = 0; 393 | GCC_PREPROCESSOR_DEFINITIONS = ( 394 | "DEBUG=1", 395 | "$(inherited)", 396 | ); 397 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 398 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 399 | GCC_WARN_UNDECLARED_SELECTOR = YES; 400 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 401 | GCC_WARN_UNUSED_FUNCTION = YES; 402 | GCC_WARN_UNUSED_VARIABLE = YES; 403 | IPHONEOS_DEPLOYMENT_TARGET = 11.4; 404 | MTL_ENABLE_DEBUG_INFO = YES; 405 | ONLY_ACTIVE_ARCH = YES; 406 | SDKROOT = iphoneos; 407 | }; 408 | name = Debug; 409 | }; 410 | 7A2846BE2106C7E6001298AB /* Release */ = { 411 | isa = XCBuildConfiguration; 412 | buildSettings = { 413 | ALWAYS_SEARCH_USER_PATHS = NO; 414 | CLANG_ANALYZER_NONNULL = YES; 415 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 416 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 417 | CLANG_CXX_LIBRARY = "libc++"; 418 | CLANG_ENABLE_MODULES = YES; 419 | CLANG_ENABLE_OBJC_ARC = YES; 420 | CLANG_ENABLE_OBJC_WEAK = YES; 421 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 422 | CLANG_WARN_BOOL_CONVERSION = YES; 423 | CLANG_WARN_COMMA = YES; 424 | CLANG_WARN_CONSTANT_CONVERSION = YES; 425 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 426 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 427 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 428 | CLANG_WARN_EMPTY_BODY = YES; 429 | CLANG_WARN_ENUM_CONVERSION = YES; 430 | CLANG_WARN_INFINITE_RECURSION = YES; 431 | CLANG_WARN_INT_CONVERSION = YES; 432 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 433 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 434 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 435 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 436 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 437 | CLANG_WARN_STRICT_PROTOTYPES = YES; 438 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 439 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 440 | CLANG_WARN_UNREACHABLE_CODE = YES; 441 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 442 | CODE_SIGN_IDENTITY = "iPhone Developer"; 443 | COPY_PHASE_STRIP = NO; 444 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 445 | ENABLE_NS_ASSERTIONS = NO; 446 | ENABLE_STRICT_OBJC_MSGSEND = YES; 447 | GCC_C_LANGUAGE_STANDARD = gnu11; 448 | GCC_NO_COMMON_BLOCKS = YES; 449 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 450 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 451 | GCC_WARN_UNDECLARED_SELECTOR = YES; 452 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 453 | GCC_WARN_UNUSED_FUNCTION = YES; 454 | GCC_WARN_UNUSED_VARIABLE = YES; 455 | IPHONEOS_DEPLOYMENT_TARGET = 11.4; 456 | MTL_ENABLE_DEBUG_INFO = NO; 457 | SDKROOT = iphoneos; 458 | VALIDATE_PRODUCT = YES; 459 | }; 460 | name = Release; 461 | }; 462 | 7A2846C02106C7E6001298AB /* Debug */ = { 463 | isa = XCBuildConfiguration; 464 | buildSettings = { 465 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 466 | CODE_SIGN_STYLE = Automatic; 467 | INFOPLIST_FILE = HQCardFlowView/Info.plist; 468 | LD_RUNPATH_SEARCH_PATHS = ( 469 | "$(inherited)", 470 | "@executable_path/Frameworks", 471 | ); 472 | PRODUCT_BUNDLE_IDENTIFIER = JunKai.HQCardFlowView; 473 | PRODUCT_NAME = "$(TARGET_NAME)"; 474 | TARGETED_DEVICE_FAMILY = "1,2"; 475 | }; 476 | name = Debug; 477 | }; 478 | 7A2846C12106C7E6001298AB /* Release */ = { 479 | isa = XCBuildConfiguration; 480 | buildSettings = { 481 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 482 | CODE_SIGN_STYLE = Automatic; 483 | INFOPLIST_FILE = HQCardFlowView/Info.plist; 484 | LD_RUNPATH_SEARCH_PATHS = ( 485 | "$(inherited)", 486 | "@executable_path/Frameworks", 487 | ); 488 | PRODUCT_BUNDLE_IDENTIFIER = JunKai.HQCardFlowView; 489 | PRODUCT_NAME = "$(TARGET_NAME)"; 490 | TARGETED_DEVICE_FAMILY = "1,2"; 491 | }; 492 | name = Release; 493 | }; 494 | 7A2846C32106C7E6001298AB /* Debug */ = { 495 | isa = XCBuildConfiguration; 496 | buildSettings = { 497 | BUNDLE_LOADER = "$(TEST_HOST)"; 498 | CODE_SIGN_STYLE = Automatic; 499 | INFOPLIST_FILE = HQCardFlowViewTests/Info.plist; 500 | LD_RUNPATH_SEARCH_PATHS = ( 501 | "$(inherited)", 502 | "@executable_path/Frameworks", 503 | "@loader_path/Frameworks", 504 | ); 505 | PRODUCT_BUNDLE_IDENTIFIER = JunKai.HQCardFlowViewTests; 506 | PRODUCT_NAME = "$(TARGET_NAME)"; 507 | TARGETED_DEVICE_FAMILY = "1,2"; 508 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/HQCardFlowView.app/HQCardFlowView"; 509 | }; 510 | name = Debug; 511 | }; 512 | 7A2846C42106C7E6001298AB /* Release */ = { 513 | isa = XCBuildConfiguration; 514 | buildSettings = { 515 | BUNDLE_LOADER = "$(TEST_HOST)"; 516 | CODE_SIGN_STYLE = Automatic; 517 | INFOPLIST_FILE = HQCardFlowViewTests/Info.plist; 518 | LD_RUNPATH_SEARCH_PATHS = ( 519 | "$(inherited)", 520 | "@executable_path/Frameworks", 521 | "@loader_path/Frameworks", 522 | ); 523 | PRODUCT_BUNDLE_IDENTIFIER = JunKai.HQCardFlowViewTests; 524 | PRODUCT_NAME = "$(TARGET_NAME)"; 525 | TARGETED_DEVICE_FAMILY = "1,2"; 526 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/HQCardFlowView.app/HQCardFlowView"; 527 | }; 528 | name = Release; 529 | }; 530 | 7A2846C62106C7E6001298AB /* Debug */ = { 531 | isa = XCBuildConfiguration; 532 | buildSettings = { 533 | CODE_SIGN_STYLE = Automatic; 534 | INFOPLIST_FILE = HQCardFlowViewUITests/Info.plist; 535 | LD_RUNPATH_SEARCH_PATHS = ( 536 | "$(inherited)", 537 | "@executable_path/Frameworks", 538 | "@loader_path/Frameworks", 539 | ); 540 | PRODUCT_BUNDLE_IDENTIFIER = JunKai.HQCardFlowViewUITests; 541 | PRODUCT_NAME = "$(TARGET_NAME)"; 542 | TARGETED_DEVICE_FAMILY = "1,2"; 543 | TEST_TARGET_NAME = HQCardFlowView; 544 | }; 545 | name = Debug; 546 | }; 547 | 7A2846C72106C7E6001298AB /* Release */ = { 548 | isa = XCBuildConfiguration; 549 | buildSettings = { 550 | CODE_SIGN_STYLE = Automatic; 551 | INFOPLIST_FILE = HQCardFlowViewUITests/Info.plist; 552 | LD_RUNPATH_SEARCH_PATHS = ( 553 | "$(inherited)", 554 | "@executable_path/Frameworks", 555 | "@loader_path/Frameworks", 556 | ); 557 | PRODUCT_BUNDLE_IDENTIFIER = JunKai.HQCardFlowViewUITests; 558 | PRODUCT_NAME = "$(TARGET_NAME)"; 559 | TARGETED_DEVICE_FAMILY = "1,2"; 560 | TEST_TARGET_NAME = HQCardFlowView; 561 | }; 562 | name = Release; 563 | }; 564 | /* End XCBuildConfiguration section */ 565 | 566 | /* Begin XCConfigurationList section */ 567 | 7A28468E2106C7E5001298AB /* Build configuration list for PBXProject "HQCardFlowView" */ = { 568 | isa = XCConfigurationList; 569 | buildConfigurations = ( 570 | 7A2846BD2106C7E6001298AB /* Debug */, 571 | 7A2846BE2106C7E6001298AB /* Release */, 572 | ); 573 | defaultConfigurationIsVisible = 0; 574 | defaultConfigurationName = Release; 575 | }; 576 | 7A2846BF2106C7E6001298AB /* Build configuration list for PBXNativeTarget "HQCardFlowView" */ = { 577 | isa = XCConfigurationList; 578 | buildConfigurations = ( 579 | 7A2846C02106C7E6001298AB /* Debug */, 580 | 7A2846C12106C7E6001298AB /* Release */, 581 | ); 582 | defaultConfigurationIsVisible = 0; 583 | defaultConfigurationName = Release; 584 | }; 585 | 7A2846C22106C7E6001298AB /* Build configuration list for PBXNativeTarget "HQCardFlowViewTests" */ = { 586 | isa = XCConfigurationList; 587 | buildConfigurations = ( 588 | 7A2846C32106C7E6001298AB /* Debug */, 589 | 7A2846C42106C7E6001298AB /* Release */, 590 | ); 591 | defaultConfigurationIsVisible = 0; 592 | defaultConfigurationName = Release; 593 | }; 594 | 7A2846C52106C7E6001298AB /* Build configuration list for PBXNativeTarget "HQCardFlowViewUITests" */ = { 595 | isa = XCConfigurationList; 596 | buildConfigurations = ( 597 | 7A2846C62106C7E6001298AB /* Debug */, 598 | 7A2846C72106C7E6001298AB /* Release */, 599 | ); 600 | defaultConfigurationIsVisible = 0; 601 | defaultConfigurationName = Release; 602 | }; 603 | /* End XCConfigurationList section */ 604 | }; 605 | rootObject = 7A28468B2106C7E5001298AB /* Project object */; 606 | } 607 | -------------------------------------------------------------------------------- /HQCardFlowView.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /HQCardFlowView.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /HQCardFlowView.xcodeproj/project.xcworkspace/xcuserdata/jkdzkj.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanQiGod/HQCardFlowView/36bc5ce9cd9124cde95c78a20341b4f5af22b45c/HQCardFlowView.xcodeproj/project.xcworkspace/xcuserdata/jkdzkj.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /HQCardFlowView.xcodeproj/xcuserdata/jkdzkj.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | HQCardFlowView.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /HQCardFlowView/20180724141023415.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanQiGod/HQCardFlowView/36bc5ce9cd9124cde95c78a20341b4f5af22b45c/HQCardFlowView/20180724141023415.gif -------------------------------------------------------------------------------- /HQCardFlowView/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // HQCardFlowView 4 | // 5 | // Created by Mr_Han on 2018/7/24. 6 | // Copyright © 2018年 Mr_Han. All rights reserved. 7 | // CSDN 8 | // GitHub 9 | // 10 | 11 | #import 12 | 13 | @interface AppDelegate : UIResponder 14 | 15 | @property (strong, nonatomic) UIWindow *window; 16 | 17 | 18 | @end 19 | 20 | -------------------------------------------------------------------------------- /HQCardFlowView/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // HQCardFlowView 4 | // 5 | // Created by Mr_Han on 2018/7/24. 6 | // Copyright © 2018年 Mr_Han. All rights reserved. 7 | // CSDN 8 | // GitHub 9 | // 10 | 11 | #import "AppDelegate.h" 12 | 13 | @interface AppDelegate () 14 | 15 | @end 16 | 17 | @implementation AppDelegate 18 | 19 | 20 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 21 | // Override point for customization after application launch. 22 | return YES; 23 | } 24 | 25 | 26 | - (void)applicationWillResignActive:(UIApplication *)application { 27 | // 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. 28 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 29 | } 30 | 31 | 32 | - (void)applicationDidEnterBackground:(UIApplication *)application { 33 | // 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. 34 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 35 | } 36 | 37 | 38 | - (void)applicationWillEnterForeground:(UIApplication *)application { 39 | // 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. 40 | } 41 | 42 | 43 | - (void)applicationDidBecomeActive:(UIApplication *)application { 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 | 48 | - (void)applicationWillTerminate:(UIApplication *)application { 49 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 50 | } 51 | 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /HQCardFlowView/Assets.xcassets/1.imageset/1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanQiGod/HQCardFlowView/36bc5ce9cd9124cde95c78a20341b4f5af22b45c/HQCardFlowView/Assets.xcassets/1.imageset/1.jpeg -------------------------------------------------------------------------------- /HQCardFlowView/Assets.xcassets/1.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "1.jpeg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /HQCardFlowView/Assets.xcassets/22.imageset/22.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanQiGod/HQCardFlowView/36bc5ce9cd9124cde95c78a20341b4f5af22b45c/HQCardFlowView/Assets.xcassets/22.imageset/22.jpeg -------------------------------------------------------------------------------- /HQCardFlowView/Assets.xcassets/22.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "22.jpeg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /HQCardFlowView/Assets.xcassets/33.imageset/33.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanQiGod/HQCardFlowView/36bc5ce9cd9124cde95c78a20341b4f5af22b45c/HQCardFlowView/Assets.xcassets/33.imageset/33.jpeg -------------------------------------------------------------------------------- /HQCardFlowView/Assets.xcassets/33.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "33.jpeg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /HQCardFlowView/Assets.xcassets/44.imageset/44.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanQiGod/HQCardFlowView/36bc5ce9cd9124cde95c78a20341b4f5af22b45c/HQCardFlowView/Assets.xcassets/44.imageset/44.jpeg -------------------------------------------------------------------------------- /HQCardFlowView/Assets.xcassets/44.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "44.jpeg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /HQCardFlowView/Assets.xcassets/55.imageset/55.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanQiGod/HQCardFlowView/36bc5ce9cd9124cde95c78a20341b4f5af22b45c/HQCardFlowView/Assets.xcassets/55.imageset/55.jpeg -------------------------------------------------------------------------------- /HQCardFlowView/Assets.xcassets/55.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "55.jpeg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /HQCardFlowView/Assets.xcassets/66.imageset/66.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanQiGod/HQCardFlowView/36bc5ce9cd9124cde95c78a20341b4f5af22b45c/HQCardFlowView/Assets.xcassets/66.imageset/66.jpeg -------------------------------------------------------------------------------- /HQCardFlowView/Assets.xcassets/66.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "66.jpeg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /HQCardFlowView/Assets.xcassets/77.imageset/77.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanQiGod/HQCardFlowView/36bc5ce9cd9124cde95c78a20341b4f5af22b45c/HQCardFlowView/Assets.xcassets/77.imageset/77.jpeg -------------------------------------------------------------------------------- /HQCardFlowView/Assets.xcassets/77.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "77.jpeg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /HQCardFlowView/Assets.xcassets/88.imageset/88.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanQiGod/HQCardFlowView/36bc5ce9cd9124cde95c78a20341b4f5af22b45c/HQCardFlowView/Assets.xcassets/88.imageset/88.jpeg -------------------------------------------------------------------------------- /HQCardFlowView/Assets.xcassets/88.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "88.jpeg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /HQCardFlowView/Assets.xcassets/99.imageset/99.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanQiGod/HQCardFlowView/36bc5ce9cd9124cde95c78a20341b4f5af22b45c/HQCardFlowView/Assets.xcassets/99.imageset/99.jpeg -------------------------------------------------------------------------------- /HQCardFlowView/Assets.xcassets/99.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "99.jpeg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /HQCardFlowView/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 | } -------------------------------------------------------------------------------- /HQCardFlowView/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /HQCardFlowView/Assets.xcassets/icon_pageWidget.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "icon_pageWidget@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "icon_pageWidget@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /HQCardFlowView/Assets.xcassets/icon_pageWidget.imageset/icon_pageWidget@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanQiGod/HQCardFlowView/36bc5ce9cd9124cde95c78a20341b4f5af22b45c/HQCardFlowView/Assets.xcassets/icon_pageWidget.imageset/icon_pageWidget@2x.png -------------------------------------------------------------------------------- /HQCardFlowView/Assets.xcassets/icon_pageWidget.imageset/icon_pageWidget@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanQiGod/HQCardFlowView/36bc5ce9cd9124cde95c78a20341b4f5af22b45c/HQCardFlowView/Assets.xcassets/icon_pageWidget.imageset/icon_pageWidget@3x.png -------------------------------------------------------------------------------- /HQCardFlowView/Assets.xcassets/icon_pageWidget_sign.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "icon_pageWidget_sign@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "icon_pageWidget_sign@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /HQCardFlowView/Assets.xcassets/icon_pageWidget_sign.imageset/icon_pageWidget_sign@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanQiGod/HQCardFlowView/36bc5ce9cd9124cde95c78a20341b4f5af22b45c/HQCardFlowView/Assets.xcassets/icon_pageWidget_sign.imageset/icon_pageWidget_sign@2x.png -------------------------------------------------------------------------------- /HQCardFlowView/Assets.xcassets/icon_pageWidget_sign.imageset/icon_pageWidget_sign@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HanQiGod/HQCardFlowView/36bc5ce9cd9124cde95c78a20341b4f5af22b45c/HQCardFlowView/Assets.xcassets/icon_pageWidget_sign.imageset/icon_pageWidget_sign@3x.png -------------------------------------------------------------------------------- /HQCardFlowView/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 | -------------------------------------------------------------------------------- /HQCardFlowView/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /HQCardFlowView/HQFlowView/HQFlowView.h: -------------------------------------------------------------------------------- 1 | // 2 | // HQFlowView.h 3 | // HQCardFlowView 4 | // 5 | // Created by Mr_Han on 2018/7/24. 6 | // Copyright © 2018年 Mr_Han. All rights reserved. 7 | // CSDN 8 | // GitHub 9 | // 10 | 11 | #import 12 | #import "HQIndexBannerSubview.h" 13 | 14 | @protocol HQFlowViewDataSource; 15 | @protocol HQFlowViewDelegate; 16 | 17 | /****************************** 18 | 19 | 页面滚动的方向分为横向和纵向 20 | 21 | Version 1.0: 22 | 目的:实现类似于选择电影票的效果,并且实现无限/自动轮播 23 | 24 | 特点:1.无限轮播;2.自动轮播;3.电影票样式的层次感;4.非当前显示view具有缩放和透明的特效 25 | 26 | 问题:考虑到轮播图的数量不会太大,暂时未做重用处理;对设备性能影响不明显,后期版本会考虑添加重用标识模仿tableview的重用 27 | 28 | ******************************/ 29 | 30 | typedef enum{ 31 | HQFlowViewOrientationHorizontal = 0, 32 | HQFlowViewOrientationVertical 33 | }HQFlowViewOrientation; 34 | 35 | @interface HQFlowView : UIView 36 | 37 | /** 38 | * 默认为横向 39 | */ 40 | @property (nonatomic,assign) HQFlowViewOrientation orientation; 41 | 42 | @property (nonatomic, strong) UIScrollView *scrollView; 43 | 44 | @property (nonatomic,assign) BOOL needsReload; 45 | /** 46 | * 总页数 47 | */ 48 | @property (nonatomic,assign) NSInteger pageCount; 49 | 50 | @property (nonatomic,strong) NSMutableArray *cells; 51 | @property (nonatomic,assign) NSRange visibleRange; 52 | /** 53 | * 如果以后需要支持reuseIdentifier,这边就得使用字典类型了 54 | */ 55 | @property (nonatomic,strong) NSMutableArray *reusableCells; 56 | 57 | @property (nonatomic,assign) id dataSource; 58 | @property (nonatomic,assign) id delegate; 59 | 60 | /** 61 | * 指示器 62 | */ 63 | @property (nonatomic,retain) UIPageControl *pageControl; 64 | 65 | /** 66 | * 非当前页的透明比例 67 | */ 68 | @property (nonatomic, assign) CGFloat minimumPageAlpha; 69 | 70 | /** 71 | 左右间距,默认20 72 | */ 73 | @property (nonatomic, assign) CGFloat leftRightMargin; 74 | 75 | /** 76 | 上下间距,默认30 77 | */ 78 | @property (nonatomic, assign) CGFloat topBottomMargin; 79 | 80 | /** 81 | * 是否开启自动滚动,默认为开启 82 | */ 83 | @property (nonatomic, assign) BOOL isOpenAutoScroll; 84 | 85 | /** 86 | * 是否开启无限轮播,默认为开启 87 | */ 88 | @property (nonatomic, assign) BOOL isCarousel; 89 | 90 | /** 91 | * 当前是第几页 92 | */ 93 | @property (nonatomic, assign, readonly) NSInteger currentPageIndex; 94 | 95 | /** 96 | * 定时器 97 | */ 98 | @property (nonatomic, weak) NSTimer *timer; 99 | 100 | /** 101 | * 自动切换视图的时间,默认是5.0 102 | */ 103 | @property (nonatomic, assign) CGFloat autoTime; 104 | 105 | /** 106 | * 原始页数 107 | */ 108 | @property (nonatomic, assign) NSInteger orginPageCount; 109 | 110 | /** 111 | * 刷新视图 112 | */ 113 | - (void)reloadData; 114 | 115 | /** 116 | * 获取可重复使用的Cell 117 | * 118 | * @return <#return value description#> 119 | */ 120 | - (HQIndexBannerSubview *)dequeueReusableCell; 121 | 122 | /** 123 | * 滚动到指定的页面 124 | * 125 | * @param pageNumber <#pageNumber description#> 126 | */ 127 | - (void)scrollToPage:(NSUInteger)pageNumber; 128 | 129 | /** 130 | * 开启定时器,废弃 131 | */ 132 | //- (void)startTimer; 133 | 134 | /** 135 | * 关闭定时器,关闭自动滚动 136 | */ 137 | - (void)stopTimer; 138 | 139 | /** 140 | 调整中间页居中,经常出现滚动卡住一半时调用 141 | */ 142 | - (void)adjustCenterSubview; 143 | 144 | @end 145 | 146 | 147 | @protocol HQFlowViewDelegate 148 | 149 | @optional 150 | /** 151 | * 当前显示cell的Size(中间页显示大小) 152 | * 153 | * @param flowView <#flowView description#> 154 | * 155 | * @return <#return value description#> 156 | */ 157 | - (CGSize)sizeForPageInFlowView:(HQFlowView *)flowView; 158 | 159 | /** 160 | * 滚动到了某一列 161 | * 162 | * @param pageNumber <#pageNumber description#> 163 | * @param flowView <#flowView description#> 164 | */ 165 | - (void)didScrollToPage:(NSInteger)pageNumber inFlowView:(HQFlowView *)flowView; 166 | 167 | /** 168 | * 点击了第几个cell 169 | * 170 | * @param subView 点击的控件 171 | * @param subIndex 点击控件的index 172 | * 173 | * @return <#return value description#> 174 | */ 175 | - (void)didSelectCell:(HQIndexBannerSubview *)subView withSubViewIndex:(NSInteger)subIndex; 176 | 177 | @end 178 | 179 | 180 | @protocol HQFlowViewDataSource 181 | 182 | /** 183 | * 返回显示View的个数 184 | * 185 | * @param flowView <#flowView description#> 186 | * 187 | * @return <#return value description#> 188 | */ 189 | - (NSInteger)numberOfPagesInFlowView:(HQFlowView *)flowView; 190 | 191 | /** 192 | * 给某一列设置属性 193 | * 194 | * @param flowView <#flowView description#> 195 | * @param index <#index description#> 196 | * 197 | * @return <#return value description#> 198 | */ 199 | - (HQIndexBannerSubview *)flowView:(HQFlowView *)flowView cellForPageAtIndex:(NSInteger)index; 200 | 201 | @end 202 | -------------------------------------------------------------------------------- /HQCardFlowView/HQFlowView/HQFlowView.m: -------------------------------------------------------------------------------- 1 | // 2 | // HQFlowView.m 3 | // HQCardFlowView 4 | // 5 | // Created by Mr_Han on 2018/7/24. 6 | // Copyright © 2018年 Mr_Han. All rights reserved. 7 | // CSDN 8 | // GitHub 9 | // 10 | 11 | #import "HQFlowView.h" 12 | 13 | @interface HQFlowView () 14 | 15 | @property (nonatomic, assign, readwrite) NSInteger currentPageIndex; 16 | 17 | /** 18 | * 计时器用到的页数 19 | */ 20 | @property (nonatomic, assign) NSInteger page; 21 | 22 | /** 23 | * 一页的尺寸 24 | */ 25 | @property (nonatomic,assign) CGSize pageSize; 26 | 27 | @end 28 | 29 | //子控制器的类名 30 | static NSString *subviewClassName; 31 | 32 | @implementation HQFlowView 33 | 34 | //////////////////////////////////////////////////////////////////////////////////////////////////// 35 | #pragma mark - 36 | #pragma mark Private Methods 37 | 38 | - (void)initialize { 39 | self.clipsToBounds = YES; 40 | 41 | self.needsReload = YES; 42 | self.pageCount = 0; 43 | self.isOpenAutoScroll = YES; 44 | self.isCarousel = YES; 45 | self.leftRightMargin = 20; 46 | self.topBottomMargin = 30; 47 | _currentPageIndex = 0; 48 | 49 | _minimumPageAlpha = 1.0; 50 | _autoTime = 5.0; 51 | 52 | self.visibleRange = NSMakeRange(0, 0); 53 | 54 | self.reusableCells = [[NSMutableArray alloc] initWithCapacity:0]; 55 | self.cells = [[NSMutableArray alloc] initWithCapacity:0]; 56 | 57 | self.scrollView = [[UIScrollView alloc] initWithFrame:self.bounds]; 58 | self.scrollView.scrollsToTop = NO; 59 | self.scrollView.delegate = self; 60 | self.scrollView.pagingEnabled = YES; 61 | self.scrollView.clipsToBounds = NO; 62 | self.scrollView.showsHorizontalScrollIndicator = NO; 63 | self.scrollView.showsVerticalScrollIndicator = NO; 64 | 65 | subviewClassName = @"HQIndexBannerSubview"; 66 | 67 | [self addSubview:self.scrollView]; 68 | 69 | } 70 | 71 | - (void)setLeftRightMargin:(CGFloat)leftRightMargin { 72 | _leftRightMargin = leftRightMargin * 0.5; 73 | 74 | } 75 | 76 | - (void)setTopBottomMargin:(CGFloat)topBottomMargin { 77 | _topBottomMargin = topBottomMargin * 0.5; 78 | } 79 | 80 | - (void)startTimer { 81 | 82 | if (self.orginPageCount > 1 && self.isOpenAutoScroll && self.isCarousel) { 83 | NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:self.autoTime target:self selector:@selector(autoNextPage) userInfo:nil repeats:YES]; 84 | self.timer = timer; 85 | [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes]; 86 | 87 | } 88 | 89 | } 90 | 91 | - (void)stopTimer { 92 | 93 | if (self.timer) { 94 | [self.timer invalidate]; 95 | self.timer = nil; 96 | } 97 | } 98 | 99 | - (void)adjustCenterSubview { 100 | if (self.isOpenAutoScroll && self.orginPageCount > 0) { 101 | [_scrollView setContentOffset:CGPointMake(_pageSize.width * self.page, 0) animated:NO]; 102 | } 103 | } 104 | 105 | #pragma mark --自动轮播 106 | - (void)autoNextPage { 107 | 108 | self.page ++; 109 | 110 | 111 | 112 | switch (self.orientation) { 113 | case HQFlowViewOrientationHorizontal:{ 114 | 115 | [_scrollView setContentOffset:CGPointMake(self.page * _pageSize.width, 0) animated:YES]; 116 | break; 117 | } 118 | case HQFlowViewOrientationVertical:{ 119 | 120 | [_scrollView setContentOffset:CGPointMake(0, self.page * _pageSize.height) animated:YES]; 121 | 122 | break; 123 | } 124 | default: 125 | break; 126 | } 127 | } 128 | 129 | 130 | - (void)queueReusableCell:(HQIndexBannerSubview *)cell{ 131 | [_reusableCells addObject:cell]; 132 | } 133 | 134 | - (void)removeCellAtIndex:(NSInteger)index{ 135 | HQIndexBannerSubview *cell = [_cells objectAtIndex:index]; 136 | if ((NSObject *)cell == [NSNull null]) { 137 | return; 138 | } 139 | 140 | [self queueReusableCell:cell]; 141 | 142 | if (cell.superview) { 143 | [cell removeFromSuperview]; 144 | } 145 | 146 | [_cells replaceObjectAtIndex:index withObject:[NSNull null]]; 147 | } 148 | 149 | - (void)refreshVisibleCellAppearance{ 150 | 151 | if (_minimumPageAlpha == 1.0 && self.leftRightMargin == 0 && self.topBottomMargin == 0) { 152 | return;//无需更新 153 | } 154 | switch (self.orientation) { 155 | case HQFlowViewOrientationHorizontal:{ 156 | CGFloat offset = _scrollView.contentOffset.x; 157 | 158 | for (NSInteger i = self.visibleRange.location; i < self.visibleRange.location + _visibleRange.length; i++) { 159 | HQIndexBannerSubview *cell = [_cells objectAtIndex:i]; 160 | subviewClassName = NSStringFromClass([cell class]); 161 | CGFloat origin = cell.frame.origin.x; 162 | CGFloat delta = fabs(origin - offset); 163 | 164 | CGRect originCellFrame = CGRectMake(_pageSize.width * i, 0, _pageSize.width, _pageSize.height);//如果没有缩小效果的情况下的本该的Frame 165 | 166 | if (delta < _pageSize.width) { 167 | 168 | cell.coverView.alpha = (delta / _pageSize.width) * _minimumPageAlpha; 169 | 170 | CGFloat leftRightInset = self.leftRightMargin * delta / _pageSize.width; 171 | CGFloat topBottomInset = self.topBottomMargin * delta / _pageSize.width; 172 | 173 | cell.layer.transform = CATransform3DMakeScale((_pageSize.width-leftRightInset*2)/_pageSize.width,(_pageSize.height-topBottomInset*2)/_pageSize.height, 1.0); 174 | cell.frame = UIEdgeInsetsInsetRect(originCellFrame, UIEdgeInsetsMake(topBottomInset, leftRightInset, topBottomInset, leftRightInset)); 175 | 176 | 177 | } else { 178 | cell.coverView.alpha = _minimumPageAlpha; 179 | cell.layer.transform = CATransform3DMakeScale((_pageSize.width-self.leftRightMargin*2)/_pageSize.width,(_pageSize.height-self.topBottomMargin*2)/_pageSize.height, 1.0); 180 | cell.frame = UIEdgeInsetsInsetRect(originCellFrame, UIEdgeInsetsMake(self.topBottomMargin, self.leftRightMargin, self.topBottomMargin, self.leftRightMargin)); 181 | 182 | 183 | } 184 | 185 | } 186 | break; 187 | } 188 | case HQFlowViewOrientationVertical:{ 189 | CGFloat offset = _scrollView.contentOffset.y; 190 | 191 | for (NSInteger i = self.visibleRange.location; i < self.visibleRange.location + _visibleRange.length; i++) { 192 | HQIndexBannerSubview *cell = [_cells objectAtIndex:i]; 193 | subviewClassName = NSStringFromClass([cell class]); 194 | CGFloat origin = cell.frame.origin.y; 195 | CGFloat delta = fabs(origin - offset); 196 | 197 | CGRect originCellFrame = CGRectMake(0, _pageSize.height * i, _pageSize.width, _pageSize.height);//如果没有缩小效果的情况下的本该的Frame 198 | 199 | if (delta < _pageSize.height) { 200 | cell.coverView.alpha = (delta / _pageSize.height) * _minimumPageAlpha; 201 | 202 | CGFloat leftRightInset = self.leftRightMargin * delta / _pageSize.height; 203 | CGFloat topBottomInset = self.topBottomMargin * delta / _pageSize.height; 204 | 205 | cell.layer.transform = CATransform3DMakeScale((_pageSize.width-leftRightInset*2)/_pageSize.width,(_pageSize.height-topBottomInset*2) / _pageSize.height, 1.0); 206 | cell.frame = UIEdgeInsetsInsetRect(originCellFrame, UIEdgeInsetsMake(topBottomInset, leftRightInset, topBottomInset, leftRightInset)); 207 | cell.mainImageView.frame = cell.bounds; 208 | } else { 209 | cell.coverView.alpha = _minimumPageAlpha; 210 | cell.frame = UIEdgeInsetsInsetRect(originCellFrame, UIEdgeInsetsMake(self.topBottomMargin, self.leftRightMargin, self.topBottomMargin, self.leftRightMargin)); 211 | cell.mainImageView.frame = cell.bounds; 212 | } 213 | 214 | } 215 | } 216 | default: 217 | break; 218 | } 219 | 220 | } 221 | 222 | - (void)setPageAtIndex:(NSInteger)pageIndex{ 223 | NSParameterAssert(pageIndex >= 0 && pageIndex < [_cells count]); 224 | 225 | HQIndexBannerSubview *cell = [_cells objectAtIndex:pageIndex]; 226 | 227 | if ((NSObject *)cell == [NSNull null]) { 228 | cell = [_dataSource flowView:self cellForPageAtIndex:pageIndex % self.orginPageCount]; 229 | NSAssert(cell!=nil, @"datasource must not return nil"); 230 | [_cells replaceObjectAtIndex:pageIndex withObject:cell]; 231 | 232 | cell.tag = pageIndex % self.orginPageCount; 233 | [cell setSubviewsWithSuperViewBounds:CGRectMake(0, 0, _pageSize.width, _pageSize.height)]; 234 | 235 | __weak __typeof(self) weakSelf = self; 236 | cell.didSelectCellBlock = ^(NSInteger tag, HQIndexBannerSubview *cell) { 237 | [weakSelf singleCellTapAction:tag withCell:cell]; 238 | }; 239 | 240 | switch (self.orientation) { 241 | case HQFlowViewOrientationHorizontal: 242 | cell.frame = CGRectMake(_pageSize.width * pageIndex, 0, _pageSize.width, _pageSize.height); 243 | break; 244 | case HQFlowViewOrientationVertical: 245 | cell.frame = CGRectMake(0, _pageSize.height * pageIndex, _pageSize.width, _pageSize.height); 246 | break; 247 | default: 248 | break; 249 | } 250 | 251 | if (!cell.superview) { 252 | [_scrollView addSubview:cell]; 253 | } 254 | } 255 | } 256 | 257 | 258 | - (void)setPagesAtContentOffset:(CGPoint)offset{ 259 | //计算_visibleRange 260 | CGPoint startPoint = CGPointMake(offset.x - _scrollView.frame.origin.x, offset.y - _scrollView.frame.origin.y); 261 | CGPoint endPoint = CGPointMake(startPoint.x + self.bounds.size.width, startPoint.y + self.bounds.size.height); 262 | 263 | 264 | switch (self.orientation) { 265 | case HQFlowViewOrientationHorizontal:{ 266 | NSInteger startIndex = 0; 267 | for (int i =0; i < [_cells count]; i++) { 268 | if (_pageSize.width * (i +1) > startPoint.x) { 269 | startIndex = i; 270 | break; 271 | } 272 | } 273 | 274 | NSInteger endIndex = startIndex; 275 | for (NSInteger i = startIndex; i < [_cells count]; i++) { 276 | //如果都不超过则取最后一个 277 | if ((_pageSize.width * (i + 1) < endPoint.x && _pageSize.width * (i + 2) >= endPoint.x) || i+ 2 == [_cells count]) { 278 | endIndex = i + 1;//i+2 是以个数,所以其index需要减去1 279 | break; 280 | } 281 | } 282 | 283 | //可见页分别向前向后扩展一个,提高效率 284 | startIndex = MAX(startIndex - 1, 0); 285 | endIndex = MIN(endIndex + 1, [_cells count] - 1); 286 | 287 | // self.visibleRange.location = startIndex; 288 | // self.visibleRange.length = endIndex - startIndex + 1; 289 | self.visibleRange = NSMakeRange(startIndex, endIndex - startIndex + 1); 290 | for (NSInteger i = startIndex; i <= endIndex; i++) { 291 | [self setPageAtIndex:i]; 292 | } 293 | 294 | for (int i = 0; i < startIndex; i ++) { 295 | [self removeCellAtIndex:i]; 296 | } 297 | 298 | for (NSInteger i = endIndex + 1; i < [_cells count]; i ++) { 299 | [self removeCellAtIndex:i]; 300 | } 301 | break; 302 | } 303 | case HQFlowViewOrientationVertical:{ 304 | NSInteger startIndex = 0; 305 | for (int i =0; i < [_cells count]; i++) { 306 | if (_pageSize.height * (i +1) > startPoint.y) { 307 | startIndex = i; 308 | break; 309 | } 310 | } 311 | 312 | NSInteger endIndex = startIndex; 313 | for (NSInteger i = startIndex; i < [_cells count]; i++) { 314 | //如果都不超过则取最后一个 315 | if ((_pageSize.height * (i + 1) < endPoint.y && _pageSize.height * (i + 2) >= endPoint.y) || i+ 2 == [_cells count]) { 316 | endIndex = i + 1;//i+2 是以个数,所以其index需要减去1 317 | break; 318 | } 319 | } 320 | 321 | //可见页分别向前向后扩展一个,提高效率 322 | startIndex = MAX(startIndex - 1, 0); 323 | endIndex = MIN(endIndex + 1, [_cells count] - 1); 324 | 325 | _visibleRange.location = startIndex; 326 | _visibleRange.length = endIndex - startIndex + 1; 327 | 328 | for (NSInteger i = startIndex; i <= endIndex; i++) { 329 | [self setPageAtIndex:i]; 330 | } 331 | 332 | for (NSInteger i = 0; i < startIndex; i ++) { 333 | [self removeCellAtIndex:i]; 334 | } 335 | 336 | for (NSInteger i = endIndex + 1; i < [_cells count]; i ++) { 337 | [self removeCellAtIndex:i]; 338 | } 339 | break; 340 | } 341 | default: 342 | break; 343 | } 344 | 345 | 346 | 347 | } 348 | 349 | 350 | 351 | 352 | //////////////////////////////////////////////////////////////////////////////////////////////////// 353 | #pragma mark - 354 | #pragma mark Override Methods 355 | 356 | - (id)initWithFrame:(CGRect)frame 357 | { 358 | self = [super initWithFrame:frame]; 359 | if (self) 360 | { 361 | [self initialize]; 362 | } 363 | return self; 364 | } 365 | 366 | - (id)initWithCoder:(NSCoder *)aDecoder 367 | { 368 | self = [super initWithCoder:aDecoder]; 369 | if (self) 370 | { 371 | [self initialize]; 372 | } 373 | return self; 374 | } 375 | 376 | 377 | //////////////////////////////////////////////////////////////////////////////////////////////////// 378 | #pragma mark - 379 | #pragma mark JQFlowView API 380 | 381 | - (void)reloadData { 382 | _needsReload = YES; 383 | 384 | //移除所有self.scrollView的子控件 385 | for (UIView *view in self.scrollView.subviews) { 386 | if ([NSStringFromClass(view.class) isEqualToString:subviewClassName] || [view isKindOfClass:[HQIndexBannerSubview class]]) { 387 | [view removeFromSuperview]; 388 | } 389 | } 390 | 391 | [self stopTimer]; 392 | 393 | if (_needsReload) { 394 | //如果需要重新加载数据,则需要清空相关数据全部重新加载 395 | 396 | 397 | //重置pageCount 398 | if (_dataSource && [_dataSource respondsToSelector:@selector(numberOfPagesInFlowView:)]) { 399 | 400 | //原始页数 401 | self.orginPageCount = [_dataSource numberOfPagesInFlowView:self]; 402 | 403 | //总页数 404 | if (self.isCarousel) { 405 | _pageCount = self.orginPageCount == 1 ? 1: [_dataSource numberOfPagesInFlowView:self] * 3; 406 | }else { 407 | _pageCount = self.orginPageCount == 1 ? 1: [_dataSource numberOfPagesInFlowView:self]; 408 | } 409 | 410 | //如果总页数为0,return 411 | if (_pageCount == 0) { 412 | 413 | return; 414 | } 415 | 416 | if (self.pageControl && [self.pageControl respondsToSelector:@selector(setNumberOfPages:)]) { 417 | [self.pageControl setNumberOfPages:self.orginPageCount]; 418 | } 419 | } 420 | 421 | //重置pageWidth 422 | _pageSize = CGSizeMake(self.bounds.size.width - 4 * self.leftRightMargin,(self.bounds.size.width - 4 * self.leftRightMargin) * 9 /16); 423 | if (self.delegate && self.delegate && [self.delegate respondsToSelector:@selector(sizeForPageInFlowView:)]) { 424 | _pageSize = [self.delegate sizeForPageInFlowView:self]; 425 | } 426 | 427 | [_reusableCells removeAllObjects]; 428 | _visibleRange = NSMakeRange(0, 0); 429 | 430 | //填充cells数组 431 | [_cells removeAllObjects]; 432 | for (NSInteger index=0; index<_pageCount; index++) 433 | { 434 | [_cells addObject:[NSNull null]]; 435 | } 436 | 437 | // 重置_scrollView的contentSize 438 | switch (self.orientation) { 439 | case HQFlowViewOrientationHorizontal://横向 440 | _scrollView.frame = CGRectMake(0, 0, _pageSize.width, _pageSize.height); 441 | _scrollView.contentSize = CGSizeMake(_pageSize.width * _pageCount,0); 442 | CGPoint theCenter = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds)); 443 | _scrollView.center = theCenter; 444 | 445 | if (self.orginPageCount > 1) { 446 | 447 | if (self.isCarousel) { 448 | 449 | //滚到第二组 450 | [_scrollView setContentOffset:CGPointMake(_pageSize.width * self.orginPageCount, 0) animated:NO]; 451 | 452 | self.page = self.orginPageCount; 453 | 454 | //启动自动轮播 455 | [self startTimer]; 456 | 457 | }else { 458 | //滚到开始 459 | [_scrollView setContentOffset:CGPointMake(0, 0) animated:NO]; 460 | 461 | self.page = self.orginPageCount; 462 | 463 | } 464 | 465 | } 466 | 467 | break; 468 | case HQFlowViewOrientationVertical:{ 469 | _scrollView.frame = CGRectMake(0, 0, _pageSize.width, _pageSize.height); 470 | _scrollView.contentSize = CGSizeMake(0 ,_pageSize.height * _pageCount); 471 | CGPoint theCenter = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds)); 472 | _scrollView.center = theCenter; 473 | 474 | if (self.orginPageCount > 1) { 475 | 476 | if (self.isCarousel) { 477 | //滚到第二组 478 | [_scrollView setContentOffset:CGPointMake(0, _pageSize.height * self.orginPageCount) animated:NO]; 479 | 480 | self.page = self.orginPageCount; 481 | 482 | //启动自动轮播 483 | [self startTimer]; 484 | }else { 485 | //滚到第二组 486 | [_scrollView setContentOffset:CGPointMake(0, 0) animated:NO]; 487 | 488 | self.page = self.orginPageCount; 489 | 490 | } 491 | 492 | } 493 | 494 | break; 495 | } 496 | default: 497 | break; 498 | } 499 | 500 | _needsReload = NO; 501 | } 502 | 503 | 504 | [self setPagesAtContentOffset:_scrollView.contentOffset];//根据当前scrollView的offset设置cell 505 | 506 | [self refreshVisibleCellAppearance];//更新各个可见Cell的显示外貌 507 | } 508 | 509 | 510 | - (HQIndexBannerSubview *)dequeueReusableCell{ 511 | HQIndexBannerSubview *cell = [_reusableCells lastObject]; 512 | if (cell) 513 | { 514 | [_reusableCells removeLastObject]; 515 | } 516 | 517 | return cell; 518 | } 519 | 520 | - (void)scrollToPage:(NSUInteger)pageNumber { 521 | if (pageNumber < _pageCount) { 522 | 523 | //首先停止定时器 524 | [self stopTimer]; 525 | 526 | if (self.isCarousel) { 527 | 528 | self.page = pageNumber + self.orginPageCount; 529 | [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(startTimer) object:nil]; 530 | [self performSelector:@selector(startTimer) withObject:nil afterDelay:0.5]; 531 | 532 | }else { 533 | self.page = pageNumber; 534 | } 535 | 536 | switch (self.orientation) { 537 | case HQFlowViewOrientationHorizontal: 538 | [_scrollView setContentOffset:CGPointMake(_pageSize.width * self.page, 0) animated:YES]; 539 | break; 540 | case HQFlowViewOrientationVertical: 541 | [_scrollView setContentOffset:CGPointMake(0, _pageSize.height * self.page) animated:YES]; 542 | break; 543 | } 544 | [self setPagesAtContentOffset:_scrollView.contentOffset]; 545 | [self refreshVisibleCellAppearance]; 546 | } 547 | } 548 | 549 | //////////////////////////////////////////////////////////////////////////////////////////////////// 550 | #pragma mark - 551 | #pragma mark hitTest 552 | 553 | - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { 554 | if ([self pointInside:point withEvent:event]) { 555 | CGPoint newPoint = CGPointZero; 556 | newPoint.x = point.x - _scrollView.frame.origin.x + _scrollView.contentOffset.x; 557 | newPoint.y = point.y - _scrollView.frame.origin.y + _scrollView.contentOffset.y; 558 | if ([_scrollView pointInside:newPoint withEvent:event]) { 559 | return [_scrollView hitTest:newPoint withEvent:event]; 560 | } 561 | 562 | return _scrollView; 563 | } 564 | 565 | return nil; 566 | } 567 | 568 | 569 | #pragma mark - 570 | #pragma mark UIScrollView Delegate 571 | 572 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView{ 573 | 574 | if (self.orginPageCount == 0) { 575 | return; 576 | } 577 | 578 | NSInteger pageIndex; 579 | 580 | switch (self.orientation) { 581 | case HQFlowViewOrientationHorizontal: 582 | pageIndex = (int)round(_scrollView.contentOffset.x / _pageSize.width) % self.orginPageCount; 583 | break; 584 | case HQFlowViewOrientationVertical: 585 | pageIndex = (int)round(_scrollView.contentOffset.y / _pageSize.height) % self.orginPageCount; 586 | break; 587 | default: 588 | break; 589 | } 590 | 591 | if (self.isCarousel) { 592 | 593 | if (self.orginPageCount > 1) { 594 | switch (self.orientation) { 595 | case HQFlowViewOrientationHorizontal: 596 | { 597 | if (scrollView.contentOffset.x / _pageSize.width >= 2 * self.orginPageCount) { 598 | 599 | [scrollView setContentOffset:CGPointMake(_pageSize.width * self.orginPageCount, 0) animated:NO]; 600 | 601 | self.page = self.orginPageCount; 602 | 603 | } 604 | 605 | if (scrollView.contentOffset.x / _pageSize.width <= self.orginPageCount - 1) { 606 | [scrollView setContentOffset:CGPointMake((2 * self.orginPageCount - 1) * _pageSize.width, 0) animated:NO]; 607 | 608 | self.page = 2 * self.orginPageCount; 609 | } 610 | 611 | } 612 | break; 613 | case HQFlowViewOrientationVertical: 614 | { 615 | if (scrollView.contentOffset.y / _pageSize.height >= 2 * self.orginPageCount) { 616 | 617 | [scrollView setContentOffset:CGPointMake(0, _pageSize.height * self.orginPageCount) animated:NO]; 618 | 619 | self.page = self.orginPageCount; 620 | 621 | } 622 | 623 | if (scrollView.contentOffset.y / _pageSize.height <= self.orginPageCount - 1) { 624 | [scrollView setContentOffset:CGPointMake(0, (2 * self.orginPageCount - 1) * _pageSize.height) animated:NO]; 625 | self.page = 2 * self.orginPageCount; 626 | } 627 | 628 | } 629 | break; 630 | default: 631 | break; 632 | } 633 | 634 | 635 | }else { 636 | 637 | pageIndex = 0; 638 | 639 | 640 | } 641 | } 642 | 643 | 644 | [self setPagesAtContentOffset:scrollView.contentOffset]; 645 | [self refreshVisibleCellAppearance]; 646 | 647 | if (self.pageControl && [self.pageControl respondsToSelector:@selector(setCurrentPage:)]) { 648 | 649 | [self.pageControl setCurrentPage:pageIndex]; 650 | } 651 | 652 | if (_delegate && [_delegate respondsToSelector:@selector(didScrollToPage:inFlowView:)] && _currentPageIndex != pageIndex && pageIndex >= 0) { 653 | [_delegate didScrollToPage:pageIndex inFlowView:self]; 654 | } 655 | 656 | _currentPageIndex = pageIndex; 657 | } 658 | 659 | #pragma mark --将要开始拖拽 660 | - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { 661 | [self stopTimer]; 662 | } 663 | 664 | #pragma mark --结束拖拽 665 | - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate { 666 | [self startTimer]; 667 | } 668 | 669 | #pragma mark --将要结束拖拽 670 | - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset { 671 | 672 | if (self.orginPageCount > 1 && self.isOpenAutoScroll && self.isCarousel) { 673 | 674 | switch (self.orientation) { 675 | case HQFlowViewOrientationHorizontal: 676 | { 677 | if (self.page == floor(_scrollView.contentOffset.x / _pageSize.width)) { 678 | 679 | self.page = floor(_scrollView.contentOffset.x / _pageSize.width) + 1; 680 | 681 | }else { 682 | 683 | self.page = floor(_scrollView.contentOffset.x / _pageSize.width); 684 | } 685 | } 686 | break; 687 | case HQFlowViewOrientationVertical: 688 | { 689 | if (self.page == floor(_scrollView.contentOffset.y / _pageSize.height)) { 690 | 691 | self.page = floor(_scrollView.contentOffset.y / _pageSize.height) + 1; 692 | 693 | }else { 694 | 695 | self.page = floor(_scrollView.contentOffset.y / _pageSize.height); 696 | } 697 | } 698 | break; 699 | default: 700 | break; 701 | } 702 | 703 | } 704 | } 705 | 706 | //点击了cell 707 | - (void)singleCellTapAction:(NSInteger)selectTag withCell:(HQIndexBannerSubview *)cell { 708 | 709 | if (self.delegate && [self.delegate respondsToSelector:@selector(didSelectCell:withSubViewIndex:)]) { 710 | 711 | [self.delegate didSelectCell:cell withSubViewIndex:selectTag]; 712 | 713 | } 714 | } 715 | 716 | //解决当父View释放时,当前视图因为被Timer强引用而不能释放的问题 717 | - (void)willMoveToSuperview:(UIView *)newSuperview { 718 | if (!newSuperview) { 719 | [self stopTimer]; 720 | } 721 | } 722 | 723 | //解决当timer释放后 回调scrollViewDidScroll时访问野指针导致崩溃 724 | - (void)dealloc { 725 | _scrollView.delegate = nil; 726 | } 727 | 728 | @end 729 | -------------------------------------------------------------------------------- /HQCardFlowView/HQFlowView/HQImagePageControl.h: -------------------------------------------------------------------------------- 1 | // 2 | // HQImagePageControl.h 3 | // HQCardFlowView 4 | // 5 | // Created by Mr_Han on 2018/7/24. 6 | // Copyright © 2018年 Mr_Han. All rights reserved. 7 | // CSDN 8 | // GitHub 9 | // 10 | 11 | #import 12 | 13 | @interface HQImagePageControl : UIPageControl 14 | 15 | { 16 | UIImage* activeImage; 17 | UIImage* inactiveImage; 18 | } 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /HQCardFlowView/HQFlowView/HQImagePageControl.m: -------------------------------------------------------------------------------- 1 | // 2 | // HQImagePageControl.m 3 | // HQCardFlowView 4 | // 5 | // Created by Mr_Han on 2018/7/24. 6 | // Copyright © 2018年 Mr_Han. All rights reserved.. 7 | // CSDN 8 | // GitHub 9 | // 10 | 11 | #import "HQImagePageControl.h" 12 | 13 | @implementation HQImagePageControl 14 | 15 | -(id) initWithFrame:(CGRect)frame 16 | { 17 | self = [super initWithFrame:frame]; 18 | 19 | activeImage = [UIImage imageNamed:@"icon_pageWidget_sign"]; 20 | inactiveImage = [UIImage imageNamed:@"icon_pageWidget"] ; 21 | 22 | return self; 23 | } 24 | 25 | -(void) updateDots 26 | { 27 | for (int i = 0; i < [self.subviews count]; i++) 28 | { 29 | UIView *vi = [self.subviews objectAtIndex:i]; 30 | 31 | //添加imageView 32 | if ([vi.subviews count] == 0) { 33 | UIImageView * view = [[UIImageView alloc]initWithFrame:vi.bounds]; 34 | [vi addSubview:view]; 35 | }; 36 | 37 | //配置imageView 38 | UIImageView * view = vi.subviews[0]; 39 | 40 | if (i == self.currentPage) view.image = activeImage; 41 | else view.image = inactiveImage; 42 | } 43 | } 44 | 45 | -(void) setCurrentPage:(NSInteger)page 46 | { 47 | [super setCurrentPage:page]; 48 | //修改图标大小 49 | for (NSUInteger subviewIndex = 0; subviewIndex < [self.subviews count]; subviewIndex++) { 50 | 51 | UIImageView* subview = [self.subviews objectAtIndex:subviewIndex]; 52 | 53 | CGSize size; 54 | 55 | size.height = 8.5; 56 | 57 | size.width = 6.f; 58 | 59 | subview.backgroundColor = [UIColor clearColor]; 60 | 61 | [subview setFrame:CGRectMake(subview.frame.origin.x, subview.frame.origin.y, 62 | 63 | size.width,size.height)]; 64 | 65 | } 66 | 67 | 68 | [self updateDots]; 69 | } 70 | 71 | @end 72 | -------------------------------------------------------------------------------- /HQCardFlowView/HQFlowView/HQIndexBannerSubview.h: -------------------------------------------------------------------------------- 1 | // 2 | // HQIndexBannerSubview.h 3 | // HQCardFlowView 4 | // 5 | // Created by Mr_Han on 2018/7/24. 6 | // Copyright © 2018年 Mr_Han. All rights reserved. 7 | // CSDN 8 | // GitHub 9 | // 10 | 11 | 12 | /****************************** 13 | 14 | 可以根据自己的需要继承HQIndexBannerSubview 15 | 16 | ******************************/ 17 | 18 | #import 19 | 20 | @interface HQIndexBannerSubview : UIView 21 | 22 | /** 23 | * 主图 24 | */ 25 | @property (nonatomic, strong) UIImageView *mainImageView; 26 | 27 | /** 28 | * 阴影 29 | */ 30 | @property (nonatomic, strong) UIImageView *iconImage; 31 | 32 | /** 33 | * 用来变色的view 34 | */ 35 | @property (nonatomic, strong) UIView *coverView; 36 | 37 | @property (nonatomic, copy) void (^didSelectCellBlock)(NSInteger tag, HQIndexBannerSubview *cell); 38 | 39 | /** 40 | 设置子控件frame,继承后要重写 41 | 42 | @param superViewBounds <#superViewBounds description#> 43 | */ 44 | - (void)setSubviewsWithSuperViewBounds:(CGRect)superViewBounds; 45 | 46 | 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /HQCardFlowView/HQFlowView/HQIndexBannerSubview.m: -------------------------------------------------------------------------------- 1 | // 2 | // HQIndexBannerSubview.m 3 | // HQCardFlowView 4 | // 5 | // Created by Mr_Han on 2018/7/24. 6 | // Copyright © 2018年 Mr_Han. All rights reserved. 7 | // CSDN 8 | // GitHub 9 | // 10 | 11 | #import "HQIndexBannerSubview.h" 12 | 13 | @implementation HQIndexBannerSubview 14 | 15 | - (instancetype)initWithFrame:(CGRect)frame { 16 | 17 | self = [super initWithFrame:frame]; 18 | 19 | if (self) { 20 | 21 | [self addSubview:self.mainImageView]; 22 | [self addSubview:self.coverView]; 23 | UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleCellTapAction:)]; 24 | [self addGestureRecognizer:singleTap]; 25 | } 26 | 27 | return self; 28 | } 29 | 30 | - (void)singleCellTapAction:(UIGestureRecognizer *)gesture { 31 | if (self.didSelectCellBlock) { 32 | self.didSelectCellBlock(self.tag, self); 33 | } 34 | } 35 | 36 | - (void)setSubviewsWithSuperViewBounds:(CGRect)superViewBounds { 37 | 38 | NSLog(@"cell.coverView.alpha---%f",self.coverView.alpha); 39 | 40 | if (CGRectEqualToRect(self.mainImageView.frame, superViewBounds)) { 41 | return; 42 | } 43 | 44 | self.mainImageView.frame = superViewBounds; 45 | self.coverView.frame = superViewBounds; 46 | } 47 | 48 | - (UIImageView *)mainImageView { 49 | 50 | if (!_mainImageView) { 51 | _mainImageView = [[UIImageView alloc] init]; 52 | _mainImageView.userInteractionEnabled = YES; 53 | } 54 | return _mainImageView; 55 | } 56 | 57 | - (UIImageView *)iconImage { 58 | 59 | if (!_iconImage) { 60 | _iconImage = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)]; 61 | _iconImage.contentMode = UIViewContentModeScaleAspectFit; 62 | } 63 | return _iconImage; 64 | } 65 | 66 | - (UIView *)coverView { 67 | 68 | if (!_coverView) { 69 | _coverView = [[UIView alloc] init]; 70 | _coverView.backgroundColor = [UIColor blackColor]; 71 | } 72 | return _coverView; 73 | } 74 | 75 | 76 | @end 77 | -------------------------------------------------------------------------------- /HQCardFlowView/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 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /HQCardFlowView/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // HQCardFlowView 4 | // 5 | // Created by Mr_Han on 2018/7/24. 6 | // Copyright © 2018年 Mr_Han. All rights reserved. 7 | // CSDN 8 | // GitHub 9 | // 10 | 11 | #import 12 | 13 | @interface ViewController : UIViewController 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /HQCardFlowView/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // HQCardFlowView 4 | // 5 | // Created by Mr_Han on 2018/7/24. 6 | // Copyright © 2018年 Mr_Han. All rights reserved. 7 | // CSDN 8 | // GitHub 9 | // 10 | 11 | #define JkScreenHeight [UIScreen mainScreen].bounds.size.height 12 | #define JkScreenWidth [UIScreen mainScreen].bounds.size.width 13 | 14 | #import "ViewController.h" 15 | #import "HQFlowView.h" 16 | #import "HQImagePageControl.h" 17 | 18 | @interface ViewController () 19 | 20 | /** 21 | * 图片数组 22 | */ 23 | @property (nonatomic, strong) NSMutableArray *advArray; 24 | /** 25 | * 轮播图 26 | */ 27 | @property (nonatomic, strong) HQImagePageControl *pageC; 28 | @property (nonatomic, strong) HQFlowView *pageFlowView; 29 | @property (nonatomic, strong) UIScrollView *scrollView; // 轮播图容器 30 | 31 | @end 32 | 33 | @implementation ViewController 34 | 35 | - (NSMutableArray *)advArray 36 | { 37 | if (!_advArray) { 38 | _advArray = [NSMutableArray arrayWithObjects:@"1",@"22",@"33",@"44",@"55",@"66",@"77",@"88",@"99", nil]; 39 | } 40 | return _advArray; 41 | } 42 | 43 | #pragma mark -- 轮播图 44 | - (UIScrollView *)scrollView 45 | { 46 | if (!_scrollView) { 47 | _scrollView = [[UIScrollView alloc]initWithFrame:CGRectMake(0, 100, JkScreenWidth, 200)]; 48 | _scrollView.backgroundColor = [UIColor clearColor]; 49 | } 50 | return _scrollView; 51 | } 52 | 53 | - (HQFlowView *)pageFlowView 54 | { 55 | if (!_pageFlowView) { 56 | 57 | _pageFlowView = [[HQFlowView alloc] initWithFrame:CGRectMake(0, 0, JkScreenWidth, 200)]; 58 | _pageFlowView.delegate = self; 59 | _pageFlowView.dataSource = self; 60 | _pageFlowView.minimumPageAlpha = 0.3; 61 | _pageFlowView.leftRightMargin = 15; 62 | _pageFlowView.topBottomMargin = 20; 63 | _pageFlowView.orginPageCount = _advArray.count; 64 | _pageFlowView.isOpenAutoScroll = YES; 65 | _pageFlowView.autoTime = 3.0; 66 | _pageFlowView.orientation = HQFlowViewOrientationHorizontal; 67 | 68 | } 69 | return _pageFlowView; 70 | } 71 | 72 | - (HQImagePageControl *)pageC 73 | { 74 | if (!_pageC) { 75 | 76 | //初始化pageControl 77 | if (!_pageC) { 78 | _pageC = [[HQImagePageControl alloc]initWithFrame:CGRectMake(0, self.scrollView.frame.size.height - 15, self.scrollView.frame.size.width, 7.5)]; 79 | } 80 | [self.pageFlowView.pageControl setCurrentPage:0]; 81 | self.pageFlowView.pageControl = _pageC; 82 | 83 | } 84 | return _pageC; 85 | } 86 | 87 | #pragma mark JQFlowViewDelegate 88 | - (CGSize)sizeForPageInFlowView:(HQFlowView *)flowView 89 | { 90 | return CGSizeMake(JkScreenWidth-2*30, self.scrollView.frame.size.height-2*3); 91 | } 92 | 93 | - (void)didSelectCell:(UIView *)subView withSubViewIndex:(NSInteger)subIndex 94 | { 95 | NSLog(@"点击第%d个广告",subIndex); 96 | } 97 | #pragma mark JQFlowViewDatasource 98 | - (NSInteger)numberOfPagesInFlowView:(HQFlowView *)flowView 99 | { 100 | return self.advArray.count; 101 | } 102 | - (HQIndexBannerSubview *)flowView:(HQFlowView *)flowView cellForPageAtIndex:(NSInteger)index 103 | { 104 | HQIndexBannerSubview *bannerView = (HQIndexBannerSubview *)[flowView dequeueReusableCell]; 105 | if (!bannerView) { 106 | bannerView = [[HQIndexBannerSubview alloc] initWithFrame:CGRectMake(0, 0, self.pageFlowView.frame.size.width, self.pageFlowView.frame.size.height)]; 107 | bannerView.layer.cornerRadius = 5; 108 | bannerView.layer.masksToBounds = YES; 109 | bannerView.coverView.backgroundColor = [UIColor darkGrayColor]; 110 | } 111 | //在这里下载网络图片 112 | // [bannerView.mainImageView sd_setImageWithURL:[NSURL URLWithString:self.advArray[index]] placeholderImage:nil]; 113 | //加载本地图片 114 | bannerView.mainImageView.image = [UIImage imageNamed:self.advArray[index]]; 115 | 116 | return bannerView; 117 | } 118 | 119 | - (void)didScrollToPage:(NSInteger)pageNumber inFlowView:(HQFlowView *)flowView 120 | { 121 | [self.pageFlowView.pageControl setCurrentPage:pageNumber]; 122 | } 123 | #pragma mark --旋转屏幕改变JQFlowView大小之后实现该方法 124 | - (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id)coordinator 125 | { 126 | if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad){ 127 | [coordinator animateAlongsideTransition:^(id context) { [self.pageFlowView reloadData]; 128 | } completion:NULL]; 129 | } 130 | } 131 | 132 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 133 | { 134 | return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown); 135 | } 136 | - (void)dealloc 137 | { 138 | self.pageFlowView.delegate = nil; 139 | self.pageFlowView.dataSource = nil; 140 | [self.pageFlowView stopTimer]; 141 | } 142 | 143 | 144 | 145 | - (void)viewDidLoad { 146 | [super viewDidLoad]; 147 | // Do any additional setup after loading the view, typically from a nib. 148 | 149 | [self.view addSubview:self.scrollView]; 150 | [self.scrollView addSubview:self.pageFlowView]; 151 | [self.pageFlowView addSubview:self.pageC]; 152 | 153 | [self.pageFlowView reloadData];//刷新轮播 154 | } 155 | 156 | 157 | - (void)didReceiveMemoryWarning { 158 | [super didReceiveMemoryWarning]; 159 | // Dispose of any resources that can be recreated. 160 | } 161 | 162 | 163 | @end 164 | -------------------------------------------------------------------------------- /HQCardFlowView/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // HQCardFlowView 4 | // 5 | // Created by Mr_Han on 2018/7/24. 6 | // Copyright © 2018年 Mr_Han. All rights reserved. 7 | // CSDN 8 | // GitHub 9 | // 10 | 11 | #import 12 | #import "AppDelegate.h" 13 | 14 | int main(int argc, char * argv[]) { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /HQCardFlowViewTests/HQCardFlowViewTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // HQCardFlowViewTests.m 3 | // HQCardFlowViewTests 4 | // 5 | // Created by Mr_Han on 2018/7/24. 6 | // Copyright © 2018年 Mr_Han. All rights reserved. 7 | // CSDN 8 | // GitHub 9 | // 10 | 11 | #import 12 | 13 | @interface HQCardFlowViewTests : XCTestCase 14 | 15 | @end 16 | 17 | @implementation HQCardFlowViewTests 18 | 19 | - (void)setUp { 20 | [super setUp]; 21 | // Put setup code here. This method is called before the invocation of each test method in the class. 22 | } 23 | 24 | - (void)tearDown { 25 | // Put teardown code here. This method is called after the invocation of each test method in the class. 26 | [super tearDown]; 27 | } 28 | 29 | - (void)testExample { 30 | // This is an example of a functional test case. 31 | // Use XCTAssert and related functions to verify your tests produce the correct results. 32 | } 33 | 34 | - (void)testPerformanceExample { 35 | // This is an example of a performance test case. 36 | [self measureBlock:^{ 37 | // Put the code you want to measure the time of here. 38 | }]; 39 | } 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /HQCardFlowViewTests/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 | -------------------------------------------------------------------------------- /HQCardFlowViewUITests/HQCardFlowViewUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // HQCardFlowViewUITests.m 3 | // HQCardFlowViewUITests 4 | // 5 | // Created by Mr_Han on 2018/7/24. 6 | // Copyright © 2018年 Mr_Han. All rights reserved. 7 | // CSDN 8 | // GitHub 9 | // 10 | 11 | #import 12 | 13 | @interface HQCardFlowViewUITests : XCTestCase 14 | 15 | @end 16 | 17 | @implementation HQCardFlowViewUITests 18 | 19 | - (void)setUp { 20 | [super setUp]; 21 | 22 | // Put setup code here. This method is called before the invocation of each test method in the class. 23 | 24 | // In UI tests it is usually best to stop immediately when a failure occurs. 25 | self.continueAfterFailure = NO; 26 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 27 | [[[XCUIApplication alloc] init] launch]; 28 | 29 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 30 | } 31 | 32 | - (void)tearDown { 33 | // Put teardown code here. This method is called after the invocation of each test method in the class. 34 | [super tearDown]; 35 | } 36 | 37 | - (void)testExample { 38 | // Use recording to get started writing UI tests. 39 | // Use XCTAssert and related functions to verify your tests produce the correct results. 40 | } 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /HQCardFlowViewUITests/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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HQCardFlowView 2 | 3 | ### 3D卡片轮播,卡片轮播,无限轮播,DIY 4 | 5 | **如果喜欢,请给一个小星星。O(∩_∩)O谢谢!** 6 | 7 | ### [详细请参考博客](https://blog.csdn.net/u010960265/article/details/81183843) 8 | 9 | ### 效果如下图: 10 | 11 | ![效果图](https://github.com/HanQiGod/HQCardFlowView/blob/master/HQCardFlowView/20180724141023415.gif) 12 | 13 | 14 | ### 参考UITableView的UITableViewDataSource和UITableViewDelegate两个方法实现;支持五险轮播,可以加载本地图片,也可以加载网络图片,可以根据自己的需求自定义。 15 | 16 | ## HQFlowViewDelegate 17 | ``` 18 | /** 19 | * 当前显示cell的Size(中间页显示大小) 20 | * 21 | * @param flowView 22 | * 23 | * @return CGSize 24 | */ 25 | - (CGSize)sizeForPageInFlowView:(HQFlowView *)flowView; 26 | 27 | /** 28 | * 滚动到了某一列 29 | * 30 | * @param pageNumber 31 | * @param flowView 32 | */ 33 | - (void)didScrollToPage:(NSInteger)pageNumber inFlowView:(HQFlowView *)flowView; 34 | 35 | /** 36 | * 点击了第几个cell 37 | * 38 | * @param subView 点击的控件 39 | * @param subIndex 点击控件的index 40 | * 41 | * @return 42 | */ 43 | - (void)didSelectCell:(HQIndexBannerSubview *)subView withSubViewIndex:(NSInteger)subIndex; 44 | ``` 45 | 46 | ## HQFlowViewDataSource 47 | ``` 48 | /** 49 | * 返回显示View的个数 50 | * 51 | * @param flowView 52 | * 53 | * @return 54 | */ 55 | - (NSInteger)numberOfPagesInFlowView:(HQFlowView *)flowView; 56 | 57 | /** 58 | * 给某一列设置属性 59 | * 60 | * @param flowView 61 | * @param index 62 | * 63 | * @return 64 | */ 65 | - (HQIndexBannerSubview *)flowView:(HQFlowView *)flowView cellForPageAtIndex:(NSInteger)index; 66 | ``` 67 | --------------------------------------------------------------------------------