├── .gitignore ├── README.md ├── SheetViewSwift.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── SheetViewSwift ├── AppDelegate.swift ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Info.plist ├── SheetView │ ├── ContentViewCell.swift │ └── SheetView.swift └── ViewController.swift ├── SheetViewSwiftTests ├── Info.plist └── SheetViewSwiftTests.swift └── SheetViewSwiftUITests ├── Info.plist └── SheetViewSwiftUITests.swift /.gitignore: -------------------------------------------------------------------------------- 1 | SheetViewSwift.xcodeproj/xcuserdata 2 | SheetViewSwift.xcodeproj/project.xcworkspace/xcuserdata 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SheetView 2 | 同时支持横向和竖向滑动的表格,可以用来很方便的展示excel等表格数据 3 | 4 | 另有objective-C版本:https://github.com/nothot/SheetView 5 | 6 | ## 2017.12.20 7 | 单元格支持点击事件回调 8 | 9 | ## 2017.12.15 10 | 列和行可以独立设置宽高 11 | -------------------------------------------------------------------------------- /SheetViewSwift.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | C520A1D51F7E6C9A0054B1CB /* ContentViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C520A1D41F7E6C9A0054B1CB /* ContentViewCell.swift */; }; 11 | C5C90C7E1F7E4E0000EB7BF0 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5C90C7D1F7E4E0000EB7BF0 /* AppDelegate.swift */; }; 12 | C5C90C801F7E4E0000EB7BF0 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5C90C7F1F7E4E0000EB7BF0 /* ViewController.swift */; }; 13 | C5C90C831F7E4E0000EB7BF0 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C5C90C811F7E4E0000EB7BF0 /* Main.storyboard */; }; 14 | C5C90C851F7E4E0000EB7BF0 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C5C90C841F7E4E0000EB7BF0 /* Assets.xcassets */; }; 15 | C5C90C881F7E4E0000EB7BF0 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C5C90C861F7E4E0000EB7BF0 /* LaunchScreen.storyboard */; }; 16 | C5C90C931F7E4E0000EB7BF0 /* SheetViewSwiftTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5C90C921F7E4E0000EB7BF0 /* SheetViewSwiftTests.swift */; }; 17 | C5C90C9E1F7E4E0000EB7BF0 /* SheetViewSwiftUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5C90C9D1F7E4E0000EB7BF0 /* SheetViewSwiftUITests.swift */; }; 18 | C5C90CAD1F7E4E5500EB7BF0 /* SheetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C5C90CAC1F7E4E5500EB7BF0 /* SheetView.swift */; }; 19 | /* End PBXBuildFile section */ 20 | 21 | /* Begin PBXContainerItemProxy section */ 22 | C5C90C8F1F7E4E0000EB7BF0 /* PBXContainerItemProxy */ = { 23 | isa = PBXContainerItemProxy; 24 | containerPortal = C5C90C721F7E4E0000EB7BF0 /* Project object */; 25 | proxyType = 1; 26 | remoteGlobalIDString = C5C90C791F7E4E0000EB7BF0; 27 | remoteInfo = SheetViewSwift; 28 | }; 29 | C5C90C9A1F7E4E0000EB7BF0 /* PBXContainerItemProxy */ = { 30 | isa = PBXContainerItemProxy; 31 | containerPortal = C5C90C721F7E4E0000EB7BF0 /* Project object */; 32 | proxyType = 1; 33 | remoteGlobalIDString = C5C90C791F7E4E0000EB7BF0; 34 | remoteInfo = SheetViewSwift; 35 | }; 36 | /* End PBXContainerItemProxy section */ 37 | 38 | /* Begin PBXFileReference section */ 39 | C520A1D41F7E6C9A0054B1CB /* ContentViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentViewCell.swift; sourceTree = ""; }; 40 | C5C90C7A1F7E4E0000EB7BF0 /* SheetViewSwift.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SheetViewSwift.app; sourceTree = BUILT_PRODUCTS_DIR; }; 41 | C5C90C7D1F7E4E0000EB7BF0 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 42 | C5C90C7F1F7E4E0000EB7BF0 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 43 | C5C90C821F7E4E0000EB7BF0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 44 | C5C90C841F7E4E0000EB7BF0 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 45 | C5C90C871F7E4E0000EB7BF0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 46 | C5C90C891F7E4E0000EB7BF0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 47 | C5C90C8E1F7E4E0000EB7BF0 /* SheetViewSwiftTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SheetViewSwiftTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 48 | C5C90C921F7E4E0000EB7BF0 /* SheetViewSwiftTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SheetViewSwiftTests.swift; sourceTree = ""; }; 49 | C5C90C941F7E4E0000EB7BF0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 50 | C5C90C991F7E4E0000EB7BF0 /* SheetViewSwiftUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SheetViewSwiftUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 51 | C5C90C9D1F7E4E0000EB7BF0 /* SheetViewSwiftUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SheetViewSwiftUITests.swift; sourceTree = ""; }; 52 | C5C90C9F1F7E4E0000EB7BF0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 53 | C5C90CAC1F7E4E5500EB7BF0 /* SheetView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SheetView.swift; sourceTree = ""; }; 54 | /* End PBXFileReference section */ 55 | 56 | /* Begin PBXFrameworksBuildPhase section */ 57 | C5C90C771F7E4E0000EB7BF0 /* Frameworks */ = { 58 | isa = PBXFrameworksBuildPhase; 59 | buildActionMask = 2147483647; 60 | files = ( 61 | ); 62 | runOnlyForDeploymentPostprocessing = 0; 63 | }; 64 | C5C90C8B1F7E4E0000EB7BF0 /* Frameworks */ = { 65 | isa = PBXFrameworksBuildPhase; 66 | buildActionMask = 2147483647; 67 | files = ( 68 | ); 69 | runOnlyForDeploymentPostprocessing = 0; 70 | }; 71 | C5C90C961F7E4E0000EB7BF0 /* Frameworks */ = { 72 | isa = PBXFrameworksBuildPhase; 73 | buildActionMask = 2147483647; 74 | files = ( 75 | ); 76 | runOnlyForDeploymentPostprocessing = 0; 77 | }; 78 | /* End PBXFrameworksBuildPhase section */ 79 | 80 | /* Begin PBXGroup section */ 81 | C5C90C711F7E4E0000EB7BF0 = { 82 | isa = PBXGroup; 83 | children = ( 84 | C5C90C7C1F7E4E0000EB7BF0 /* SheetViewSwift */, 85 | C5C90C911F7E4E0000EB7BF0 /* SheetViewSwiftTests */, 86 | C5C90C9C1F7E4E0000EB7BF0 /* SheetViewSwiftUITests */, 87 | C5C90C7B1F7E4E0000EB7BF0 /* Products */, 88 | ); 89 | sourceTree = ""; 90 | }; 91 | C5C90C7B1F7E4E0000EB7BF0 /* Products */ = { 92 | isa = PBXGroup; 93 | children = ( 94 | C5C90C7A1F7E4E0000EB7BF0 /* SheetViewSwift.app */, 95 | C5C90C8E1F7E4E0000EB7BF0 /* SheetViewSwiftTests.xctest */, 96 | C5C90C991F7E4E0000EB7BF0 /* SheetViewSwiftUITests.xctest */, 97 | ); 98 | name = Products; 99 | sourceTree = ""; 100 | }; 101 | C5C90C7C1F7E4E0000EB7BF0 /* SheetViewSwift */ = { 102 | isa = PBXGroup; 103 | children = ( 104 | C5C90CAB1F7E4E2500EB7BF0 /* SheetView */, 105 | C5C90C7D1F7E4E0000EB7BF0 /* AppDelegate.swift */, 106 | C5C90C7F1F7E4E0000EB7BF0 /* ViewController.swift */, 107 | C5C90C811F7E4E0000EB7BF0 /* Main.storyboard */, 108 | C5C90C841F7E4E0000EB7BF0 /* Assets.xcassets */, 109 | C5C90C861F7E4E0000EB7BF0 /* LaunchScreen.storyboard */, 110 | C5C90C891F7E4E0000EB7BF0 /* Info.plist */, 111 | ); 112 | path = SheetViewSwift; 113 | sourceTree = ""; 114 | }; 115 | C5C90C911F7E4E0000EB7BF0 /* SheetViewSwiftTests */ = { 116 | isa = PBXGroup; 117 | children = ( 118 | C5C90C921F7E4E0000EB7BF0 /* SheetViewSwiftTests.swift */, 119 | C5C90C941F7E4E0000EB7BF0 /* Info.plist */, 120 | ); 121 | path = SheetViewSwiftTests; 122 | sourceTree = ""; 123 | }; 124 | C5C90C9C1F7E4E0000EB7BF0 /* SheetViewSwiftUITests */ = { 125 | isa = PBXGroup; 126 | children = ( 127 | C5C90C9D1F7E4E0000EB7BF0 /* SheetViewSwiftUITests.swift */, 128 | C5C90C9F1F7E4E0000EB7BF0 /* Info.plist */, 129 | ); 130 | path = SheetViewSwiftUITests; 131 | sourceTree = ""; 132 | }; 133 | C5C90CAB1F7E4E2500EB7BF0 /* SheetView */ = { 134 | isa = PBXGroup; 135 | children = ( 136 | C5C90CAC1F7E4E5500EB7BF0 /* SheetView.swift */, 137 | C520A1D41F7E6C9A0054B1CB /* ContentViewCell.swift */, 138 | ); 139 | path = SheetView; 140 | sourceTree = ""; 141 | }; 142 | /* End PBXGroup section */ 143 | 144 | /* Begin PBXNativeTarget section */ 145 | C5C90C791F7E4E0000EB7BF0 /* SheetViewSwift */ = { 146 | isa = PBXNativeTarget; 147 | buildConfigurationList = C5C90CA21F7E4E0000EB7BF0 /* Build configuration list for PBXNativeTarget "SheetViewSwift" */; 148 | buildPhases = ( 149 | C5C90C761F7E4E0000EB7BF0 /* Sources */, 150 | C5C90C771F7E4E0000EB7BF0 /* Frameworks */, 151 | C5C90C781F7E4E0000EB7BF0 /* Resources */, 152 | ); 153 | buildRules = ( 154 | ); 155 | dependencies = ( 156 | ); 157 | name = SheetViewSwift; 158 | productName = SheetViewSwift; 159 | productReference = C5C90C7A1F7E4E0000EB7BF0 /* SheetViewSwift.app */; 160 | productType = "com.apple.product-type.application"; 161 | }; 162 | C5C90C8D1F7E4E0000EB7BF0 /* SheetViewSwiftTests */ = { 163 | isa = PBXNativeTarget; 164 | buildConfigurationList = C5C90CA51F7E4E0000EB7BF0 /* Build configuration list for PBXNativeTarget "SheetViewSwiftTests" */; 165 | buildPhases = ( 166 | C5C90C8A1F7E4E0000EB7BF0 /* Sources */, 167 | C5C90C8B1F7E4E0000EB7BF0 /* Frameworks */, 168 | C5C90C8C1F7E4E0000EB7BF0 /* Resources */, 169 | ); 170 | buildRules = ( 171 | ); 172 | dependencies = ( 173 | C5C90C901F7E4E0000EB7BF0 /* PBXTargetDependency */, 174 | ); 175 | name = SheetViewSwiftTests; 176 | productName = SheetViewSwiftTests; 177 | productReference = C5C90C8E1F7E4E0000EB7BF0 /* SheetViewSwiftTests.xctest */; 178 | productType = "com.apple.product-type.bundle.unit-test"; 179 | }; 180 | C5C90C981F7E4E0000EB7BF0 /* SheetViewSwiftUITests */ = { 181 | isa = PBXNativeTarget; 182 | buildConfigurationList = C5C90CA81F7E4E0000EB7BF0 /* Build configuration list for PBXNativeTarget "SheetViewSwiftUITests" */; 183 | buildPhases = ( 184 | C5C90C951F7E4E0000EB7BF0 /* Sources */, 185 | C5C90C961F7E4E0000EB7BF0 /* Frameworks */, 186 | C5C90C971F7E4E0000EB7BF0 /* Resources */, 187 | ); 188 | buildRules = ( 189 | ); 190 | dependencies = ( 191 | C5C90C9B1F7E4E0000EB7BF0 /* PBXTargetDependency */, 192 | ); 193 | name = SheetViewSwiftUITests; 194 | productName = SheetViewSwiftUITests; 195 | productReference = C5C90C991F7E4E0000EB7BF0 /* SheetViewSwiftUITests.xctest */; 196 | productType = "com.apple.product-type.bundle.ui-testing"; 197 | }; 198 | /* End PBXNativeTarget section */ 199 | 200 | /* Begin PBXProject section */ 201 | C5C90C721F7E4E0000EB7BF0 /* Project object */ = { 202 | isa = PBXProject; 203 | attributes = { 204 | LastSwiftUpdateCheck = 0900; 205 | LastUpgradeCheck = 0900; 206 | ORGANIZATIONNAME = mengminduan; 207 | TargetAttributes = { 208 | C5C90C791F7E4E0000EB7BF0 = { 209 | CreatedOnToolsVersion = 9.0; 210 | ProvisioningStyle = Manual; 211 | }; 212 | C5C90C8D1F7E4E0000EB7BF0 = { 213 | CreatedOnToolsVersion = 9.0; 214 | ProvisioningStyle = Automatic; 215 | TestTargetID = C5C90C791F7E4E0000EB7BF0; 216 | }; 217 | C5C90C981F7E4E0000EB7BF0 = { 218 | CreatedOnToolsVersion = 9.0; 219 | ProvisioningStyle = Automatic; 220 | TestTargetID = C5C90C791F7E4E0000EB7BF0; 221 | }; 222 | }; 223 | }; 224 | buildConfigurationList = C5C90C751F7E4E0000EB7BF0 /* Build configuration list for PBXProject "SheetViewSwift" */; 225 | compatibilityVersion = "Xcode 8.0"; 226 | developmentRegion = en; 227 | hasScannedForEncodings = 0; 228 | knownRegions = ( 229 | en, 230 | Base, 231 | ); 232 | mainGroup = C5C90C711F7E4E0000EB7BF0; 233 | productRefGroup = C5C90C7B1F7E4E0000EB7BF0 /* Products */; 234 | projectDirPath = ""; 235 | projectRoot = ""; 236 | targets = ( 237 | C5C90C791F7E4E0000EB7BF0 /* SheetViewSwift */, 238 | C5C90C8D1F7E4E0000EB7BF0 /* SheetViewSwiftTests */, 239 | C5C90C981F7E4E0000EB7BF0 /* SheetViewSwiftUITests */, 240 | ); 241 | }; 242 | /* End PBXProject section */ 243 | 244 | /* Begin PBXResourcesBuildPhase section */ 245 | C5C90C781F7E4E0000EB7BF0 /* Resources */ = { 246 | isa = PBXResourcesBuildPhase; 247 | buildActionMask = 2147483647; 248 | files = ( 249 | C5C90C881F7E4E0000EB7BF0 /* LaunchScreen.storyboard in Resources */, 250 | C5C90C851F7E4E0000EB7BF0 /* Assets.xcassets in Resources */, 251 | C5C90C831F7E4E0000EB7BF0 /* Main.storyboard in Resources */, 252 | ); 253 | runOnlyForDeploymentPostprocessing = 0; 254 | }; 255 | C5C90C8C1F7E4E0000EB7BF0 /* Resources */ = { 256 | isa = PBXResourcesBuildPhase; 257 | buildActionMask = 2147483647; 258 | files = ( 259 | ); 260 | runOnlyForDeploymentPostprocessing = 0; 261 | }; 262 | C5C90C971F7E4E0000EB7BF0 /* Resources */ = { 263 | isa = PBXResourcesBuildPhase; 264 | buildActionMask = 2147483647; 265 | files = ( 266 | ); 267 | runOnlyForDeploymentPostprocessing = 0; 268 | }; 269 | /* End PBXResourcesBuildPhase section */ 270 | 271 | /* Begin PBXSourcesBuildPhase section */ 272 | C5C90C761F7E4E0000EB7BF0 /* Sources */ = { 273 | isa = PBXSourcesBuildPhase; 274 | buildActionMask = 2147483647; 275 | files = ( 276 | C5C90C801F7E4E0000EB7BF0 /* ViewController.swift in Sources */, 277 | C5C90CAD1F7E4E5500EB7BF0 /* SheetView.swift in Sources */, 278 | C520A1D51F7E6C9A0054B1CB /* ContentViewCell.swift in Sources */, 279 | C5C90C7E1F7E4E0000EB7BF0 /* AppDelegate.swift in Sources */, 280 | ); 281 | runOnlyForDeploymentPostprocessing = 0; 282 | }; 283 | C5C90C8A1F7E4E0000EB7BF0 /* Sources */ = { 284 | isa = PBXSourcesBuildPhase; 285 | buildActionMask = 2147483647; 286 | files = ( 287 | C5C90C931F7E4E0000EB7BF0 /* SheetViewSwiftTests.swift in Sources */, 288 | ); 289 | runOnlyForDeploymentPostprocessing = 0; 290 | }; 291 | C5C90C951F7E4E0000EB7BF0 /* Sources */ = { 292 | isa = PBXSourcesBuildPhase; 293 | buildActionMask = 2147483647; 294 | files = ( 295 | C5C90C9E1F7E4E0000EB7BF0 /* SheetViewSwiftUITests.swift in Sources */, 296 | ); 297 | runOnlyForDeploymentPostprocessing = 0; 298 | }; 299 | /* End PBXSourcesBuildPhase section */ 300 | 301 | /* Begin PBXTargetDependency section */ 302 | C5C90C901F7E4E0000EB7BF0 /* PBXTargetDependency */ = { 303 | isa = PBXTargetDependency; 304 | target = C5C90C791F7E4E0000EB7BF0 /* SheetViewSwift */; 305 | targetProxy = C5C90C8F1F7E4E0000EB7BF0 /* PBXContainerItemProxy */; 306 | }; 307 | C5C90C9B1F7E4E0000EB7BF0 /* PBXTargetDependency */ = { 308 | isa = PBXTargetDependency; 309 | target = C5C90C791F7E4E0000EB7BF0 /* SheetViewSwift */; 310 | targetProxy = C5C90C9A1F7E4E0000EB7BF0 /* PBXContainerItemProxy */; 311 | }; 312 | /* End PBXTargetDependency section */ 313 | 314 | /* Begin PBXVariantGroup section */ 315 | C5C90C811F7E4E0000EB7BF0 /* Main.storyboard */ = { 316 | isa = PBXVariantGroup; 317 | children = ( 318 | C5C90C821F7E4E0000EB7BF0 /* Base */, 319 | ); 320 | name = Main.storyboard; 321 | sourceTree = ""; 322 | }; 323 | C5C90C861F7E4E0000EB7BF0 /* LaunchScreen.storyboard */ = { 324 | isa = PBXVariantGroup; 325 | children = ( 326 | C5C90C871F7E4E0000EB7BF0 /* Base */, 327 | ); 328 | name = LaunchScreen.storyboard; 329 | sourceTree = ""; 330 | }; 331 | /* End PBXVariantGroup section */ 332 | 333 | /* Begin XCBuildConfiguration section */ 334 | C5C90CA01F7E4E0000EB7BF0 /* Debug */ = { 335 | isa = XCBuildConfiguration; 336 | buildSettings = { 337 | ALWAYS_SEARCH_USER_PATHS = NO; 338 | CLANG_ANALYZER_NONNULL = YES; 339 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 340 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 341 | CLANG_CXX_LIBRARY = "libc++"; 342 | CLANG_ENABLE_MODULES = YES; 343 | CLANG_ENABLE_OBJC_ARC = YES; 344 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 345 | CLANG_WARN_BOOL_CONVERSION = YES; 346 | CLANG_WARN_COMMA = YES; 347 | CLANG_WARN_CONSTANT_CONVERSION = YES; 348 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 349 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 350 | CLANG_WARN_EMPTY_BODY = YES; 351 | CLANG_WARN_ENUM_CONVERSION = YES; 352 | CLANG_WARN_INFINITE_RECURSION = YES; 353 | CLANG_WARN_INT_CONVERSION = YES; 354 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 355 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 356 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 357 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 358 | CLANG_WARN_STRICT_PROTOTYPES = YES; 359 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 360 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 361 | CLANG_WARN_UNREACHABLE_CODE = YES; 362 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 363 | CODE_SIGN_IDENTITY = "iPhone Developer"; 364 | COPY_PHASE_STRIP = NO; 365 | DEBUG_INFORMATION_FORMAT = dwarf; 366 | ENABLE_STRICT_OBJC_MSGSEND = YES; 367 | ENABLE_TESTABILITY = YES; 368 | GCC_C_LANGUAGE_STANDARD = gnu11; 369 | GCC_DYNAMIC_NO_PIC = NO; 370 | GCC_NO_COMMON_BLOCKS = YES; 371 | GCC_OPTIMIZATION_LEVEL = 0; 372 | GCC_PREPROCESSOR_DEFINITIONS = ( 373 | "DEBUG=1", 374 | "$(inherited)", 375 | ); 376 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 377 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 378 | GCC_WARN_UNDECLARED_SELECTOR = YES; 379 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 380 | GCC_WARN_UNUSED_FUNCTION = YES; 381 | GCC_WARN_UNUSED_VARIABLE = YES; 382 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 383 | MTL_ENABLE_DEBUG_INFO = YES; 384 | ONLY_ACTIVE_ARCH = YES; 385 | SDKROOT = iphoneos; 386 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 387 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 388 | }; 389 | name = Debug; 390 | }; 391 | C5C90CA11F7E4E0000EB7BF0 /* Release */ = { 392 | isa = XCBuildConfiguration; 393 | buildSettings = { 394 | ALWAYS_SEARCH_USER_PATHS = NO; 395 | CLANG_ANALYZER_NONNULL = YES; 396 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 397 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 398 | CLANG_CXX_LIBRARY = "libc++"; 399 | CLANG_ENABLE_MODULES = YES; 400 | CLANG_ENABLE_OBJC_ARC = YES; 401 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 402 | CLANG_WARN_BOOL_CONVERSION = YES; 403 | CLANG_WARN_COMMA = YES; 404 | CLANG_WARN_CONSTANT_CONVERSION = YES; 405 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 406 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 407 | CLANG_WARN_EMPTY_BODY = YES; 408 | CLANG_WARN_ENUM_CONVERSION = YES; 409 | CLANG_WARN_INFINITE_RECURSION = YES; 410 | CLANG_WARN_INT_CONVERSION = YES; 411 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 412 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 413 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 414 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 415 | CLANG_WARN_STRICT_PROTOTYPES = YES; 416 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 417 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 418 | CLANG_WARN_UNREACHABLE_CODE = YES; 419 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 420 | CODE_SIGN_IDENTITY = "iPhone Developer"; 421 | COPY_PHASE_STRIP = NO; 422 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 423 | ENABLE_NS_ASSERTIONS = NO; 424 | ENABLE_STRICT_OBJC_MSGSEND = YES; 425 | GCC_C_LANGUAGE_STANDARD = gnu11; 426 | GCC_NO_COMMON_BLOCKS = YES; 427 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 428 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 429 | GCC_WARN_UNDECLARED_SELECTOR = YES; 430 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 431 | GCC_WARN_UNUSED_FUNCTION = YES; 432 | GCC_WARN_UNUSED_VARIABLE = YES; 433 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 434 | MTL_ENABLE_DEBUG_INFO = NO; 435 | SDKROOT = iphoneos; 436 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 437 | VALIDATE_PRODUCT = YES; 438 | }; 439 | name = Release; 440 | }; 441 | C5C90CA31F7E4E0000EB7BF0 /* Debug */ = { 442 | isa = XCBuildConfiguration; 443 | buildSettings = { 444 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 445 | CODE_SIGN_IDENTITY = ""; 446 | CODE_SIGN_STYLE = Manual; 447 | DEVELOPMENT_TEAM = ""; 448 | INFOPLIST_FILE = SheetViewSwift/Info.plist; 449 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 450 | PRODUCT_BUNDLE_IDENTIFIER = com.nothot.SheetViewSwift; 451 | PRODUCT_NAME = "$(TARGET_NAME)"; 452 | PROVISIONING_PROFILE_SPECIFIER = ""; 453 | SWIFT_VERSION = 4.0; 454 | TARGETED_DEVICE_FAMILY = "1,2"; 455 | }; 456 | name = Debug; 457 | }; 458 | C5C90CA41F7E4E0000EB7BF0 /* Release */ = { 459 | isa = XCBuildConfiguration; 460 | buildSettings = { 461 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 462 | CODE_SIGN_IDENTITY = ""; 463 | CODE_SIGN_STYLE = Manual; 464 | DEVELOPMENT_TEAM = ""; 465 | INFOPLIST_FILE = SheetViewSwift/Info.plist; 466 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 467 | PRODUCT_BUNDLE_IDENTIFIER = com.nothot.SheetViewSwift; 468 | PRODUCT_NAME = "$(TARGET_NAME)"; 469 | PROVISIONING_PROFILE_SPECIFIER = ""; 470 | SWIFT_VERSION = 4.0; 471 | TARGETED_DEVICE_FAMILY = "1,2"; 472 | }; 473 | name = Release; 474 | }; 475 | C5C90CA61F7E4E0000EB7BF0 /* Debug */ = { 476 | isa = XCBuildConfiguration; 477 | buildSettings = { 478 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 479 | BUNDLE_LOADER = "$(TEST_HOST)"; 480 | CODE_SIGN_STYLE = Automatic; 481 | INFOPLIST_FILE = SheetViewSwiftTests/Info.plist; 482 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 483 | PRODUCT_BUNDLE_IDENTIFIER = com.nothot.SheetViewSwiftTests; 484 | PRODUCT_NAME = "$(TARGET_NAME)"; 485 | SWIFT_VERSION = 4.0; 486 | TARGETED_DEVICE_FAMILY = "1,2"; 487 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SheetViewSwift.app/SheetViewSwift"; 488 | }; 489 | name = Debug; 490 | }; 491 | C5C90CA71F7E4E0000EB7BF0 /* Release */ = { 492 | isa = XCBuildConfiguration; 493 | buildSettings = { 494 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 495 | BUNDLE_LOADER = "$(TEST_HOST)"; 496 | CODE_SIGN_STYLE = Automatic; 497 | INFOPLIST_FILE = SheetViewSwiftTests/Info.plist; 498 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 499 | PRODUCT_BUNDLE_IDENTIFIER = com.nothot.SheetViewSwiftTests; 500 | PRODUCT_NAME = "$(TARGET_NAME)"; 501 | SWIFT_VERSION = 4.0; 502 | TARGETED_DEVICE_FAMILY = "1,2"; 503 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SheetViewSwift.app/SheetViewSwift"; 504 | }; 505 | name = Release; 506 | }; 507 | C5C90CA91F7E4E0000EB7BF0 /* Debug */ = { 508 | isa = XCBuildConfiguration; 509 | buildSettings = { 510 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 511 | CODE_SIGN_STYLE = Automatic; 512 | INFOPLIST_FILE = SheetViewSwiftUITests/Info.plist; 513 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 514 | PRODUCT_BUNDLE_IDENTIFIER = com.nothot.SheetViewSwiftUITests; 515 | PRODUCT_NAME = "$(TARGET_NAME)"; 516 | SWIFT_VERSION = 4.0; 517 | TARGETED_DEVICE_FAMILY = "1,2"; 518 | TEST_TARGET_NAME = SheetViewSwift; 519 | }; 520 | name = Debug; 521 | }; 522 | C5C90CAA1F7E4E0000EB7BF0 /* Release */ = { 523 | isa = XCBuildConfiguration; 524 | buildSettings = { 525 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 526 | CODE_SIGN_STYLE = Automatic; 527 | INFOPLIST_FILE = SheetViewSwiftUITests/Info.plist; 528 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 529 | PRODUCT_BUNDLE_IDENTIFIER = com.nothot.SheetViewSwiftUITests; 530 | PRODUCT_NAME = "$(TARGET_NAME)"; 531 | SWIFT_VERSION = 4.0; 532 | TARGETED_DEVICE_FAMILY = "1,2"; 533 | TEST_TARGET_NAME = SheetViewSwift; 534 | }; 535 | name = Release; 536 | }; 537 | /* End XCBuildConfiguration section */ 538 | 539 | /* Begin XCConfigurationList section */ 540 | C5C90C751F7E4E0000EB7BF0 /* Build configuration list for PBXProject "SheetViewSwift" */ = { 541 | isa = XCConfigurationList; 542 | buildConfigurations = ( 543 | C5C90CA01F7E4E0000EB7BF0 /* Debug */, 544 | C5C90CA11F7E4E0000EB7BF0 /* Release */, 545 | ); 546 | defaultConfigurationIsVisible = 0; 547 | defaultConfigurationName = Release; 548 | }; 549 | C5C90CA21F7E4E0000EB7BF0 /* Build configuration list for PBXNativeTarget "SheetViewSwift" */ = { 550 | isa = XCConfigurationList; 551 | buildConfigurations = ( 552 | C5C90CA31F7E4E0000EB7BF0 /* Debug */, 553 | C5C90CA41F7E4E0000EB7BF0 /* Release */, 554 | ); 555 | defaultConfigurationIsVisible = 0; 556 | defaultConfigurationName = Release; 557 | }; 558 | C5C90CA51F7E4E0000EB7BF0 /* Build configuration list for PBXNativeTarget "SheetViewSwiftTests" */ = { 559 | isa = XCConfigurationList; 560 | buildConfigurations = ( 561 | C5C90CA61F7E4E0000EB7BF0 /* Debug */, 562 | C5C90CA71F7E4E0000EB7BF0 /* Release */, 563 | ); 564 | defaultConfigurationIsVisible = 0; 565 | defaultConfigurationName = Release; 566 | }; 567 | C5C90CA81F7E4E0000EB7BF0 /* Build configuration list for PBXNativeTarget "SheetViewSwiftUITests" */ = { 568 | isa = XCConfigurationList; 569 | buildConfigurations = ( 570 | C5C90CA91F7E4E0000EB7BF0 /* Debug */, 571 | C5C90CAA1F7E4E0000EB7BF0 /* Release */, 572 | ); 573 | defaultConfigurationIsVisible = 0; 574 | defaultConfigurationName = Release; 575 | }; 576 | /* End XCConfigurationList section */ 577 | }; 578 | rootObject = C5C90C721F7E4E0000EB7BF0 /* Project object */; 579 | } 580 | -------------------------------------------------------------------------------- /SheetViewSwift.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SheetViewSwift/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // SheetViewSwift 4 | // 5 | // Created by mengminduan on 2017/9/29. 6 | // Copyright © 2017年 mengminduan. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(_ application: UIApplication) { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(_ application: UIApplication) { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(_ application: UIApplication) { 33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(_ application: UIApplication) { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | func applicationWillTerminate(_ application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /SheetViewSwift/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 | "info" : { 90 | "version" : 1, 91 | "author" : "xcode" 92 | } 93 | } -------------------------------------------------------------------------------- /SheetViewSwift/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 | -------------------------------------------------------------------------------- /SheetViewSwift/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 | -------------------------------------------------------------------------------- /SheetViewSwift/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 | -------------------------------------------------------------------------------- /SheetViewSwift/SheetView/ContentViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentViewCell.swift 3 | // SheetViewSwift 4 | // 5 | // Created by mengminduan on 2017/9/29. 6 | // Copyright © 2017年 mengminduan. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ContentViewCell: UITableViewCell, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout { 12 | 13 | 14 | var cellCollectionView: UICollectionView? 15 | 16 | var cellForItemAtIndexPathClosure: ((NSIndexPath) -> String)? 17 | var numberOfItemsInSectionClosure: ((Int) -> Int)? 18 | var sizeForItemAtIndexPathClosure: ((UICollectionViewLayout?, NSIndexPath) -> CGSize)? 19 | var ContentViewCellDidScrollClosure: ((UIScrollView) ->Void)? 20 | var cellWithColorAtIndexPathClosure: ((NSIndexPath) -> Bool)? 21 | var cellDidSelectedClosure: ((NSIndexPath) -> Void)? 22 | 23 | 24 | override init(style: UITableViewCellStyle, reuseIdentifier: String?) { 25 | super.init(style: style, reuseIdentifier: reuseIdentifier) 26 | let layout = UICollectionViewFlowLayout() 27 | layout.minimumLineSpacing = 1.0 28 | layout.minimumInteritemSpacing = 0 29 | layout.scrollDirection = UICollectionViewScrollDirection.horizontal 30 | let rect = CGRect(x: 0, y: 0, width: self.frame.size.width, height: self.frame.size.height) 31 | self.cellCollectionView = UICollectionView(frame: rect, collectionViewLayout: layout) 32 | self.cellCollectionView?.showsHorizontalScrollIndicator = false 33 | self.cellCollectionView?.backgroundColor = UIColor(red: 0x90 / 255.0, green: 0x90 / 255.0, blue: 0x90 / 255.0, alpha: 1.0) 34 | self.cellCollectionView?.layer.borderColor = self.cellCollectionView?.backgroundColor?.cgColor 35 | self.cellCollectionView?.layer.borderWidth = 1.0 36 | self.cellCollectionView?.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "inner.cell") 37 | self.cellCollectionView?.dataSource = self 38 | self.cellCollectionView?.delegate = self 39 | 40 | self.contentView.addSubview(self.cellCollectionView!) 41 | } 42 | 43 | required init?(coder aDecoder: NSCoder) { 44 | super.init(coder: aDecoder) 45 | } 46 | 47 | func scrollViewDidScroll(_ scrollView: UIScrollView) { 48 | if self.ContentViewCellDidScrollClosure != nil { 49 | self.ContentViewCellDidScrollClosure!(scrollView) 50 | } 51 | } 52 | 53 | func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 54 | return self.numberOfItemsInSectionClosure!(section) 55 | } 56 | 57 | func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { 58 | return self.sizeForItemAtIndexPathClosure!(collectionViewLayout, indexPath as NSIndexPath) 59 | 60 | } 61 | 62 | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 63 | let innerCell = collectionView.dequeueReusableCell(withReuseIdentifier: "inner.cell", for: indexPath) 64 | for item in innerCell.contentView.subviews { 65 | let view = item as UIView 66 | view.removeFromSuperview() 67 | } 68 | var hasColor = false 69 | if self.cellWithColorAtIndexPathClosure != nil { 70 | hasColor = self.cellWithColorAtIndexPathClosure!(indexPath as NSIndexPath) 71 | } 72 | innerCell.backgroundColor = hasColor ? UIColor(red: 0xf0 / 255.0, green: 0xf0 / 255.0, blue: 0xf0 / 255.0, alpha: 1.0) : UIColor.white 73 | let width = self.sizeForItemAtIndexPathClosure!(nil, indexPath as NSIndexPath).width 74 | let height = self.sizeForItemAtIndexPathClosure!(nil, indexPath as NSIndexPath).height 75 | let label = UILabel(frame: CGRect(x: 0, y: 0, width: width, height: height)) 76 | label.text = self.cellForItemAtIndexPathClosure!(indexPath as NSIndexPath) 77 | label.textColor = UIColor.black 78 | label.textAlignment = NSTextAlignment.center 79 | innerCell.contentView.addSubview(label) 80 | innerCell.layer.borderColor = UIColor(red: 0x90 / 255.0, green: 0x90 / 255.0, blue: 0x90 / 255.0, alpha: 1.0).cgColor 81 | innerCell.layer.borderWidth = 1.0 82 | 83 | return innerCell 84 | } 85 | 86 | func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { 87 | if self.cellDidSelectedClosure != nil { 88 | self.cellDidSelectedClosure!(indexPath as NSIndexPath) 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /SheetViewSwift/SheetView/SheetView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SheetView.swift 3 | // SheetViewSwift 4 | // 5 | // Created by mengminduan on 2017/9/29. 6 | // Copyright © 2017年 mengminduan. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | protocol SheetViewDataSource: NSObjectProtocol { 12 | func sheetView(sheetView: SheetView, numberOfRowsInSection section: Int) -> Int 13 | func sheetView(sheetView: SheetView, numberOfColsInSection section: Int) -> Int 14 | func sheetView(sheetView: SheetView, cellForContentItemAtIndexRow indexRow: NSIndexPath?, indexCol: NSIndexPath?) -> String 15 | func sheetView(sheetView: SheetView, cellForLeftColAtIndexPath indexPath: NSIndexPath?) -> String 16 | func sheetView(sheetView: SheetView, cellForTopRowAtIndexPath indexPath: NSIndexPath?) -> String 17 | func sheetView(sheetView: SheetView, cellWithColorAtIndexRow indexRow: NSIndexPath?) -> Bool 18 | 19 | } 20 | 21 | protocol SheetViewDelegate: NSObjectProtocol { 22 | func sheetView(sheetView: SheetView, heightForRowAtIndexPath indexPath: NSIndexPath?) -> CGFloat 23 | func sheetView(sheetView: SheetView, widthForColAtIndexPath indexPath: NSIndexPath?) -> CGFloat 24 | func sheetView(sheetView: SheetView, cellDidSelectedAtIndexRow indexRow: NSIndexPath?, indexCol: NSIndexPath?) -> Void 25 | 26 | } 27 | 28 | let leftViewCellId = "left.tableview.cell" 29 | let topViewCellId = "top.collectionview.cell" 30 | let contentViewCellId = "content.tableview.cell" 31 | 32 | class SheetLeftView: UITableView { 33 | 34 | } 35 | 36 | class SheetTopView: UICollectionView { 37 | 38 | } 39 | 40 | class SheetContentView: UITableView { 41 | 42 | } 43 | 44 | class SheetView: UIView, UITableViewDelegate, UITableViewDataSource, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { 45 | 46 | public weak var dataSource: SheetViewDataSource? 47 | public weak var delegate: SheetViewDelegate? 48 | public var sheetHead: String? 49 | public var autoResizingItemMask: Bool = true 50 | public var titleColWidth: CGFloat = 80; 51 | public var titleRowHeight: CGFloat = 60; 52 | 53 | var leftView: SheetLeftView = SheetLeftView() 54 | var topView: SheetTopView? 55 | var contentView: SheetContentView = SheetContentView() 56 | var sheetHeadLabel: UILabel? 57 | var kRowheight: CGFloat = 0 58 | var kColWidth: CGFloat = 0 59 | 60 | override init(frame: CGRect) { 61 | 62 | super.init(frame: frame) 63 | 64 | 65 | self.layer.borderColor = UIColor(red: 0xe5 / 255.0, green: 0xe5 / 255.0, blue: 0xe5 / 255.0, alpha: 1.0).cgColor 66 | self.layer.cornerRadius = 1.0 67 | self.layer.borderWidth = 1.0 68 | 69 | //leftview 70 | 71 | self.leftView = SheetLeftView(frame: CGRect.zero, style: UITableViewStyle.plain) 72 | self.leftView.dataSource = self 73 | self.leftView.delegate = self 74 | self.leftView.showsVerticalScrollIndicator = false 75 | self.leftView.backgroundColor = UIColor(red: 0x90 / 255.0, green: 0x90 / 255.0, blue: 0x90 / 255.0, alpha: 1.0) 76 | self.leftView.layer.borderColor = UIColor(red: 0x90 / 255.0, green: 0x90 / 255.0, blue: 0x90 / 255.0, alpha: 1.0).cgColor 77 | self.leftView.layer.borderWidth = 1.0 78 | self.leftView.separatorStyle = UITableViewCellSeparatorStyle.none 79 | 80 | //topview 81 | 82 | let layout = UICollectionViewFlowLayout() 83 | layout.minimumLineSpacing = 1.0 84 | layout.minimumInteritemSpacing = 0.0 85 | layout.scrollDirection = UICollectionViewScrollDirection.horizontal 86 | self.topView = SheetTopView(frame: CGRect.zero, collectionViewLayout: layout) 87 | self.topView?.dataSource = self 88 | self.topView?.delegate = self 89 | self.topView?.showsHorizontalScrollIndicator = false 90 | self.topView?.register(UICollectionViewCell.self, forCellWithReuseIdentifier: topViewCellId) 91 | self.topView?.backgroundColor = UIColor(red: 0x90 / 255.0, green: 0x90 / 255.0, blue: 0x90 / 255.0, alpha: 1.0) 92 | self.topView?.layer.borderColor = UIColor(red: 0x90 / 255.0, green: 0x90 / 255.0, blue: 0x90 / 255.0, alpha: 1.0).cgColor 93 | self.topView?.layer.borderWidth = 1.0 94 | 95 | //contentview 96 | 97 | self.contentView = SheetContentView(frame: CGRect.zero, style: UITableViewStyle.plain) 98 | self.contentView.dataSource = self 99 | self.contentView.delegate = self 100 | self.contentView.showsVerticalScrollIndicator = false 101 | self.contentView.separatorStyle = UITableViewCellSeparatorStyle.none 102 | self.contentView.backgroundColor = self.topView?.backgroundColor 103 | 104 | self.addSubview(self.topView!) 105 | self.addSubview(self.leftView) 106 | self.addSubview(self.contentView) 107 | } 108 | 109 | required public init?(coder aDecoder: NSCoder) { 110 | super.init(coder: aDecoder) 111 | } 112 | 113 | func scrollViewDidScroll(_ scrollView: UIScrollView) { 114 | if scrollView is SheetLeftView { 115 | self.contentView.contentOffset = self.leftView.contentOffset 116 | } 117 | if scrollView is SheetContentView { 118 | self.leftView.contentOffset = self.contentView.contentOffset 119 | } 120 | if scrollView is SheetTopView { 121 | for item in self.contentView.visibleCells { 122 | let cell = item as! ContentViewCell 123 | cell.cellCollectionView?.contentOffset = scrollView.contentOffset 124 | } 125 | } 126 | } 127 | 128 | override func layoutSubviews() { 129 | super.layoutSubviews() 130 | let sheetViewWidth = self.frame.size.width 131 | let sheetViewHeight = self.frame.size.height 132 | self.leftView.frame = CGRect(x: 0, y: self.titleRowHeight, width: self.titleColWidth, height: sheetViewHeight - self.titleRowHeight) 133 | self.topView?.frame = CGRect(x: self.titleColWidth, y: 0, width: sheetViewWidth - self.titleColWidth, height: self.titleRowHeight) 134 | self.contentView.frame = CGRect(x: self.titleColWidth, y: self.titleRowHeight, width: sheetViewWidth - self.titleColWidth, height: sheetViewHeight - self.titleRowHeight) 135 | 136 | if self.sheetHeadLabel != nil { 137 | self.sheetHeadLabel!.removeFromSuperview() 138 | } 139 | 140 | self.sheetHeadLabel = UILabel(frame: CGRect(x: 0, y: 0, width: self.titleColWidth, height: self.titleRowHeight)) 141 | self.sheetHeadLabel?.text = self.sheetHead 142 | self.sheetHeadLabel?.textColor = UIColor.black 143 | self.sheetHeadLabel?.textAlignment = NSTextAlignment.center 144 | self.sheetHeadLabel?.backgroundColor = UIColor(red: 0xf0 / 255.0, green: 0xf0 / 255.0, blue: 0xf0 / 255.0, alpha: 1.0) 145 | self.sheetHeadLabel?.layer.borderColor = UIColor(red: 0x90 / 255.0, green: 0x90 / 255.0, blue: 0x90 / 255.0, alpha: 1.0).cgColor 146 | self.sheetHeadLabel?.layer.borderWidth = 1.0 147 | self.addSubview(self.sheetHeadLabel!) 148 | 149 | } 150 | 151 | 152 | 153 | 154 | func reloadData() { 155 | self.sheetHeadLabel?.frame = CGRect(x: 0, y: 0, width: self.titleColWidth, height: self.titleRowHeight) 156 | self.leftView.reloadData() 157 | self.topView?.reloadData() 158 | self.contentView.reloadData() 159 | 160 | } 161 | 162 | //tableview delegate 163 | 164 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 165 | return self.dataSource!.sheetView(sheetView: self, numberOfRowsInSection: section) 166 | } 167 | 168 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 169 | let height = self.delegate?.sheetView(sheetView: self, heightForRowAtIndexPath: indexPath as NSIndexPath) 170 | if tableView is SheetLeftView { 171 | var leftCell = tableView.dequeueReusableCell(withIdentifier: leftViewCellId) 172 | if leftCell == nil { 173 | leftCell = UITableViewCell(style: UITableViewCellStyle.default, reuseIdentifier: leftViewCellId) 174 | leftCell?.selectionStyle = UITableViewCellSelectionStyle.none 175 | } 176 | for item in (leftCell?.contentView.subviews)! { 177 | let subView = item as UIView 178 | subView.removeFromSuperview() 179 | } 180 | leftCell?.backgroundColor = UIColor(red: 0xf0 / 255.0, green: 0xf0 / 255.0, blue: 0xf0 / 255.0, alpha: 1.0) 181 | leftCell?.layer.borderColor = UIColor(red: 0x90 / 255.0, green: 0x90 / 255.0, blue: 0x90 / 255.0, alpha: 1.0).cgColor 182 | leftCell?.layer.borderWidth = 1.0 183 | let label = UILabel(frame: CGRect(x: 0, y: 0, width: self.titleColWidth, height: height!)) 184 | label.text = self.dataSource?.sheetView(sheetView: self, cellForLeftColAtIndexPath: indexPath as NSIndexPath) 185 | label.textColor = UIColor.black 186 | label.textAlignment = NSTextAlignment.center 187 | leftCell?.contentView.addSubview(label) 188 | 189 | return leftCell! 190 | } 191 | 192 | var contentCell: ContentViewCell? = tableView.dequeueReusableCell(withIdentifier: contentViewCellId) as? ContentViewCell 193 | if contentCell == nil { 194 | contentCell = ContentViewCell(style: UITableViewCellStyle.default, reuseIdentifier: contentViewCellId) 195 | contentCell?.selectionStyle = UITableViewCellSelectionStyle.none 196 | } 197 | contentCell?.cellForItemAtIndexPathClosure = {(indexPathInner) in 198 | return (self.dataSource?.sheetView(sheetView: self, cellForContentItemAtIndexRow: indexPath as NSIndexPath, indexCol: indexPathInner))! 199 | } 200 | contentCell?.numberOfItemsInSectionClosure = {(section) in 201 | return (self.dataSource?.sheetView(sheetView: self, numberOfColsInSection: section))! 202 | } 203 | contentCell?.sizeForItemAtIndexPathClosure = {(collectionViewLayout, indexPathInner) in 204 | let width = self.delegate?.sheetView(sheetView: self, widthForColAtIndexPath: indexPathInner) 205 | 206 | return CGSize(width: width!, height: height!) 207 | } 208 | contentCell?.ContentViewCellDidScrollClosure = {(scroll) in 209 | for item in self.contentView.visibleCells { 210 | let cell = item as! ContentViewCell 211 | cell.cellCollectionView?.contentOffset = scroll.contentOffset 212 | } 213 | self.topView?.contentOffset = scroll.contentOffset 214 | } 215 | if ((self.dataSource?.sheetView(sheetView: cellWithColorAtIndexRow: )) != nil) { 216 | contentCell?.cellWithColorAtIndexPathClosure = {(indexPathInner) in 217 | return (self.dataSource?.sheetView(sheetView: self, cellWithColorAtIndexRow: indexPath as NSIndexPath))! 218 | } 219 | } 220 | contentCell?.cellDidSelectedClosure = {(indexPathInner) in 221 | if self.delegate?.sheetView(sheetView: cellDidSelectedAtIndexRow: indexCol:) != nil { 222 | self.delegate?.sheetView(sheetView: self, cellDidSelectedAtIndexRow: indexPath as NSIndexPath, indexCol: indexPathInner as NSIndexPath) 223 | } 224 | } 225 | 226 | contentCell?.backgroundColor = UIColor(red: 0x90 / 255.0, green: 0x90 / 255.0, blue: 0x90 / 255.0, alpha: 1.0) 227 | contentCell?.cellCollectionView?.frame = CGRect(x: 0, y: 0, width: self.frame.size.width - self.titleColWidth, height: height!) 228 | contentCell?.cellCollectionView?.reloadData() 229 | 230 | return contentCell! 231 | } 232 | 233 | func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 234 | return (self.delegate?.sheetView(sheetView: self, heightForRowAtIndexPath: indexPath as NSIndexPath))! 235 | } 236 | 237 | func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { 238 | if tableView is SheetLeftView { 239 | return 240 | } 241 | let willDisplayCell = cell as? ContentViewCell 242 | let didDisplayCell = tableView.visibleCells.first as? ContentViewCell 243 | if willDisplayCell != nil && didDisplayCell != nil && willDisplayCell?.cellCollectionView?.contentOffset.x != didDisplayCell?.cellCollectionView?.contentOffset.x { 244 | willDisplayCell?.cellCollectionView?.contentOffset = (didDisplayCell?.cellCollectionView?.contentOffset)! 245 | } 246 | } 247 | 248 | func numberOfSections(in collectionView: UICollectionView) -> Int { 249 | return 1 250 | } 251 | 252 | func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 253 | return self.dataSource!.sheetView(sheetView: self, numberOfColsInSection: section) 254 | } 255 | 256 | func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPathInner: IndexPath) -> CGSize { 257 | let width = self.delegate?.sheetView(sheetView: self, widthForColAtIndexPath: indexPathInner as NSIndexPath) 258 | 259 | return CGSize(width: width!, height: self.titleRowHeight) 260 | } 261 | 262 | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 263 | let topCell = collectionView.dequeueReusableCell(withReuseIdentifier: topViewCellId, for: indexPath) 264 | for item in topCell.contentView.subviews { 265 | let view = item as UIView 266 | view.removeFromSuperview() 267 | } 268 | topCell.backgroundColor = UIColor(red: 0xf0 / 255.0, green: 0xf0 / 255.0, blue: 0xf0 / 255.0, alpha: 1.0) 269 | let width = self.delegate?.sheetView(sheetView: self, widthForColAtIndexPath: indexPath as NSIndexPath) 270 | let label = UILabel(frame: CGRect(x: 0, y: 0, width: width!, height: self.titleRowHeight)) 271 | label.text = self.dataSource?.sheetView(sheetView: self, cellForTopRowAtIndexPath: indexPath as NSIndexPath) 272 | label.textAlignment = NSTextAlignment.center 273 | label.textColor = UIColor.black 274 | topCell.contentView.addSubview(label) 275 | 276 | topCell.layer.borderColor = UIColor(red: 0x90 / 255.0, green: 0x90 / 255.0, blue: 0x90 / 255.0, alpha: 1.0).cgColor 277 | topCell.layer.borderWidth = 1.0 278 | 279 | return topCell 280 | } 281 | 282 | } 283 | -------------------------------------------------------------------------------- /SheetViewSwift/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // SheetViewSwift 4 | // 5 | // Created by mengminduan on 2017/9/29. 6 | // Copyright © 2017年 mengminduan. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController, SheetViewDelegate, SheetViewDataSource { 12 | func sheetView(sheetView: SheetView, cellDidSelectedAtIndexRow indexRow: NSIndexPath?, indexCol: NSIndexPath?) { 13 | print("点击 row \(String(describing: indexRow!.row)) col \(String(describing: indexCol!.row))") 14 | } 15 | 16 | func sheetView(sheetView: SheetView, numberOfRowsInSection section: Int) -> Int { 17 | return 48 18 | } 19 | 20 | func sheetView(sheetView: SheetView, numberOfColsInSection section: Int) -> Int { 21 | return 40 22 | } 23 | 24 | func sheetView(sheetView: SheetView, cellForContentItemAtIndexRow indexRow: NSIndexPath?, indexCol: NSIndexPath?) -> String { 25 | let str1 = String(describing: indexRow!.row) 26 | let str2 = String(indexCol!.row) 27 | 28 | return "data(\(str1),\(str2))" 29 | 30 | } 31 | 32 | func sheetView(sheetView: SheetView, cellForLeftColAtIndexPath indexPath: NSIndexPath?) -> String { 33 | let str = String(describing: indexPath!.row) 34 | return "row(\(str))" 35 | 36 | } 37 | 38 | func sheetView(sheetView: SheetView, cellForTopRowAtIndexPath indexPath: NSIndexPath?) -> String { 39 | let str = String(describing: indexPath!.row) 40 | return "col(\(str))" 41 | 42 | } 43 | 44 | func sheetView(sheetView: SheetView, cellWithColorAtIndexRow indexRow: NSIndexPath?) -> Bool { 45 | return ((indexRow?.row)! % 2 == 1) ? true : false 46 | } 47 | 48 | func sheetView(sheetView: SheetView, heightForRowAtIndexPath indexPath: NSIndexPath?) -> CGFloat { 49 | return 60 50 | } 51 | 52 | func sheetView(sheetView: SheetView, widthForColAtIndexPath indexPath: NSIndexPath?) -> CGFloat { 53 | return CGFloat(80 + 10 * (indexPath?.row)!) 54 | } 55 | 56 | 57 | 58 | 59 | override func viewDidLoad() { 60 | super.viewDidLoad() 61 | let sheetView = SheetView(frame: CGRect(x: 0, y: 20, width: self.view.frame.size.width, height: self.view.frame.size.height - 20)) 62 | sheetView.dataSource = self 63 | sheetView.delegate = self 64 | sheetView.sheetHead = "sheet" 65 | self.view.addSubview(sheetView) 66 | 67 | } 68 | 69 | 70 | } 71 | 72 | -------------------------------------------------------------------------------- /SheetViewSwiftTests/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 | -------------------------------------------------------------------------------- /SheetViewSwiftTests/SheetViewSwiftTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SheetViewSwiftTests.swift 3 | // SheetViewSwiftTests 4 | // 5 | // Created by mengminduan on 2017/9/29. 6 | // Copyright © 2017年 mengminduan. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import SheetViewSwift 11 | 12 | class SheetViewSwiftTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | // Use XCTAssert and related functions to verify your tests produce the correct results. 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measure { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /SheetViewSwiftUITests/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 | -------------------------------------------------------------------------------- /SheetViewSwiftUITests/SheetViewSwiftUITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SheetViewSwiftUITests.swift 3 | // SheetViewSwiftUITests 4 | // 5 | // Created by mengminduan on 2017/9/29. 6 | // Copyright © 2017年 mengminduan. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class SheetViewSwiftUITests: XCTestCase { 12 | 13 | override func setUp() { 14 | super.setUp() 15 | 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | 18 | // In UI tests it is usually best to stop immediately when a failure occurs. 19 | continueAfterFailure = false 20 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 21 | XCUIApplication().launch() 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 | override func tearDown() { 27 | // Put teardown code here. This method is called after the invocation of each test method in the class. 28 | super.tearDown() 29 | } 30 | 31 | func testExample() { 32 | // Use recording to get started writing UI tests. 33 | // Use XCTAssert and related functions to verify your tests produce the correct results. 34 | } 35 | 36 | } 37 | --------------------------------------------------------------------------------