├── .DS_Store ├── Example ├── .DS_Store └── JHCollectionViewFlowLayout │ ├── .DS_Store │ ├── JHCollectionViewFlowLayout.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcuserdata │ │ │ └── apple.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── apple.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ └── xcschememanagement.plist │ ├── JHCollectionViewFlowLayout │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── Contents.json │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Demo1Ctrl.h │ ├── Demo1Ctrl.m │ ├── Demo2Ctrl.h │ ├── Demo2Ctrl.m │ ├── DemoCell.h │ ├── DemoCell.m │ ├── Info.plist │ ├── ViewController.h │ ├── ViewController.m │ └── main.m │ ├── JHCollectionViewFlowLayoutTests │ ├── Info.plist │ └── JHCollectionViewFlowLayoutTests.m │ └── JHCollectionViewFlowLayoutUITests │ ├── Info.plist │ └── JHCollectionViewFlowLayoutUITests.m ├── JHCollectionViewFlowLayout ├── JHCollectionViewFlowLayout.h └── JHCollectionViewFlowLayout.m ├── LICENSE ├── README.md └── image ├── custom.png └── system.png /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xjh093/JHCollectionViewFlowLayout/170372d43e416eb967bc95804e39dec2f25178f6/.DS_Store -------------------------------------------------------------------------------- /Example/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xjh093/JHCollectionViewFlowLayout/170372d43e416eb967bc95804e39dec2f25178f6/Example/.DS_Store -------------------------------------------------------------------------------- /Example/JHCollectionViewFlowLayout/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xjh093/JHCollectionViewFlowLayout/170372d43e416eb967bc95804e39dec2f25178f6/Example/JHCollectionViewFlowLayout/.DS_Store -------------------------------------------------------------------------------- /Example/JHCollectionViewFlowLayout/JHCollectionViewFlowLayout.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1855CEEC2450545B00D8FD23 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1855CEEB2450545B00D8FD23 /* AppDelegate.m */; }; 11 | 1855CEF22450545B00D8FD23 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1855CEF12450545B00D8FD23 /* ViewController.m */; }; 12 | 1855CEF52450545B00D8FD23 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 1855CEF32450545B00D8FD23 /* Main.storyboard */; }; 13 | 1855CEF72450545E00D8FD23 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1855CEF62450545E00D8FD23 /* Assets.xcassets */; }; 14 | 1855CEFA2450545E00D8FD23 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 1855CEF82450545E00D8FD23 /* LaunchScreen.storyboard */; }; 15 | 1855CEFD2450545E00D8FD23 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 1855CEFC2450545E00D8FD23 /* main.m */; }; 16 | 1855CF072450545E00D8FD23 /* JHCollectionViewFlowLayoutTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1855CF062450545E00D8FD23 /* JHCollectionViewFlowLayoutTests.m */; }; 17 | 1855CF122450545E00D8FD23 /* JHCollectionViewFlowLayoutUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1855CF112450545E00D8FD23 /* JHCollectionViewFlowLayoutUITests.m */; }; 18 | 1855CF22245054AD00D8FD23 /* JHCollectionViewFlowLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 1855CF21245054AD00D8FD23 /* JHCollectionViewFlowLayout.m */; }; 19 | 1855CF25245055E600D8FD23 /* Demo1Ctrl.m in Sources */ = {isa = PBXBuildFile; fileRef = 1855CF24245055E600D8FD23 /* Demo1Ctrl.m */; }; 20 | 1855CF28245055F100D8FD23 /* Demo2Ctrl.m in Sources */ = {isa = PBXBuildFile; fileRef = 1855CF27245055F100D8FD23 /* Demo2Ctrl.m */; }; 21 | 1855CF2B2450569500D8FD23 /* DemoCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 1855CF2A2450569500D8FD23 /* DemoCell.m */; }; 22 | /* End PBXBuildFile section */ 23 | 24 | /* Begin PBXContainerItemProxy section */ 25 | 1855CF032450545E00D8FD23 /* PBXContainerItemProxy */ = { 26 | isa = PBXContainerItemProxy; 27 | containerPortal = 1855CEDF2450545B00D8FD23 /* Project object */; 28 | proxyType = 1; 29 | remoteGlobalIDString = 1855CEE62450545B00D8FD23; 30 | remoteInfo = JHCollectionViewFlowLayout; 31 | }; 32 | 1855CF0E2450545E00D8FD23 /* PBXContainerItemProxy */ = { 33 | isa = PBXContainerItemProxy; 34 | containerPortal = 1855CEDF2450545B00D8FD23 /* Project object */; 35 | proxyType = 1; 36 | remoteGlobalIDString = 1855CEE62450545B00D8FD23; 37 | remoteInfo = JHCollectionViewFlowLayout; 38 | }; 39 | /* End PBXContainerItemProxy section */ 40 | 41 | /* Begin PBXFileReference section */ 42 | 1855CEE72450545B00D8FD23 /* JHCollectionViewFlowLayout.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = JHCollectionViewFlowLayout.app; sourceTree = BUILT_PRODUCTS_DIR; }; 43 | 1855CEEA2450545B00D8FD23 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 44 | 1855CEEB2450545B00D8FD23 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 45 | 1855CEF02450545B00D8FD23 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 46 | 1855CEF12450545B00D8FD23 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 47 | 1855CEF42450545B00D8FD23 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 48 | 1855CEF62450545E00D8FD23 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 49 | 1855CEF92450545E00D8FD23 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 50 | 1855CEFB2450545E00D8FD23 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 51 | 1855CEFC2450545E00D8FD23 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 52 | 1855CF022450545E00D8FD23 /* JHCollectionViewFlowLayoutTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = JHCollectionViewFlowLayoutTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 53 | 1855CF062450545E00D8FD23 /* JHCollectionViewFlowLayoutTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JHCollectionViewFlowLayoutTests.m; sourceTree = ""; }; 54 | 1855CF082450545E00D8FD23 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 55 | 1855CF0D2450545E00D8FD23 /* JHCollectionViewFlowLayoutUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = JHCollectionViewFlowLayoutUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 56 | 1855CF112450545E00D8FD23 /* JHCollectionViewFlowLayoutUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JHCollectionViewFlowLayoutUITests.m; sourceTree = ""; }; 57 | 1855CF132450545E00D8FD23 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 58 | 1855CF20245054AD00D8FD23 /* JHCollectionViewFlowLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JHCollectionViewFlowLayout.h; sourceTree = ""; }; 59 | 1855CF21245054AD00D8FD23 /* JHCollectionViewFlowLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JHCollectionViewFlowLayout.m; sourceTree = ""; }; 60 | 1855CF23245055E600D8FD23 /* Demo1Ctrl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Demo1Ctrl.h; sourceTree = ""; }; 61 | 1855CF24245055E600D8FD23 /* Demo1Ctrl.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Demo1Ctrl.m; sourceTree = ""; }; 62 | 1855CF26245055F100D8FD23 /* Demo2Ctrl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Demo2Ctrl.h; sourceTree = ""; }; 63 | 1855CF27245055F100D8FD23 /* Demo2Ctrl.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Demo2Ctrl.m; sourceTree = ""; }; 64 | 1855CF292450569500D8FD23 /* DemoCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DemoCell.h; sourceTree = ""; }; 65 | 1855CF2A2450569500D8FD23 /* DemoCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DemoCell.m; sourceTree = ""; }; 66 | /* End PBXFileReference section */ 67 | 68 | /* Begin PBXFrameworksBuildPhase section */ 69 | 1855CEE42450545B00D8FD23 /* Frameworks */ = { 70 | isa = PBXFrameworksBuildPhase; 71 | buildActionMask = 2147483647; 72 | files = ( 73 | ); 74 | runOnlyForDeploymentPostprocessing = 0; 75 | }; 76 | 1855CEFF2450545E00D8FD23 /* Frameworks */ = { 77 | isa = PBXFrameworksBuildPhase; 78 | buildActionMask = 2147483647; 79 | files = ( 80 | ); 81 | runOnlyForDeploymentPostprocessing = 0; 82 | }; 83 | 1855CF0A2450545E00D8FD23 /* Frameworks */ = { 84 | isa = PBXFrameworksBuildPhase; 85 | buildActionMask = 2147483647; 86 | files = ( 87 | ); 88 | runOnlyForDeploymentPostprocessing = 0; 89 | }; 90 | /* End PBXFrameworksBuildPhase section */ 91 | 92 | /* Begin PBXGroup section */ 93 | 1855CEDE2450545B00D8FD23 = { 94 | isa = PBXGroup; 95 | children = ( 96 | 1855CEE92450545B00D8FD23 /* JHCollectionViewFlowLayout */, 97 | 1855CF052450545E00D8FD23 /* JHCollectionViewFlowLayoutTests */, 98 | 1855CF102450545E00D8FD23 /* JHCollectionViewFlowLayoutUITests */, 99 | 1855CEE82450545B00D8FD23 /* Products */, 100 | ); 101 | sourceTree = ""; 102 | }; 103 | 1855CEE82450545B00D8FD23 /* Products */ = { 104 | isa = PBXGroup; 105 | children = ( 106 | 1855CEE72450545B00D8FD23 /* JHCollectionViewFlowLayout.app */, 107 | 1855CF022450545E00D8FD23 /* JHCollectionViewFlowLayoutTests.xctest */, 108 | 1855CF0D2450545E00D8FD23 /* JHCollectionViewFlowLayoutUITests.xctest */, 109 | ); 110 | name = Products; 111 | sourceTree = ""; 112 | }; 113 | 1855CEE92450545B00D8FD23 /* JHCollectionViewFlowLayout */ = { 114 | isa = PBXGroup; 115 | children = ( 116 | 1855CF1F245054AD00D8FD23 /* JHCollectionViewFlowLayout */, 117 | 1855CEEA2450545B00D8FD23 /* AppDelegate.h */, 118 | 1855CEEB2450545B00D8FD23 /* AppDelegate.m */, 119 | 1855CEF02450545B00D8FD23 /* ViewController.h */, 120 | 1855CEF12450545B00D8FD23 /* ViewController.m */, 121 | 1855CF23245055E600D8FD23 /* Demo1Ctrl.h */, 122 | 1855CF24245055E600D8FD23 /* Demo1Ctrl.m */, 123 | 1855CF26245055F100D8FD23 /* Demo2Ctrl.h */, 124 | 1855CF27245055F100D8FD23 /* Demo2Ctrl.m */, 125 | 1855CF292450569500D8FD23 /* DemoCell.h */, 126 | 1855CF2A2450569500D8FD23 /* DemoCell.m */, 127 | 1855CEF32450545B00D8FD23 /* Main.storyboard */, 128 | 1855CEF62450545E00D8FD23 /* Assets.xcassets */, 129 | 1855CEF82450545E00D8FD23 /* LaunchScreen.storyboard */, 130 | 1855CEFB2450545E00D8FD23 /* Info.plist */, 131 | 1855CEFC2450545E00D8FD23 /* main.m */, 132 | ); 133 | path = JHCollectionViewFlowLayout; 134 | sourceTree = ""; 135 | }; 136 | 1855CF052450545E00D8FD23 /* JHCollectionViewFlowLayoutTests */ = { 137 | isa = PBXGroup; 138 | children = ( 139 | 1855CF062450545E00D8FD23 /* JHCollectionViewFlowLayoutTests.m */, 140 | 1855CF082450545E00D8FD23 /* Info.plist */, 141 | ); 142 | path = JHCollectionViewFlowLayoutTests; 143 | sourceTree = ""; 144 | }; 145 | 1855CF102450545E00D8FD23 /* JHCollectionViewFlowLayoutUITests */ = { 146 | isa = PBXGroup; 147 | children = ( 148 | 1855CF112450545E00D8FD23 /* JHCollectionViewFlowLayoutUITests.m */, 149 | 1855CF132450545E00D8FD23 /* Info.plist */, 150 | ); 151 | path = JHCollectionViewFlowLayoutUITests; 152 | sourceTree = ""; 153 | }; 154 | 1855CF1F245054AD00D8FD23 /* JHCollectionViewFlowLayout */ = { 155 | isa = PBXGroup; 156 | children = ( 157 | 1855CF20245054AD00D8FD23 /* JHCollectionViewFlowLayout.h */, 158 | 1855CF21245054AD00D8FD23 /* JHCollectionViewFlowLayout.m */, 159 | ); 160 | name = JHCollectionViewFlowLayout; 161 | path = ../../../JHCollectionViewFlowLayout; 162 | sourceTree = ""; 163 | }; 164 | /* End PBXGroup section */ 165 | 166 | /* Begin PBXNativeTarget section */ 167 | 1855CEE62450545B00D8FD23 /* JHCollectionViewFlowLayout */ = { 168 | isa = PBXNativeTarget; 169 | buildConfigurationList = 1855CF162450545E00D8FD23 /* Build configuration list for PBXNativeTarget "JHCollectionViewFlowLayout" */; 170 | buildPhases = ( 171 | 1855CEE32450545B00D8FD23 /* Sources */, 172 | 1855CEE42450545B00D8FD23 /* Frameworks */, 173 | 1855CEE52450545B00D8FD23 /* Resources */, 174 | ); 175 | buildRules = ( 176 | ); 177 | dependencies = ( 178 | ); 179 | name = JHCollectionViewFlowLayout; 180 | productName = JHCollectionViewFlowLayout; 181 | productReference = 1855CEE72450545B00D8FD23 /* JHCollectionViewFlowLayout.app */; 182 | productType = "com.apple.product-type.application"; 183 | }; 184 | 1855CF012450545E00D8FD23 /* JHCollectionViewFlowLayoutTests */ = { 185 | isa = PBXNativeTarget; 186 | buildConfigurationList = 1855CF192450545E00D8FD23 /* Build configuration list for PBXNativeTarget "JHCollectionViewFlowLayoutTests" */; 187 | buildPhases = ( 188 | 1855CEFE2450545E00D8FD23 /* Sources */, 189 | 1855CEFF2450545E00D8FD23 /* Frameworks */, 190 | 1855CF002450545E00D8FD23 /* Resources */, 191 | ); 192 | buildRules = ( 193 | ); 194 | dependencies = ( 195 | 1855CF042450545E00D8FD23 /* PBXTargetDependency */, 196 | ); 197 | name = JHCollectionViewFlowLayoutTests; 198 | productName = JHCollectionViewFlowLayoutTests; 199 | productReference = 1855CF022450545E00D8FD23 /* JHCollectionViewFlowLayoutTests.xctest */; 200 | productType = "com.apple.product-type.bundle.unit-test"; 201 | }; 202 | 1855CF0C2450545E00D8FD23 /* JHCollectionViewFlowLayoutUITests */ = { 203 | isa = PBXNativeTarget; 204 | buildConfigurationList = 1855CF1C2450545E00D8FD23 /* Build configuration list for PBXNativeTarget "JHCollectionViewFlowLayoutUITests" */; 205 | buildPhases = ( 206 | 1855CF092450545E00D8FD23 /* Sources */, 207 | 1855CF0A2450545E00D8FD23 /* Frameworks */, 208 | 1855CF0B2450545E00D8FD23 /* Resources */, 209 | ); 210 | buildRules = ( 211 | ); 212 | dependencies = ( 213 | 1855CF0F2450545E00D8FD23 /* PBXTargetDependency */, 214 | ); 215 | name = JHCollectionViewFlowLayoutUITests; 216 | productName = JHCollectionViewFlowLayoutUITests; 217 | productReference = 1855CF0D2450545E00D8FD23 /* JHCollectionViewFlowLayoutUITests.xctest */; 218 | productType = "com.apple.product-type.bundle.ui-testing"; 219 | }; 220 | /* End PBXNativeTarget section */ 221 | 222 | /* Begin PBXProject section */ 223 | 1855CEDF2450545B00D8FD23 /* Project object */ = { 224 | isa = PBXProject; 225 | attributes = { 226 | LastUpgradeCheck = 1130; 227 | ORGANIZATIONNAME = HaoCold; 228 | TargetAttributes = { 229 | 1855CEE62450545B00D8FD23 = { 230 | CreatedOnToolsVersion = 11.3.1; 231 | }; 232 | 1855CF012450545E00D8FD23 = { 233 | CreatedOnToolsVersion = 11.3.1; 234 | TestTargetID = 1855CEE62450545B00D8FD23; 235 | }; 236 | 1855CF0C2450545E00D8FD23 = { 237 | CreatedOnToolsVersion = 11.3.1; 238 | TestTargetID = 1855CEE62450545B00D8FD23; 239 | }; 240 | }; 241 | }; 242 | buildConfigurationList = 1855CEE22450545B00D8FD23 /* Build configuration list for PBXProject "JHCollectionViewFlowLayout" */; 243 | compatibilityVersion = "Xcode 9.3"; 244 | developmentRegion = en; 245 | hasScannedForEncodings = 0; 246 | knownRegions = ( 247 | en, 248 | Base, 249 | ); 250 | mainGroup = 1855CEDE2450545B00D8FD23; 251 | productRefGroup = 1855CEE82450545B00D8FD23 /* Products */; 252 | projectDirPath = ""; 253 | projectRoot = ""; 254 | targets = ( 255 | 1855CEE62450545B00D8FD23 /* JHCollectionViewFlowLayout */, 256 | 1855CF012450545E00D8FD23 /* JHCollectionViewFlowLayoutTests */, 257 | 1855CF0C2450545E00D8FD23 /* JHCollectionViewFlowLayoutUITests */, 258 | ); 259 | }; 260 | /* End PBXProject section */ 261 | 262 | /* Begin PBXResourcesBuildPhase section */ 263 | 1855CEE52450545B00D8FD23 /* Resources */ = { 264 | isa = PBXResourcesBuildPhase; 265 | buildActionMask = 2147483647; 266 | files = ( 267 | 1855CEFA2450545E00D8FD23 /* LaunchScreen.storyboard in Resources */, 268 | 1855CEF72450545E00D8FD23 /* Assets.xcassets in Resources */, 269 | 1855CEF52450545B00D8FD23 /* Main.storyboard in Resources */, 270 | ); 271 | runOnlyForDeploymentPostprocessing = 0; 272 | }; 273 | 1855CF002450545E00D8FD23 /* Resources */ = { 274 | isa = PBXResourcesBuildPhase; 275 | buildActionMask = 2147483647; 276 | files = ( 277 | ); 278 | runOnlyForDeploymentPostprocessing = 0; 279 | }; 280 | 1855CF0B2450545E00D8FD23 /* Resources */ = { 281 | isa = PBXResourcesBuildPhase; 282 | buildActionMask = 2147483647; 283 | files = ( 284 | ); 285 | runOnlyForDeploymentPostprocessing = 0; 286 | }; 287 | /* End PBXResourcesBuildPhase section */ 288 | 289 | /* Begin PBXSourcesBuildPhase section */ 290 | 1855CEE32450545B00D8FD23 /* Sources */ = { 291 | isa = PBXSourcesBuildPhase; 292 | buildActionMask = 2147483647; 293 | files = ( 294 | 1855CEF22450545B00D8FD23 /* ViewController.m in Sources */, 295 | 1855CEEC2450545B00D8FD23 /* AppDelegate.m in Sources */, 296 | 1855CF22245054AD00D8FD23 /* JHCollectionViewFlowLayout.m in Sources */, 297 | 1855CF2B2450569500D8FD23 /* DemoCell.m in Sources */, 298 | 1855CEFD2450545E00D8FD23 /* main.m in Sources */, 299 | 1855CF28245055F100D8FD23 /* Demo2Ctrl.m in Sources */, 300 | 1855CF25245055E600D8FD23 /* Demo1Ctrl.m in Sources */, 301 | ); 302 | runOnlyForDeploymentPostprocessing = 0; 303 | }; 304 | 1855CEFE2450545E00D8FD23 /* Sources */ = { 305 | isa = PBXSourcesBuildPhase; 306 | buildActionMask = 2147483647; 307 | files = ( 308 | 1855CF072450545E00D8FD23 /* JHCollectionViewFlowLayoutTests.m in Sources */, 309 | ); 310 | runOnlyForDeploymentPostprocessing = 0; 311 | }; 312 | 1855CF092450545E00D8FD23 /* Sources */ = { 313 | isa = PBXSourcesBuildPhase; 314 | buildActionMask = 2147483647; 315 | files = ( 316 | 1855CF122450545E00D8FD23 /* JHCollectionViewFlowLayoutUITests.m in Sources */, 317 | ); 318 | runOnlyForDeploymentPostprocessing = 0; 319 | }; 320 | /* End PBXSourcesBuildPhase section */ 321 | 322 | /* Begin PBXTargetDependency section */ 323 | 1855CF042450545E00D8FD23 /* PBXTargetDependency */ = { 324 | isa = PBXTargetDependency; 325 | target = 1855CEE62450545B00D8FD23 /* JHCollectionViewFlowLayout */; 326 | targetProxy = 1855CF032450545E00D8FD23 /* PBXContainerItemProxy */; 327 | }; 328 | 1855CF0F2450545E00D8FD23 /* PBXTargetDependency */ = { 329 | isa = PBXTargetDependency; 330 | target = 1855CEE62450545B00D8FD23 /* JHCollectionViewFlowLayout */; 331 | targetProxy = 1855CF0E2450545E00D8FD23 /* PBXContainerItemProxy */; 332 | }; 333 | /* End PBXTargetDependency section */ 334 | 335 | /* Begin PBXVariantGroup section */ 336 | 1855CEF32450545B00D8FD23 /* Main.storyboard */ = { 337 | isa = PBXVariantGroup; 338 | children = ( 339 | 1855CEF42450545B00D8FD23 /* Base */, 340 | ); 341 | name = Main.storyboard; 342 | sourceTree = ""; 343 | }; 344 | 1855CEF82450545E00D8FD23 /* LaunchScreen.storyboard */ = { 345 | isa = PBXVariantGroup; 346 | children = ( 347 | 1855CEF92450545E00D8FD23 /* Base */, 348 | ); 349 | name = LaunchScreen.storyboard; 350 | sourceTree = ""; 351 | }; 352 | /* End PBXVariantGroup section */ 353 | 354 | /* Begin XCBuildConfiguration section */ 355 | 1855CF142450545E00D8FD23 /* Debug */ = { 356 | isa = XCBuildConfiguration; 357 | buildSettings = { 358 | ALWAYS_SEARCH_USER_PATHS = NO; 359 | CLANG_ANALYZER_NONNULL = YES; 360 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 361 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 362 | CLANG_CXX_LIBRARY = "libc++"; 363 | CLANG_ENABLE_MODULES = YES; 364 | CLANG_ENABLE_OBJC_ARC = YES; 365 | CLANG_ENABLE_OBJC_WEAK = YES; 366 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 367 | CLANG_WARN_BOOL_CONVERSION = YES; 368 | CLANG_WARN_COMMA = YES; 369 | CLANG_WARN_CONSTANT_CONVERSION = YES; 370 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 371 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 372 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 373 | CLANG_WARN_EMPTY_BODY = YES; 374 | CLANG_WARN_ENUM_CONVERSION = YES; 375 | CLANG_WARN_INFINITE_RECURSION = YES; 376 | CLANG_WARN_INT_CONVERSION = YES; 377 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 378 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 379 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 380 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 381 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 382 | CLANG_WARN_STRICT_PROTOTYPES = YES; 383 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 384 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 385 | CLANG_WARN_UNREACHABLE_CODE = YES; 386 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 387 | COPY_PHASE_STRIP = NO; 388 | DEBUG_INFORMATION_FORMAT = dwarf; 389 | ENABLE_STRICT_OBJC_MSGSEND = YES; 390 | ENABLE_TESTABILITY = YES; 391 | GCC_C_LANGUAGE_STANDARD = gnu11; 392 | GCC_DYNAMIC_NO_PIC = NO; 393 | GCC_NO_COMMON_BLOCKS = YES; 394 | GCC_OPTIMIZATION_LEVEL = 0; 395 | GCC_PREPROCESSOR_DEFINITIONS = ( 396 | "DEBUG=1", 397 | "$(inherited)", 398 | ); 399 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 400 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 401 | GCC_WARN_UNDECLARED_SELECTOR = YES; 402 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 403 | GCC_WARN_UNUSED_FUNCTION = YES; 404 | GCC_WARN_UNUSED_VARIABLE = YES; 405 | IPHONEOS_DEPLOYMENT_TARGET = 13.2; 406 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 407 | MTL_FAST_MATH = YES; 408 | ONLY_ACTIVE_ARCH = YES; 409 | SDKROOT = iphoneos; 410 | }; 411 | name = Debug; 412 | }; 413 | 1855CF152450545E00D8FD23 /* Release */ = { 414 | isa = XCBuildConfiguration; 415 | buildSettings = { 416 | ALWAYS_SEARCH_USER_PATHS = NO; 417 | CLANG_ANALYZER_NONNULL = YES; 418 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 419 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 420 | CLANG_CXX_LIBRARY = "libc++"; 421 | CLANG_ENABLE_MODULES = YES; 422 | CLANG_ENABLE_OBJC_ARC = YES; 423 | CLANG_ENABLE_OBJC_WEAK = YES; 424 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 425 | CLANG_WARN_BOOL_CONVERSION = YES; 426 | CLANG_WARN_COMMA = YES; 427 | CLANG_WARN_CONSTANT_CONVERSION = YES; 428 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 429 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 430 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 431 | CLANG_WARN_EMPTY_BODY = YES; 432 | CLANG_WARN_ENUM_CONVERSION = YES; 433 | CLANG_WARN_INFINITE_RECURSION = YES; 434 | CLANG_WARN_INT_CONVERSION = YES; 435 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 436 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 437 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 438 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 439 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 440 | CLANG_WARN_STRICT_PROTOTYPES = YES; 441 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 442 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 443 | CLANG_WARN_UNREACHABLE_CODE = YES; 444 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 445 | COPY_PHASE_STRIP = NO; 446 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 447 | ENABLE_NS_ASSERTIONS = NO; 448 | ENABLE_STRICT_OBJC_MSGSEND = YES; 449 | GCC_C_LANGUAGE_STANDARD = gnu11; 450 | GCC_NO_COMMON_BLOCKS = YES; 451 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 452 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 453 | GCC_WARN_UNDECLARED_SELECTOR = YES; 454 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 455 | GCC_WARN_UNUSED_FUNCTION = YES; 456 | GCC_WARN_UNUSED_VARIABLE = YES; 457 | IPHONEOS_DEPLOYMENT_TARGET = 13.2; 458 | MTL_ENABLE_DEBUG_INFO = NO; 459 | MTL_FAST_MATH = YES; 460 | SDKROOT = iphoneos; 461 | VALIDATE_PRODUCT = YES; 462 | }; 463 | name = Release; 464 | }; 465 | 1855CF172450545E00D8FD23 /* Debug */ = { 466 | isa = XCBuildConfiguration; 467 | buildSettings = { 468 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 469 | CODE_SIGN_IDENTITY = "iPhone Developer"; 470 | CODE_SIGN_STYLE = Manual; 471 | DEVELOPMENT_TEAM = D8MERC5W3E; 472 | INFOPLIST_FILE = JHCollectionViewFlowLayout/Info.plist; 473 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 474 | LD_RUNPATH_SEARCH_PATHS = ( 475 | "$(inherited)", 476 | "@executable_path/Frameworks", 477 | ); 478 | PRODUCT_BUNDLE_IDENTIFIER = com.haocold.JHCollectionViewFlowLayout; 479 | PRODUCT_NAME = "$(TARGET_NAME)"; 480 | PROVISIONING_PROFILE_SPECIFIER = haocold.develop; 481 | TARGETED_DEVICE_FAMILY = "1,2"; 482 | }; 483 | name = Debug; 484 | }; 485 | 1855CF182450545E00D8FD23 /* Release */ = { 486 | isa = XCBuildConfiguration; 487 | buildSettings = { 488 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 489 | CODE_SIGN_IDENTITY = "iPhone Developer"; 490 | CODE_SIGN_STYLE = Manual; 491 | DEVELOPMENT_TEAM = D8MERC5W3E; 492 | INFOPLIST_FILE = JHCollectionViewFlowLayout/Info.plist; 493 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 494 | LD_RUNPATH_SEARCH_PATHS = ( 495 | "$(inherited)", 496 | "@executable_path/Frameworks", 497 | ); 498 | PRODUCT_BUNDLE_IDENTIFIER = com.haocold.JHCollectionViewFlowLayout; 499 | PRODUCT_NAME = "$(TARGET_NAME)"; 500 | PROVISIONING_PROFILE_SPECIFIER = haocold.develop; 501 | TARGETED_DEVICE_FAMILY = "1,2"; 502 | }; 503 | name = Release; 504 | }; 505 | 1855CF1A2450545E00D8FD23 /* Debug */ = { 506 | isa = XCBuildConfiguration; 507 | buildSettings = { 508 | BUNDLE_LOADER = "$(TEST_HOST)"; 509 | CODE_SIGN_STYLE = Automatic; 510 | INFOPLIST_FILE = JHCollectionViewFlowLayoutTests/Info.plist; 511 | IPHONEOS_DEPLOYMENT_TARGET = 13.2; 512 | LD_RUNPATH_SEARCH_PATHS = ( 513 | "$(inherited)", 514 | "@executable_path/Frameworks", 515 | "@loader_path/Frameworks", 516 | ); 517 | PRODUCT_BUNDLE_IDENTIFIER = com.haocold.JHCollectionViewFlowLayoutTests; 518 | PRODUCT_NAME = "$(TARGET_NAME)"; 519 | TARGETED_DEVICE_FAMILY = "1,2"; 520 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/JHCollectionViewFlowLayout.app/JHCollectionViewFlowLayout"; 521 | }; 522 | name = Debug; 523 | }; 524 | 1855CF1B2450545E00D8FD23 /* Release */ = { 525 | isa = XCBuildConfiguration; 526 | buildSettings = { 527 | BUNDLE_LOADER = "$(TEST_HOST)"; 528 | CODE_SIGN_STYLE = Automatic; 529 | INFOPLIST_FILE = JHCollectionViewFlowLayoutTests/Info.plist; 530 | IPHONEOS_DEPLOYMENT_TARGET = 13.2; 531 | LD_RUNPATH_SEARCH_PATHS = ( 532 | "$(inherited)", 533 | "@executable_path/Frameworks", 534 | "@loader_path/Frameworks", 535 | ); 536 | PRODUCT_BUNDLE_IDENTIFIER = com.haocold.JHCollectionViewFlowLayoutTests; 537 | PRODUCT_NAME = "$(TARGET_NAME)"; 538 | TARGETED_DEVICE_FAMILY = "1,2"; 539 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/JHCollectionViewFlowLayout.app/JHCollectionViewFlowLayout"; 540 | }; 541 | name = Release; 542 | }; 543 | 1855CF1D2450545E00D8FD23 /* Debug */ = { 544 | isa = XCBuildConfiguration; 545 | buildSettings = { 546 | CODE_SIGN_STYLE = Automatic; 547 | INFOPLIST_FILE = JHCollectionViewFlowLayoutUITests/Info.plist; 548 | LD_RUNPATH_SEARCH_PATHS = ( 549 | "$(inherited)", 550 | "@executable_path/Frameworks", 551 | "@loader_path/Frameworks", 552 | ); 553 | PRODUCT_BUNDLE_IDENTIFIER = com.haocold.JHCollectionViewFlowLayoutUITests; 554 | PRODUCT_NAME = "$(TARGET_NAME)"; 555 | TARGETED_DEVICE_FAMILY = "1,2"; 556 | TEST_TARGET_NAME = JHCollectionViewFlowLayout; 557 | }; 558 | name = Debug; 559 | }; 560 | 1855CF1E2450545E00D8FD23 /* Release */ = { 561 | isa = XCBuildConfiguration; 562 | buildSettings = { 563 | CODE_SIGN_STYLE = Automatic; 564 | INFOPLIST_FILE = JHCollectionViewFlowLayoutUITests/Info.plist; 565 | LD_RUNPATH_SEARCH_PATHS = ( 566 | "$(inherited)", 567 | "@executable_path/Frameworks", 568 | "@loader_path/Frameworks", 569 | ); 570 | PRODUCT_BUNDLE_IDENTIFIER = com.haocold.JHCollectionViewFlowLayoutUITests; 571 | PRODUCT_NAME = "$(TARGET_NAME)"; 572 | TARGETED_DEVICE_FAMILY = "1,2"; 573 | TEST_TARGET_NAME = JHCollectionViewFlowLayout; 574 | }; 575 | name = Release; 576 | }; 577 | /* End XCBuildConfiguration section */ 578 | 579 | /* Begin XCConfigurationList section */ 580 | 1855CEE22450545B00D8FD23 /* Build configuration list for PBXProject "JHCollectionViewFlowLayout" */ = { 581 | isa = XCConfigurationList; 582 | buildConfigurations = ( 583 | 1855CF142450545E00D8FD23 /* Debug */, 584 | 1855CF152450545E00D8FD23 /* Release */, 585 | ); 586 | defaultConfigurationIsVisible = 0; 587 | defaultConfigurationName = Release; 588 | }; 589 | 1855CF162450545E00D8FD23 /* Build configuration list for PBXNativeTarget "JHCollectionViewFlowLayout" */ = { 590 | isa = XCConfigurationList; 591 | buildConfigurations = ( 592 | 1855CF172450545E00D8FD23 /* Debug */, 593 | 1855CF182450545E00D8FD23 /* Release */, 594 | ); 595 | defaultConfigurationIsVisible = 0; 596 | defaultConfigurationName = Release; 597 | }; 598 | 1855CF192450545E00D8FD23 /* Build configuration list for PBXNativeTarget "JHCollectionViewFlowLayoutTests" */ = { 599 | isa = XCConfigurationList; 600 | buildConfigurations = ( 601 | 1855CF1A2450545E00D8FD23 /* Debug */, 602 | 1855CF1B2450545E00D8FD23 /* Release */, 603 | ); 604 | defaultConfigurationIsVisible = 0; 605 | defaultConfigurationName = Release; 606 | }; 607 | 1855CF1C2450545E00D8FD23 /* Build configuration list for PBXNativeTarget "JHCollectionViewFlowLayoutUITests" */ = { 608 | isa = XCConfigurationList; 609 | buildConfigurations = ( 610 | 1855CF1D2450545E00D8FD23 /* Debug */, 611 | 1855CF1E2450545E00D8FD23 /* Release */, 612 | ); 613 | defaultConfigurationIsVisible = 0; 614 | defaultConfigurationName = Release; 615 | }; 616 | /* End XCConfigurationList section */ 617 | }; 618 | rootObject = 1855CEDF2450545B00D8FD23 /* Project object */; 619 | } 620 | -------------------------------------------------------------------------------- /Example/JHCollectionViewFlowLayout/JHCollectionViewFlowLayout.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/JHCollectionViewFlowLayout/JHCollectionViewFlowLayout.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Example/JHCollectionViewFlowLayout/JHCollectionViewFlowLayout.xcodeproj/project.xcworkspace/xcuserdata/apple.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xjh093/JHCollectionViewFlowLayout/170372d43e416eb967bc95804e39dec2f25178f6/Example/JHCollectionViewFlowLayout/JHCollectionViewFlowLayout.xcodeproj/project.xcworkspace/xcuserdata/apple.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Example/JHCollectionViewFlowLayout/JHCollectionViewFlowLayout.xcodeproj/xcuserdata/apple.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /Example/JHCollectionViewFlowLayout/JHCollectionViewFlowLayout.xcodeproj/xcuserdata/apple.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | JHCollectionViewFlowLayout.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Example/JHCollectionViewFlowLayout/JHCollectionViewFlowLayout/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // JHCollectionViewFlowLayout 4 | // 5 | // Created by HaoCold on 2020/4/22. 6 | // Copyright © 2020 HaoCold. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow * window; 14 | 15 | @end 16 | 17 | -------------------------------------------------------------------------------- /Example/JHCollectionViewFlowLayout/JHCollectionViewFlowLayout/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // JHCollectionViewFlowLayout 4 | // 5 | // Created by HaoCold on 2020/4/22. 6 | // Copyright © 2020 HaoCold. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Example/JHCollectionViewFlowLayout/JHCollectionViewFlowLayout/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 | } -------------------------------------------------------------------------------- /Example/JHCollectionViewFlowLayout/JHCollectionViewFlowLayout/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Example/JHCollectionViewFlowLayout/JHCollectionViewFlowLayout/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 | -------------------------------------------------------------------------------- /Example/JHCollectionViewFlowLayout/JHCollectionViewFlowLayout/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /Example/JHCollectionViewFlowLayout/JHCollectionViewFlowLayout/Demo1Ctrl.h: -------------------------------------------------------------------------------- 1 | // 2 | // Demo1Ctrl.h 3 | // JHCollectionViewFlowLayout 4 | // 5 | // Created by HaoCold on 2020/4/22. 6 | // Copyright © 2020 HaoCold. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface Demo1Ctrl : UIViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /Example/JHCollectionViewFlowLayout/JHCollectionViewFlowLayout/Demo1Ctrl.m: -------------------------------------------------------------------------------- 1 | // 2 | // Demo1Ctrl.m 3 | // JHCollectionViewFlowLayout 4 | // 5 | // Created by HaoCold on 2020/4/22. 6 | // Copyright © 2020 HaoCold. All rights reserved. 7 | // 8 | 9 | #import "Demo1Ctrl.h" 10 | #import "DemoCell.h" 11 | 12 | @interface Demo1Ctrl () 13 | @property (nonatomic, strong) UICollectionView *collectionView; 14 | @property (nonatomic, strong) NSMutableArray *dataArray; 15 | @end 16 | 17 | @implementation Demo1Ctrl 18 | 19 | - (void)viewDidLoad { 20 | [super viewDidLoad]; 21 | // Do any additional setup after loading the view. 22 | 23 | self.dataArray = @[].mutableCopy; 24 | NSMutableArray *marr = @[].mutableCopy; 25 | for (int i = 0; i < 15; ++i) { 26 | [marr addObject:@[@""]]; 27 | } 28 | self.dataArray.array = marr; 29 | 30 | [self.view addSubview:[[UIView alloc] init]]; 31 | [self.view addSubview:self.collectionView]; 32 | 33 | self.view.backgroundColor = [UIColor whiteColor]; 34 | } 35 | 36 | - (NSInteger) collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { 37 | return self.dataArray.count; 38 | } 39 | - (UICollectionViewCell*) collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { 40 | 41 | DemoCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"DemoCell" forIndexPath:indexPath]; 42 | cell.nameLabel.text = [NSString stringWithFormat:@"第%@个",@(indexPath.item)]; 43 | cell.nameLabel.backgroundColor = [UIColor colorWithRed:(arc4random()%256)/255.0 green:(arc4random()%256)/255.0 blue:(arc4random()%256)/255.0 alpha:1]; 44 | return cell; 45 | } 46 | 47 | - (UICollectionView *)collectionView{ 48 | if (!_collectionView) { 49 | 50 | CGFloat width = [UIScreen mainScreen].bounds.size.width; 51 | 52 | UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; 53 | CGFloat W = (width-3)/4; 54 | //cell尺寸 55 | layout.itemSize = CGSizeMake(W, W-.5); 56 | layout.minimumLineSpacing = 1; //行距 因为是左右滚动,这里是左右间隔 57 | layout.minimumInteritemSpacing = 1; //因为是左右滚动,这里是上下间隔 58 | layout.sectionInset = UIEdgeInsetsMake(0, 0, 0, 0); 59 | layout.scrollDirection = 1; //左右滚动 60 | 61 | _collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 100, width, width/2.0) collectionViewLayout:layout]; 62 | _collectionView.backgroundColor = [UIColor lightGrayColor]; 63 | _collectionView.delegate = self; 64 | _collectionView.dataSource = self; 65 | _collectionView.showsHorizontalScrollIndicator = NO; 66 | _collectionView.pagingEnabled = YES; 67 | [_collectionView registerClass:[DemoCell class] forCellWithReuseIdentifier:@"DemoCell"]; 68 | } 69 | return _collectionView; 70 | } 71 | 72 | /* 73 | #pragma mark - Navigation 74 | 75 | // In a storyboard-based application, you will often want to do a little preparation before navigation 76 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 77 | // Get the new view controller using [segue destinationViewController]. 78 | // Pass the selected object to the new view controller. 79 | } 80 | */ 81 | 82 | @end 83 | -------------------------------------------------------------------------------- /Example/JHCollectionViewFlowLayout/JHCollectionViewFlowLayout/Demo2Ctrl.h: -------------------------------------------------------------------------------- 1 | // 2 | // Demo2Ctrl.h 3 | // JHCollectionViewFlowLayout 4 | // 5 | // Created by HaoCold on 2020/4/22. 6 | // Copyright © 2020 HaoCold. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface Demo2Ctrl : UIViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /Example/JHCollectionViewFlowLayout/JHCollectionViewFlowLayout/Demo2Ctrl.m: -------------------------------------------------------------------------------- 1 | // 2 | // Demo2Ctrl.m 3 | // JHCollectionViewFlowLayout 4 | // 5 | // Created by HaoCold on 2020/4/22. 6 | // Copyright © 2020 HaoCold. All rights reserved. 7 | // 8 | 9 | #import "Demo2Ctrl.h" 10 | #import "DemoCell.h" 11 | #import "JHCollectionViewFlowLayout.h" 12 | 13 | @interface Demo2Ctrl () 14 | @property (nonatomic, strong) UICollectionView *collectionView; 15 | @property (nonatomic, strong) NSMutableArray *dataArray; 16 | 17 | @end 18 | 19 | @implementation Demo2Ctrl 20 | 21 | - (void)viewDidLoad { 22 | [super viewDidLoad]; 23 | // Do any additional setup after loading the view. 24 | 25 | self.dataArray = @[].mutableCopy; 26 | NSMutableArray *marr = @[].mutableCopy; 27 | for (int i = 0; i < 15; ++i) { 28 | [marr addObject:@[@""]]; 29 | } 30 | self.dataArray.array = marr; 31 | 32 | [self.view addSubview:[[UIView alloc] init]]; 33 | [self.view addSubview:self.collectionView]; 34 | 35 | self.view.backgroundColor = [UIColor whiteColor]; 36 | } 37 | 38 | - (NSInteger) collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { 39 | return self.dataArray.count; 40 | } 41 | 42 | - (UICollectionViewCell*) collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { 43 | 44 | DemoCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"DemoCell" forIndexPath:indexPath]; 45 | cell.nameLabel.text = [NSString stringWithFormat:@"第%@个",@(indexPath.item)]; 46 | cell.nameLabel.backgroundColor = [UIColor colorWithRed:(arc4random()%256)/255.0 green:(arc4random()%256)/255.0 blue:(arc4random()%256)/255.0 alpha:1]; 47 | return cell; 48 | } 49 | 50 | - (UICollectionView *)collectionView{ 51 | if (!_collectionView) { 52 | 53 | CGFloat width = [UIScreen mainScreen].bounds.size.width; 54 | 55 | JHCollectionViewFlowLayout *layout = [[JHCollectionViewFlowLayout alloc] init]; 56 | CGFloat W = (width-3)/4; 57 | layout.scrollDirection = 1; //左右滚动 58 | layout.size = CGSizeMake(W, W-.5); 59 | layout.columnSpacing = 2; 60 | layout.rowSpacing = 2; 61 | layout.row = 3; 62 | layout.column = 4; 63 | layout.showLastPageFull = NO; // 不完全展示最后一页 64 | layout.pageWidth = width; 65 | //layout.pageWidth = width - 50; 66 | //layout.sectionInset = UIEdgeInsetsZero; 67 | layout.sectionInset = UIEdgeInsetsMake(20, 10, 20, 10); 68 | 69 | _collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 100, layout.collectionViewSize.width, layout.collectionViewSize.height) collectionViewLayout:layout]; 70 | _collectionView.backgroundColor = [UIColor lightGrayColor]; 71 | _collectionView.delegate = self; 72 | _collectionView.dataSource = self; 73 | _collectionView.showsHorizontalScrollIndicator = NO; 74 | _collectionView.pagingEnabled = YES; 75 | [_collectionView registerClass:[DemoCell class] forCellWithReuseIdentifier:@"DemoCell"]; 76 | } 77 | return _collectionView; 78 | } 79 | 80 | /* 81 | #pragma mark - Navigation 82 | 83 | // In a storyboard-based application, you will often want to do a little preparation before navigation 84 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 85 | // Get the new view controller using [segue destinationViewController]. 86 | // Pass the selected object to the new view controller. 87 | } 88 | */ 89 | 90 | @end 91 | -------------------------------------------------------------------------------- /Example/JHCollectionViewFlowLayout/JHCollectionViewFlowLayout/DemoCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // DemoCell.h 3 | // JHCollectionViewFlowLayout 4 | // 5 | // Created by HaoCold on 2020/4/22. 6 | // Copyright © 2020 HaoCold. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface DemoCell : UICollectionViewCell 14 | @property (nonatomic, strong) UILabel *nameLabel; 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /Example/JHCollectionViewFlowLayout/JHCollectionViewFlowLayout/DemoCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // DemoCell.m 3 | // JHCollectionViewFlowLayout 4 | // 5 | // Created by HaoCold on 2020/4/22. 6 | // Copyright © 2020 HaoCold. All rights reserved. 7 | // 8 | 9 | #import "DemoCell.h" 10 | 11 | @implementation DemoCell 12 | 13 | - (instancetype)initWithFrame:(CGRect)frame 14 | { 15 | self = [super initWithFrame:frame]; 16 | if (self) { 17 | UILabel *label = [[UILabel alloc] init]; 18 | label.frame = self.bounds; 19 | label.text = @""; 20 | label.textColor = [UIColor whiteColor]; 21 | label.font = [UIFont systemFontOfSize:14]; 22 | label.textAlignment = NSTextAlignmentCenter; 23 | [self.contentView addSubview:label]; 24 | _nameLabel = label; 25 | } 26 | return self; 27 | } 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /Example/JHCollectionViewFlowLayout/JHCollectionViewFlowLayout/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 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 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 | -------------------------------------------------------------------------------- /Example/JHCollectionViewFlowLayout/JHCollectionViewFlowLayout/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // JHCollectionViewFlowLayout 4 | // 5 | // Created by HaoCold on 2020/4/22. 6 | // Copyright © 2020 HaoCold. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /Example/JHCollectionViewFlowLayout/JHCollectionViewFlowLayout/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // JHCollectionViewFlowLayout 4 | // 5 | // Created by HaoCold on 2020/4/22. 6 | // Copyright © 2020 HaoCold. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | 11 | @interface ViewController () 12 | @property (nonatomic, strong) UITableView *tableView; 13 | @property (nonatomic, strong) NSArray *dataArray; 14 | @end 15 | 16 | @implementation ViewController 17 | 18 | - (void)viewDidLoad { 19 | [super viewDidLoad]; 20 | // Do any additional setup after loading the view. 21 | 22 | _dataArray = @[@"系统横向排版",@"自定义横向排版"]; 23 | self.navigationItem.title = @"排版"; 24 | [self.view addSubview:self.tableView]; 25 | } 26 | 27 | #pragma mark ---UITableViewDataSource 28 | 29 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 30 | { 31 | return _dataArray.count; 32 | } 33 | 34 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 35 | { 36 | static NSString *ID = @"resueID"; 37 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; 38 | if (cell == nil) { 39 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID]; 40 | } 41 | cell.textLabel.text = _dataArray[indexPath.row]; 42 | return cell; 43 | } 44 | 45 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 46 | { 47 | NSInteger index = indexPath.row + 1; 48 | NSString *ctrl = [NSString stringWithFormat:@"Demo%@Ctrl",@(index)]; 49 | UIViewController *cls = [NSClassFromString(ctrl) new]; 50 | cls.title = _dataArray[indexPath.row]; 51 | [self.navigationController pushViewController:cls animated:YES]; 52 | } 53 | 54 | - (UITableView *)tableView{ 55 | if (!_tableView) { 56 | UITableView *tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:0]; 57 | tableView.delegate = self; 58 | tableView.dataSource = self; 59 | tableView.tableFooterView = [[UIView alloc] init]; 60 | tableView.showsVerticalScrollIndicator = NO; 61 | tableView.separatorStyle = UITableViewCellSeparatorStyleNone; 62 | _tableView = tableView; 63 | } 64 | return _tableView; 65 | } 66 | @end 67 | -------------------------------------------------------------------------------- /Example/JHCollectionViewFlowLayout/JHCollectionViewFlowLayout/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // JHCollectionViewFlowLayout 4 | // 5 | // Created by HaoCold on 2020/4/22. 6 | // Copyright © 2020 HaoCold. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | NSString * appDelegateClassName; 14 | @autoreleasepool { 15 | // Setup code that might create autoreleased objects goes here. 16 | appDelegateClassName = NSStringFromClass([AppDelegate class]); 17 | } 18 | return UIApplicationMain(argc, argv, nil, appDelegateClassName); 19 | } 20 | -------------------------------------------------------------------------------- /Example/JHCollectionViewFlowLayout/JHCollectionViewFlowLayoutTests/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 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Example/JHCollectionViewFlowLayout/JHCollectionViewFlowLayoutTests/JHCollectionViewFlowLayoutTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // JHCollectionViewFlowLayoutTests.m 3 | // JHCollectionViewFlowLayoutTests 4 | // 5 | // Created by HaoCold on 2020/4/22. 6 | // Copyright © 2020 HaoCold. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface JHCollectionViewFlowLayoutTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation JHCollectionViewFlowLayoutTests 16 | 17 | - (void)setUp { 18 | // Put setup code here. This method is called before the invocation of each test method in the class. 19 | } 20 | 21 | - (void)tearDown { 22 | // Put teardown code here. This method is called after the invocation of each test method in the class. 23 | } 24 | 25 | - (void)testExample { 26 | // This is an example of a functional test case. 27 | // Use XCTAssert and related functions to verify your tests produce the correct results. 28 | } 29 | 30 | - (void)testPerformanceExample { 31 | // This is an example of a performance test case. 32 | [self measureBlock:^{ 33 | // Put the code you want to measure the time of here. 34 | }]; 35 | } 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /Example/JHCollectionViewFlowLayout/JHCollectionViewFlowLayoutUITests/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 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Example/JHCollectionViewFlowLayout/JHCollectionViewFlowLayoutUITests/JHCollectionViewFlowLayoutUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // JHCollectionViewFlowLayoutUITests.m 3 | // JHCollectionViewFlowLayoutUITests 4 | // 5 | // Created by HaoCold on 2020/4/22. 6 | // Copyright © 2020 HaoCold. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface JHCollectionViewFlowLayoutUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation JHCollectionViewFlowLayoutUITests 16 | 17 | - (void)setUp { 18 | // Put setup code here. This method is called before the invocation of each test method in the class. 19 | 20 | // In UI tests it is usually best to stop immediately when a failure occurs. 21 | self.continueAfterFailure = NO; 22 | 23 | // 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. 24 | } 25 | 26 | - (void)tearDown { 27 | // Put teardown code here. This method is called after the invocation of each test method in the class. 28 | } 29 | 30 | - (void)testExample { 31 | // UI tests must launch the application that they test. 32 | XCUIApplication *app = [[XCUIApplication alloc] init]; 33 | [app launch]; 34 | 35 | // Use recording to get started writing UI tests. 36 | // Use XCTAssert and related functions to verify your tests produce the correct results. 37 | } 38 | 39 | - (void)testLaunchPerformance { 40 | if (@available(macOS 10.15, iOS 13.0, tvOS 13.0, *)) { 41 | // This measures how long it takes to launch your application. 42 | [self measureWithMetrics:@[XCTOSSignpostMetric.applicationLaunchMetric] block:^{ 43 | [[[XCUIApplication alloc] init] launch]; 44 | }]; 45 | } 46 | } 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /JHCollectionViewFlowLayout/JHCollectionViewFlowLayout.h: -------------------------------------------------------------------------------- 1 | // 2 | // JHCollectionViewFlowLayout.h 3 | // JHKit 4 | // 5 | // Created by HaoCold on 2017/9/13. 6 | // Copyright © 2017年 HaoCold. All rights reserved. 7 | // 8 | // MIT License 9 | // 10 | // Copyright (c) 2017 xjh093 11 | // 12 | // Permission is hereby granted, free of charge, to any person obtaining a copy 13 | // of this software and associated documentation files (the "Software"), to deal 14 | // in the Software without restriction, including without limitation the rights 15 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | // copies of the Software, and to permit persons to whom the Software is 17 | // furnished to do so, subject to the following conditions: 18 | // 19 | // The above copyright notice and this permission notice shall be included in all 20 | // copies or substantial portions of the Software. 21 | // 22 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | // SOFTWARE. 29 | 30 | #import 31 | 32 | @interface JHCollectionViewFlowLayout : UICollectionViewFlowLayout 33 | ///一页展示行数 34 | @property (nonatomic, assign) NSInteger row; 35 | ///一页展示列数 36 | @property (nonatomic, assign) NSInteger column; 37 | ///行间距 38 | @property (nonatomic, assign) CGFloat rowSpacing; 39 | ///列间距 40 | @property (nonatomic, assign) CGFloat columnSpacing; 41 | ///item大小 42 | @property (nonatomic, assign) CGSize size; 43 | ///一页的宽度,默认 [UIScreen mainScreen].bounds.size.width 44 | @property (nonatomic, assign) CGFloat pageWidth; 45 | ///默认YES。根据最后一页的个数,是否展示完整的一页 46 | @property (nonatomic, assign) BOOL showLastPageFull; 47 | ///collectionView Size 48 | @property (nonatomic, assign, readonly) CGSize collectionViewSize; 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /JHCollectionViewFlowLayout/JHCollectionViewFlowLayout.m: -------------------------------------------------------------------------------- 1 | // 2 | // JHCollectionViewFlowLayout.m 3 | // JHKit 4 | // 5 | // Created by HaoCold on 2017/9/13. 6 | // Copyright © 2017年 HaoCold. All rights reserved. 7 | // 8 | // MIT License 9 | // 10 | // Copyright (c) 2017 xjh093 11 | // 12 | // Permission is hereby granted, free of charge, to any person obtaining a copy 13 | // of this software and associated documentation files (the "Software"), to deal 14 | // in the Software without restriction, including without limitation the rights 15 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | // copies of the Software, and to permit persons to whom the Software is 17 | // furnished to do so, subject to the following conditions: 18 | // 19 | // The above copyright notice and this permission notice shall be included in all 20 | // copies or substantial portions of the Software. 21 | // 22 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | // SOFTWARE. 29 | 30 | #import "JHCollectionViewFlowLayout.h" 31 | 32 | @interface JHCollectionViewFlowLayout() 33 | @property (strong, nonatomic) NSMutableArray *attributesArray; 34 | @property (nonatomic, assign) CGFloat onePageWidth; 35 | @end 36 | 37 | @implementation JHCollectionViewFlowLayout 38 | 39 | - (instancetype)init 40 | { 41 | self = [super init]; 42 | if (self) { 43 | _showLastPageFull = YES; 44 | _pageWidth = [UIScreen mainScreen].bounds.size.width; 45 | } 46 | return self; 47 | } 48 | 49 | - (void)prepareLayout 50 | { 51 | [super prepareLayout]; 52 | 53 | _attributesArray = @[].mutableCopy; 54 | _onePageWidth = (_size.width + _columnSpacing) * _column - _columnSpacing; 55 | 56 | NSUInteger count = [self.collectionView numberOfItemsInSection:0]; 57 | for (NSUInteger i = 0; i < count; i++) { 58 | NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0]; 59 | UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForItemAtIndexPath:indexPath]; 60 | [_attributesArray addObject:attributes]; 61 | } 62 | } 63 | 64 | //计算每个item的frame 65 | - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{ 66 | UICollectionViewLayoutAttributes *attribute = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; 67 | 68 | NSInteger index = indexPath.item; 69 | 70 | NSInteger page = index / (_row * _column); 71 | 72 | // % 运算 确定 x 是 0,1,2 ... _column-1 73 | CGFloat x = (index % _column) * (_size.width + _columnSpacing) + page * (_onePageWidth + _columnSpacing) + self.sectionInset.left; 74 | // / 运算 确定 y 是 在哪行(一行有 column 个), % 确定在 0,1,2 ... _row-1 行内的哪行 75 | CGFloat y = (index / _column % _row) * (_size.height + _rowSpacing) + self.sectionInset.top; 76 | 77 | attribute.frame = CGRectMake(x, y, _size.width, _size.height); 78 | 79 | return attribute; 80 | 81 | } 82 | 83 | //返回所有item的frame 84 | - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect{ 85 | return _attributesArray; 86 | } 87 | 88 | //返回总的可见尺寸 89 | //避免一页未排满,滑动显示不全 90 | - (CGSize)collectionViewContentSize{ 91 | CGFloat width = (CGFloat)ceil(_attributesArray.count/(_row * _column * 1.0)) * _onePageWidth; 92 | if (!_showLastPageFull) { 93 | NSInteger lastCount = _attributesArray.count%(_row * _column); 94 | if (lastCount > 0 && lastCount < _column) { 95 | width = _attributesArray.count/(_row * _column) * _onePageWidth; 96 | width += (_size.width + _columnSpacing)*lastCount; 97 | } 98 | } 99 | width += self.sectionInset.left + self.sectionInset.right; 100 | CGFloat height = (_size.height + _rowSpacing) * _row + self.sectionInset.top + self.sectionInset.bottom; 101 | return CGSizeMake(width, height); 102 | } 103 | 104 | - (CGSize)collectionViewSize 105 | { 106 | return CGSizeMake(_pageWidth, (_size.height + _rowSpacing) * _row + self.sectionInset.top + self.sectionInset.bottom); 107 | } 108 | 109 | @end 110 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 xjh093 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JHCollectionViewFlowLayout 2 | CollectionView horizontal layout 3 | - CollectionView横向排版 4 | 5 | --- 6 | 7 | # What 8 | System layout 9 | 10 | ![image](https://github.com/xjh093/JHCollectionViewFlowLayout/blob/master/image/system.png) 11 | 12 | Custom layout 13 | 14 | ![image](https://github.com/xjh093/JHCollectionViewFlowLayout/blob/master/image/custom.png) 15 | 16 | --- 17 | 18 | # Log 19 | 20 | ### 2020-04-22 21 | - add `collectionViewSize`. 22 | - support `sectionInset`. 23 | 24 | ### 2019-11-8 25 | - add `showLastPageFull`. 26 | 27 | ### 2017-09-18 28 | - upload. 29 | 30 | --- 31 | 32 | -------------------------------------------------------------------------------- /image/custom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xjh093/JHCollectionViewFlowLayout/170372d43e416eb967bc95804e39dec2f25178f6/image/custom.png -------------------------------------------------------------------------------- /image/system.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xjh093/JHCollectionViewFlowLayout/170372d43e416eb967bc95804e39dec2f25178f6/image/system.png --------------------------------------------------------------------------------