├── .gitignore ├── 01F3FA58-E2F9-4BFF-9F49-F07BD32322DD.png ├── Demo ├── PickerViewDemo.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata ├── PickerViewDemo.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── PickerViewDemo │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ ├── Info.plist │ ├── Main.storyboard │ ├── UIColor+PGHex.h │ ├── UIColor+PGHex.m │ ├── ViewController.h │ ├── ViewController.m │ └── main.m ├── Images ├── middle.png ├── type1.png ├── type2.png └── type3.png ├── LICENSE ├── PGPickerView.gif ├── PGPickerView.podspec ├── PGPickerView ├── PGPickerColumnCell.h ├── PGPickerColumnCell.m ├── PGPickerColumnView.h ├── PGPickerColumnView.m ├── PGPickerTableView.h ├── PGPickerTableView.m ├── PGPickerView.h └── PGPickerView.m └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xccheckout 23 | *.xcscmblueprint 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | *.ipa 28 | *.dSYM.zip 29 | *.dSYM 30 | 31 | # CocoaPods 32 | # 33 | # We recommend against adding the Pods directory to your .gitignore. However 34 | # you should judge for yourself, the pros and cons are mentioned at: 35 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 36 | # 37 | # Pods/ 38 | 39 | # Carthage 40 | # 41 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 42 | # Carthage/Checkouts 43 | 44 | Carthage/Build 45 | 46 | # fastlane 47 | # 48 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 49 | # screenshots whenever they are needed. 50 | # For more information about the recommended setup visit: 51 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 52 | 53 | fastlane/report.xml 54 | fastlane/Preview.html 55 | fastlane/screenshots 56 | fastlane/test_output 57 | 58 | # Code Injection 59 | # 60 | # After new code Injection tools there's a generated folder /iOSInjectionProject 61 | # https://github.com/johnno1962/injectionforxcode 62 | 63 | iOSInjectionProject/ 64 | -------------------------------------------------------------------------------- /01F3FA58-E2F9-4BFF-9F49-F07BD32322DD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaozhuxiong121/PGPickerView/59790a5cf0a46fce5784c27c55678ecfc6263ce7/01F3FA58-E2F9-4BFF-9F49-F07BD32322DD.png -------------------------------------------------------------------------------- /Demo/PickerViewDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 8634EAF31F2829A200EC09CF /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 8634EAF21F2829A200EC09CF /* AppDelegate.m */; }; 11 | 8634EAF61F2829A200EC09CF /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8634EAF51F2829A200EC09CF /* ViewController.m */; }; 12 | 8634EAFB1F2829A200EC09CF /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8634EAFA1F2829A200EC09CF /* Assets.xcassets */; }; 13 | 8634EB011F2829A200EC09CF /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 8634EB001F2829A200EC09CF /* main.m */; }; 14 | 86D76F9620122C4600DC2093 /* PGPickerColumnCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 86D76F8E20122C4600DC2093 /* PGPickerColumnCell.m */; }; 15 | 86D76F9720122C4600DC2093 /* PGPickerColumnView.m in Sources */ = {isa = PBXBuildFile; fileRef = 86D76F8F20122C4600DC2093 /* PGPickerColumnView.m */; }; 16 | 86D76F9820122C4600DC2093 /* PGPickerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 86D76F9420122C4600DC2093 /* PGPickerView.m */; }; 17 | 86D76F9920122C4600DC2093 /* PGPickerTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 86D76F9520122C4600DC2093 /* PGPickerTableView.m */; }; 18 | 86F094221F2F0B700067AF16 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 86F094211F2F0B700067AF16 /* Main.storyboard */; }; 19 | /* End PBXBuildFile section */ 20 | 21 | /* Begin PBXContainerItemProxy section */ 22 | 8634EB071F2829A200EC09CF /* PBXContainerItemProxy */ = { 23 | isa = PBXContainerItemProxy; 24 | containerPortal = 8634EAE61F2829A100EC09CF /* Project object */; 25 | proxyType = 1; 26 | remoteGlobalIDString = 8634EAED1F2829A200EC09CF; 27 | remoteInfo = PickerViewDemo; 28 | }; 29 | 8634EB121F2829A200EC09CF /* PBXContainerItemProxy */ = { 30 | isa = PBXContainerItemProxy; 31 | containerPortal = 8634EAE61F2829A100EC09CF /* Project object */; 32 | proxyType = 1; 33 | remoteGlobalIDString = 8634EAED1F2829A200EC09CF; 34 | remoteInfo = PickerViewDemo; 35 | }; 36 | /* End PBXContainerItemProxy section */ 37 | 38 | /* Begin PBXFileReference section */ 39 | 8634EAEE1F2829A200EC09CF /* PickerViewDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PickerViewDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 40 | 8634EAF11F2829A200EC09CF /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 41 | 8634EAF21F2829A200EC09CF /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 42 | 8634EAF41F2829A200EC09CF /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 43 | 8634EAF51F2829A200EC09CF /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 44 | 8634EAFA1F2829A200EC09CF /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 45 | 8634EAFF1F2829A200EC09CF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 46 | 8634EB001F2829A200EC09CF /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 47 | 8634EB061F2829A200EC09CF /* PickerViewDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PickerViewDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 48 | 8634EB111F2829A200EC09CF /* PickerViewDemoUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = PickerViewDemoUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 49 | 86D76F8E20122C4600DC2093 /* PGPickerColumnCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPickerColumnCell.m; sourceTree = ""; }; 50 | 86D76F8F20122C4600DC2093 /* PGPickerColumnView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPickerColumnView.m; sourceTree = ""; }; 51 | 86D76F9020122C4600DC2093 /* PGPickerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPickerView.h; sourceTree = ""; }; 52 | 86D76F9120122C4600DC2093 /* PGPickerTableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPickerTableView.h; sourceTree = ""; }; 53 | 86D76F9220122C4600DC2093 /* PGPickerColumnCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPickerColumnCell.h; sourceTree = ""; }; 54 | 86D76F9320122C4600DC2093 /* PGPickerColumnView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PGPickerColumnView.h; sourceTree = ""; }; 55 | 86D76F9420122C4600DC2093 /* PGPickerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPickerView.m; sourceTree = ""; }; 56 | 86D76F9520122C4600DC2093 /* PGPickerTableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PGPickerTableView.m; sourceTree = ""; }; 57 | 86F094211F2F0B700067AF16 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; }; 58 | /* End PBXFileReference section */ 59 | 60 | /* Begin PBXFrameworksBuildPhase section */ 61 | 8634EAEB1F2829A200EC09CF /* Frameworks */ = { 62 | isa = PBXFrameworksBuildPhase; 63 | buildActionMask = 2147483647; 64 | files = ( 65 | ); 66 | runOnlyForDeploymentPostprocessing = 0; 67 | }; 68 | 8634EB031F2829A200EC09CF /* Frameworks */ = { 69 | isa = PBXFrameworksBuildPhase; 70 | buildActionMask = 2147483647; 71 | files = ( 72 | ); 73 | runOnlyForDeploymentPostprocessing = 0; 74 | }; 75 | 8634EB0E1F2829A200EC09CF /* Frameworks */ = { 76 | isa = PBXFrameworksBuildPhase; 77 | buildActionMask = 2147483647; 78 | files = ( 79 | ); 80 | runOnlyForDeploymentPostprocessing = 0; 81 | }; 82 | /* End PBXFrameworksBuildPhase section */ 83 | 84 | /* Begin PBXGroup section */ 85 | 8634EAE51F2829A100EC09CF = { 86 | isa = PBXGroup; 87 | children = ( 88 | 86D76F8D20122C4600DC2093 /* PGPickerView */, 89 | 8634EAF01F2829A200EC09CF /* PickerViewDemo */, 90 | 8634EAEF1F2829A200EC09CF /* Products */, 91 | F0F5104668D5F485A178D7A2 /* Frameworks */, 92 | ); 93 | sourceTree = ""; 94 | }; 95 | 8634EAEF1F2829A200EC09CF /* Products */ = { 96 | isa = PBXGroup; 97 | children = ( 98 | 8634EAEE1F2829A200EC09CF /* PickerViewDemo.app */, 99 | 8634EB061F2829A200EC09CF /* PickerViewDemoTests.xctest */, 100 | 8634EB111F2829A200EC09CF /* PickerViewDemoUITests.xctest */, 101 | ); 102 | name = Products; 103 | sourceTree = ""; 104 | }; 105 | 8634EAF01F2829A200EC09CF /* PickerViewDemo */ = { 106 | isa = PBXGroup; 107 | children = ( 108 | 8634EAF11F2829A200EC09CF /* AppDelegate.h */, 109 | 8634EAF21F2829A200EC09CF /* AppDelegate.m */, 110 | 8634EAF41F2829A200EC09CF /* ViewController.h */, 111 | 8634EAF51F2829A200EC09CF /* ViewController.m */, 112 | 8634EAFA1F2829A200EC09CF /* Assets.xcassets */, 113 | 8634EAFF1F2829A200EC09CF /* Info.plist */, 114 | 8634EB001F2829A200EC09CF /* main.m */, 115 | 86F094211F2F0B700067AF16 /* Main.storyboard */, 116 | ); 117 | path = PickerViewDemo; 118 | sourceTree = ""; 119 | }; 120 | 86D76F8D20122C4600DC2093 /* PGPickerView */ = { 121 | isa = PBXGroup; 122 | children = ( 123 | 86D76F9220122C4600DC2093 /* PGPickerColumnCell.h */, 124 | 86D76F8E20122C4600DC2093 /* PGPickerColumnCell.m */, 125 | 86D76F9320122C4600DC2093 /* PGPickerColumnView.h */, 126 | 86D76F8F20122C4600DC2093 /* PGPickerColumnView.m */, 127 | 86D76F9020122C4600DC2093 /* PGPickerView.h */, 128 | 86D76F9420122C4600DC2093 /* PGPickerView.m */, 129 | 86D76F9120122C4600DC2093 /* PGPickerTableView.h */, 130 | 86D76F9520122C4600DC2093 /* PGPickerTableView.m */, 131 | ); 132 | name = PGPickerView; 133 | path = ../PGPickerView; 134 | sourceTree = ""; 135 | }; 136 | F0F5104668D5F485A178D7A2 /* Frameworks */ = { 137 | isa = PBXGroup; 138 | children = ( 139 | ); 140 | name = Frameworks; 141 | sourceTree = ""; 142 | }; 143 | /* End PBXGroup section */ 144 | 145 | /* Begin PBXNativeTarget section */ 146 | 8634EAED1F2829A200EC09CF /* PickerViewDemo */ = { 147 | isa = PBXNativeTarget; 148 | buildConfigurationList = 8634EB1A1F2829A200EC09CF /* Build configuration list for PBXNativeTarget "PickerViewDemo" */; 149 | buildPhases = ( 150 | 8634EAEA1F2829A200EC09CF /* Sources */, 151 | 8634EAEB1F2829A200EC09CF /* Frameworks */, 152 | 8634EAEC1F2829A200EC09CF /* Resources */, 153 | ); 154 | buildRules = ( 155 | ); 156 | dependencies = ( 157 | ); 158 | name = PickerViewDemo; 159 | productName = PickerViewDemo; 160 | productReference = 8634EAEE1F2829A200EC09CF /* PickerViewDemo.app */; 161 | productType = "com.apple.product-type.application"; 162 | }; 163 | 8634EB051F2829A200EC09CF /* PickerViewDemoTests */ = { 164 | isa = PBXNativeTarget; 165 | buildConfigurationList = 8634EB1D1F2829A200EC09CF /* Build configuration list for PBXNativeTarget "PickerViewDemoTests" */; 166 | buildPhases = ( 167 | 8634EB021F2829A200EC09CF /* Sources */, 168 | 8634EB031F2829A200EC09CF /* Frameworks */, 169 | 8634EB041F2829A200EC09CF /* Resources */, 170 | ); 171 | buildRules = ( 172 | ); 173 | dependencies = ( 174 | 8634EB081F2829A200EC09CF /* PBXTargetDependency */, 175 | ); 176 | name = PickerViewDemoTests; 177 | productName = PickerViewDemoTests; 178 | productReference = 8634EB061F2829A200EC09CF /* PickerViewDemoTests.xctest */; 179 | productType = "com.apple.product-type.bundle.unit-test"; 180 | }; 181 | 8634EB101F2829A200EC09CF /* PickerViewDemoUITests */ = { 182 | isa = PBXNativeTarget; 183 | buildConfigurationList = 8634EB201F2829A200EC09CF /* Build configuration list for PBXNativeTarget "PickerViewDemoUITests" */; 184 | buildPhases = ( 185 | 8634EB0D1F2829A200EC09CF /* Sources */, 186 | 8634EB0E1F2829A200EC09CF /* Frameworks */, 187 | 8634EB0F1F2829A200EC09CF /* Resources */, 188 | ); 189 | buildRules = ( 190 | ); 191 | dependencies = ( 192 | 8634EB131F2829A200EC09CF /* PBXTargetDependency */, 193 | ); 194 | name = PickerViewDemoUITests; 195 | productName = PickerViewDemoUITests; 196 | productReference = 8634EB111F2829A200EC09CF /* PickerViewDemoUITests.xctest */; 197 | productType = "com.apple.product-type.bundle.ui-testing"; 198 | }; 199 | /* End PBXNativeTarget section */ 200 | 201 | /* Begin PBXProject section */ 202 | 8634EAE61F2829A100EC09CF /* Project object */ = { 203 | isa = PBXProject; 204 | attributes = { 205 | LastUpgradeCheck = 0900; 206 | ORGANIZATIONNAME = piggybear; 207 | TargetAttributes = { 208 | 8634EAED1F2829A200EC09CF = { 209 | CreatedOnToolsVersion = 9.0; 210 | }; 211 | 8634EB051F2829A200EC09CF = { 212 | CreatedOnToolsVersion = 9.0; 213 | TestTargetID = 8634EAED1F2829A200EC09CF; 214 | }; 215 | 8634EB101F2829A200EC09CF = { 216 | CreatedOnToolsVersion = 9.0; 217 | TestTargetID = 8634EAED1F2829A200EC09CF; 218 | }; 219 | }; 220 | }; 221 | buildConfigurationList = 8634EAE91F2829A100EC09CF /* Build configuration list for PBXProject "PickerViewDemo" */; 222 | compatibilityVersion = "Xcode 8.0"; 223 | developmentRegion = en; 224 | hasScannedForEncodings = 0; 225 | knownRegions = ( 226 | en, 227 | Base, 228 | ); 229 | mainGroup = 8634EAE51F2829A100EC09CF; 230 | productRefGroup = 8634EAEF1F2829A200EC09CF /* Products */; 231 | projectDirPath = ""; 232 | projectRoot = ""; 233 | targets = ( 234 | 8634EAED1F2829A200EC09CF /* PickerViewDemo */, 235 | 8634EB051F2829A200EC09CF /* PickerViewDemoTests */, 236 | 8634EB101F2829A200EC09CF /* PickerViewDemoUITests */, 237 | ); 238 | }; 239 | /* End PBXProject section */ 240 | 241 | /* Begin PBXResourcesBuildPhase section */ 242 | 8634EAEC1F2829A200EC09CF /* Resources */ = { 243 | isa = PBXResourcesBuildPhase; 244 | buildActionMask = 2147483647; 245 | files = ( 246 | 8634EAFB1F2829A200EC09CF /* Assets.xcassets in Resources */, 247 | 86F094221F2F0B700067AF16 /* Main.storyboard in Resources */, 248 | ); 249 | runOnlyForDeploymentPostprocessing = 0; 250 | }; 251 | 8634EB041F2829A200EC09CF /* Resources */ = { 252 | isa = PBXResourcesBuildPhase; 253 | buildActionMask = 2147483647; 254 | files = ( 255 | ); 256 | runOnlyForDeploymentPostprocessing = 0; 257 | }; 258 | 8634EB0F1F2829A200EC09CF /* Resources */ = { 259 | isa = PBXResourcesBuildPhase; 260 | buildActionMask = 2147483647; 261 | files = ( 262 | ); 263 | runOnlyForDeploymentPostprocessing = 0; 264 | }; 265 | /* End PBXResourcesBuildPhase section */ 266 | 267 | /* Begin PBXSourcesBuildPhase section */ 268 | 8634EAEA1F2829A200EC09CF /* Sources */ = { 269 | isa = PBXSourcesBuildPhase; 270 | buildActionMask = 2147483647; 271 | files = ( 272 | 8634EAF61F2829A200EC09CF /* ViewController.m in Sources */, 273 | 8634EB011F2829A200EC09CF /* main.m in Sources */, 274 | 86D76F9620122C4600DC2093 /* PGPickerColumnCell.m in Sources */, 275 | 86D76F9820122C4600DC2093 /* PGPickerView.m in Sources */, 276 | 86D76F9720122C4600DC2093 /* PGPickerColumnView.m in Sources */, 277 | 86D76F9920122C4600DC2093 /* PGPickerTableView.m in Sources */, 278 | 8634EAF31F2829A200EC09CF /* AppDelegate.m in Sources */, 279 | ); 280 | runOnlyForDeploymentPostprocessing = 0; 281 | }; 282 | 8634EB021F2829A200EC09CF /* Sources */ = { 283 | isa = PBXSourcesBuildPhase; 284 | buildActionMask = 2147483647; 285 | files = ( 286 | ); 287 | runOnlyForDeploymentPostprocessing = 0; 288 | }; 289 | 8634EB0D1F2829A200EC09CF /* Sources */ = { 290 | isa = PBXSourcesBuildPhase; 291 | buildActionMask = 2147483647; 292 | files = ( 293 | ); 294 | runOnlyForDeploymentPostprocessing = 0; 295 | }; 296 | /* End PBXSourcesBuildPhase section */ 297 | 298 | /* Begin PBXTargetDependency section */ 299 | 8634EB081F2829A200EC09CF /* PBXTargetDependency */ = { 300 | isa = PBXTargetDependency; 301 | target = 8634EAED1F2829A200EC09CF /* PickerViewDemo */; 302 | targetProxy = 8634EB071F2829A200EC09CF /* PBXContainerItemProxy */; 303 | }; 304 | 8634EB131F2829A200EC09CF /* PBXTargetDependency */ = { 305 | isa = PBXTargetDependency; 306 | target = 8634EAED1F2829A200EC09CF /* PickerViewDemo */; 307 | targetProxy = 8634EB121F2829A200EC09CF /* PBXContainerItemProxy */; 308 | }; 309 | /* End PBXTargetDependency section */ 310 | 311 | /* Begin XCBuildConfiguration section */ 312 | 8634EB181F2829A200EC09CF /* Debug */ = { 313 | isa = XCBuildConfiguration; 314 | buildSettings = { 315 | ALWAYS_SEARCH_USER_PATHS = NO; 316 | CLANG_ANALYZER_NONNULL = YES; 317 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 318 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 319 | CLANG_CXX_LIBRARY = "libc++"; 320 | CLANG_ENABLE_MODULES = YES; 321 | CLANG_ENABLE_OBJC_ARC = YES; 322 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 323 | CLANG_WARN_BOOL_CONVERSION = YES; 324 | CLANG_WARN_COMMA = YES; 325 | CLANG_WARN_CONSTANT_CONVERSION = YES; 326 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 327 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 328 | CLANG_WARN_EMPTY_BODY = YES; 329 | CLANG_WARN_ENUM_CONVERSION = YES; 330 | CLANG_WARN_INFINITE_RECURSION = YES; 331 | CLANG_WARN_INT_CONVERSION = YES; 332 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 333 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 334 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 335 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 336 | CLANG_WARN_STRICT_PROTOTYPES = YES; 337 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 338 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 339 | CLANG_WARN_UNREACHABLE_CODE = YES; 340 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 341 | CODE_SIGN_IDENTITY = "iPhone Developer"; 342 | COPY_PHASE_STRIP = NO; 343 | DEBUG_INFORMATION_FORMAT = dwarf; 344 | ENABLE_STRICT_OBJC_MSGSEND = YES; 345 | ENABLE_TESTABILITY = YES; 346 | GCC_C_LANGUAGE_STANDARD = gnu11; 347 | GCC_DYNAMIC_NO_PIC = NO; 348 | GCC_NO_COMMON_BLOCKS = YES; 349 | GCC_OPTIMIZATION_LEVEL = 0; 350 | GCC_PREPROCESSOR_DEFINITIONS = ( 351 | "DEBUG=1", 352 | "$(inherited)", 353 | ); 354 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 355 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 356 | GCC_WARN_UNDECLARED_SELECTOR = YES; 357 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 358 | GCC_WARN_UNUSED_FUNCTION = YES; 359 | GCC_WARN_UNUSED_VARIABLE = YES; 360 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 361 | MTL_ENABLE_DEBUG_INFO = YES; 362 | ONLY_ACTIVE_ARCH = YES; 363 | SDKROOT = iphoneos; 364 | }; 365 | name = Debug; 366 | }; 367 | 8634EB191F2829A200EC09CF /* Release */ = { 368 | isa = XCBuildConfiguration; 369 | buildSettings = { 370 | ALWAYS_SEARCH_USER_PATHS = NO; 371 | CLANG_ANALYZER_NONNULL = YES; 372 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 373 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 374 | CLANG_CXX_LIBRARY = "libc++"; 375 | CLANG_ENABLE_MODULES = YES; 376 | CLANG_ENABLE_OBJC_ARC = YES; 377 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 378 | CLANG_WARN_BOOL_CONVERSION = YES; 379 | CLANG_WARN_COMMA = YES; 380 | CLANG_WARN_CONSTANT_CONVERSION = YES; 381 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 382 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 383 | CLANG_WARN_EMPTY_BODY = YES; 384 | CLANG_WARN_ENUM_CONVERSION = YES; 385 | CLANG_WARN_INFINITE_RECURSION = YES; 386 | CLANG_WARN_INT_CONVERSION = YES; 387 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 388 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 389 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 390 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 391 | CLANG_WARN_STRICT_PROTOTYPES = YES; 392 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 393 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 394 | CLANG_WARN_UNREACHABLE_CODE = YES; 395 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 396 | CODE_SIGN_IDENTITY = "iPhone Developer"; 397 | COPY_PHASE_STRIP = NO; 398 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 399 | ENABLE_NS_ASSERTIONS = NO; 400 | ENABLE_STRICT_OBJC_MSGSEND = YES; 401 | GCC_C_LANGUAGE_STANDARD = gnu11; 402 | GCC_NO_COMMON_BLOCKS = YES; 403 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 404 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 405 | GCC_WARN_UNDECLARED_SELECTOR = YES; 406 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 407 | GCC_WARN_UNUSED_FUNCTION = YES; 408 | GCC_WARN_UNUSED_VARIABLE = YES; 409 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 410 | MTL_ENABLE_DEBUG_INFO = NO; 411 | SDKROOT = iphoneos; 412 | VALIDATE_PRODUCT = YES; 413 | }; 414 | name = Release; 415 | }; 416 | 8634EB1B1F2829A200EC09CF /* Debug */ = { 417 | isa = XCBuildConfiguration; 418 | buildSettings = { 419 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 420 | DEVELOPMENT_TEAM = 65MUSRJ8L7; 421 | INFOPLIST_FILE = PickerViewDemo/Info.plist; 422 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 423 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 424 | PRODUCT_BUNDLE_IDENTIFIER = com.piggybear.PickerViewDemo; 425 | PRODUCT_NAME = "$(TARGET_NAME)"; 426 | TARGETED_DEVICE_FAMILY = "1,2"; 427 | }; 428 | name = Debug; 429 | }; 430 | 8634EB1C1F2829A200EC09CF /* Release */ = { 431 | isa = XCBuildConfiguration; 432 | buildSettings = { 433 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 434 | DEVELOPMENT_TEAM = 65MUSRJ8L7; 435 | INFOPLIST_FILE = PickerViewDemo/Info.plist; 436 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 437 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 438 | PRODUCT_BUNDLE_IDENTIFIER = com.piggybear.PickerViewDemo; 439 | PRODUCT_NAME = "$(TARGET_NAME)"; 440 | TARGETED_DEVICE_FAMILY = "1,2"; 441 | }; 442 | name = Release; 443 | }; 444 | 8634EB1E1F2829A200EC09CF /* Debug */ = { 445 | isa = XCBuildConfiguration; 446 | buildSettings = { 447 | BUNDLE_LOADER = "$(TEST_HOST)"; 448 | DEVELOPMENT_TEAM = 65MUSRJ8L7; 449 | INFOPLIST_FILE = PickerViewDemoTests/Info.plist; 450 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 451 | PRODUCT_BUNDLE_IDENTIFIER = com.piggybear.PickerViewDemoTests; 452 | PRODUCT_NAME = "$(TARGET_NAME)"; 453 | TARGETED_DEVICE_FAMILY = "1,2"; 454 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PickerViewDemo.app/PickerViewDemo"; 455 | }; 456 | name = Debug; 457 | }; 458 | 8634EB1F1F2829A200EC09CF /* Release */ = { 459 | isa = XCBuildConfiguration; 460 | buildSettings = { 461 | BUNDLE_LOADER = "$(TEST_HOST)"; 462 | DEVELOPMENT_TEAM = 65MUSRJ8L7; 463 | INFOPLIST_FILE = PickerViewDemoTests/Info.plist; 464 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 465 | PRODUCT_BUNDLE_IDENTIFIER = com.piggybear.PickerViewDemoTests; 466 | PRODUCT_NAME = "$(TARGET_NAME)"; 467 | TARGETED_DEVICE_FAMILY = "1,2"; 468 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PickerViewDemo.app/PickerViewDemo"; 469 | }; 470 | name = Release; 471 | }; 472 | 8634EB211F2829A200EC09CF /* Debug */ = { 473 | isa = XCBuildConfiguration; 474 | buildSettings = { 475 | DEVELOPMENT_TEAM = 65MUSRJ8L7; 476 | INFOPLIST_FILE = PickerViewDemoUITests/Info.plist; 477 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 478 | PRODUCT_BUNDLE_IDENTIFIER = com.piggybear.PickerViewDemoUITests; 479 | PRODUCT_NAME = "$(TARGET_NAME)"; 480 | TARGETED_DEVICE_FAMILY = "1,2"; 481 | TEST_TARGET_NAME = PickerViewDemo; 482 | }; 483 | name = Debug; 484 | }; 485 | 8634EB221F2829A200EC09CF /* Release */ = { 486 | isa = XCBuildConfiguration; 487 | buildSettings = { 488 | DEVELOPMENT_TEAM = 65MUSRJ8L7; 489 | INFOPLIST_FILE = PickerViewDemoUITests/Info.plist; 490 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 491 | PRODUCT_BUNDLE_IDENTIFIER = com.piggybear.PickerViewDemoUITests; 492 | PRODUCT_NAME = "$(TARGET_NAME)"; 493 | TARGETED_DEVICE_FAMILY = "1,2"; 494 | TEST_TARGET_NAME = PickerViewDemo; 495 | }; 496 | name = Release; 497 | }; 498 | /* End XCBuildConfiguration section */ 499 | 500 | /* Begin XCConfigurationList section */ 501 | 8634EAE91F2829A100EC09CF /* Build configuration list for PBXProject "PickerViewDemo" */ = { 502 | isa = XCConfigurationList; 503 | buildConfigurations = ( 504 | 8634EB181F2829A200EC09CF /* Debug */, 505 | 8634EB191F2829A200EC09CF /* Release */, 506 | ); 507 | defaultConfigurationIsVisible = 0; 508 | defaultConfigurationName = Release; 509 | }; 510 | 8634EB1A1F2829A200EC09CF /* Build configuration list for PBXNativeTarget "PickerViewDemo" */ = { 511 | isa = XCConfigurationList; 512 | buildConfigurations = ( 513 | 8634EB1B1F2829A200EC09CF /* Debug */, 514 | 8634EB1C1F2829A200EC09CF /* Release */, 515 | ); 516 | defaultConfigurationIsVisible = 0; 517 | defaultConfigurationName = Release; 518 | }; 519 | 8634EB1D1F2829A200EC09CF /* Build configuration list for PBXNativeTarget "PickerViewDemoTests" */ = { 520 | isa = XCConfigurationList; 521 | buildConfigurations = ( 522 | 8634EB1E1F2829A200EC09CF /* Debug */, 523 | 8634EB1F1F2829A200EC09CF /* Release */, 524 | ); 525 | defaultConfigurationIsVisible = 0; 526 | defaultConfigurationName = Release; 527 | }; 528 | 8634EB201F2829A200EC09CF /* Build configuration list for PBXNativeTarget "PickerViewDemoUITests" */ = { 529 | isa = XCConfigurationList; 530 | buildConfigurations = ( 531 | 8634EB211F2829A200EC09CF /* Debug */, 532 | 8634EB221F2829A200EC09CF /* Release */, 533 | ); 534 | defaultConfigurationIsVisible = 0; 535 | defaultConfigurationName = Release; 536 | }; 537 | /* End XCConfigurationList section */ 538 | }; 539 | rootObject = 8634EAE61F2829A100EC09CF /* Project object */; 540 | } 541 | -------------------------------------------------------------------------------- /Demo/PickerViewDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Demo/PickerViewDemo.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Demo/PickerViewDemo.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Demo/PickerViewDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // PickerViewDemo 4 | // 5 | // Created by piggybear on 2017/7/26. 6 | // Copyright © 2017年 piggybear. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /Demo/PickerViewDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // PickerViewDemo 4 | // 5 | // Created by piggybear on 2017/7/26. 6 | // Copyright © 2017年 piggybear. 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 | - (void)applicationWillResignActive:(UIApplication *)application { 25 | // 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. 26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 27 | } 28 | 29 | 30 | - (void)applicationDidEnterBackground:(UIApplication *)application { 31 | // 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. 32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 33 | } 34 | 35 | 36 | - (void)applicationWillEnterForeground:(UIApplication *)application { 37 | // 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. 38 | } 39 | 40 | 41 | - (void)applicationDidBecomeActive:(UIApplication *)application { 42 | // 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. 43 | } 44 | 45 | 46 | - (void)applicationWillTerminate:(UIApplication *)application { 47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 48 | } 49 | 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /Demo/PickerViewDemo/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 | } -------------------------------------------------------------------------------- /Demo/PickerViewDemo/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 | -------------------------------------------------------------------------------- /Demo/PickerViewDemo/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 | -------------------------------------------------------------------------------- /Demo/PickerViewDemo/UIColor+PGHex.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+PGHex.h 3 | // HooDatePickerDemo 4 | // 5 | // Created by piggybear on 2017/7/25. 6 | // Copyright © 2017年 piggybear. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIColor (PGHex) 12 | + (UIColor *)colorWithHexString:(NSString *)hexString; 13 | @end 14 | -------------------------------------------------------------------------------- /Demo/PickerViewDemo/UIColor+PGHex.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+PGHex.m 3 | // HooDatePickerDemo 4 | // 5 | // Created by piggybear on 2017/7/25. 6 | // Copyright © 2017年 piggybear. All rights reserved. 7 | // 8 | 9 | #import "UIColor+PGHex.h" 10 | 11 | @implementation UIColor (PGHex) 12 | 13 | + (CGFloat)colorComponentFrom:(NSString *)string start:(NSUInteger)start length:(NSUInteger) length { 14 | NSString *substring = [string substringWithRange:NSMakeRange(start, length)]; 15 | NSString *fullHex = length == 2 ? substring : [NSString stringWithFormat: @"%@%@", substring, substring]; 16 | unsigned hexComponent; 17 | [[NSScanner scannerWithString: fullHex] scanHexInt: &hexComponent]; 18 | return hexComponent / 255.0; 19 | } 20 | 21 | + (UIColor *)colorWithHexString:(NSString *)hexString { 22 | CGFloat alpha, red, blue, green; 23 | 24 | NSString *colorString = [[hexString stringByReplacingOccurrencesOfString:@"#" withString:@""] uppercaseString]; 25 | switch ([colorString length]) { 26 | case 3: // #RGB 27 | { 28 | alpha = 1.0f; 29 | red = [self colorComponentFrom:colorString start:0 length:1]; 30 | green = [self colorComponentFrom:colorString start:1 length:1]; 31 | blue = [self colorComponentFrom:colorString start:2 length:1]; 32 | } 33 | break; 34 | 35 | case 4: // #ARGB 36 | { 37 | alpha = [self colorComponentFrom:colorString start:0 length:1]; 38 | red = [self colorComponentFrom:colorString start:1 length:1]; 39 | green = [self colorComponentFrom:colorString start:2 length:1]; 40 | blue = [self colorComponentFrom:colorString start:3 length:1]; 41 | } 42 | break; 43 | 44 | case 6: // #RRGGBB 45 | { 46 | alpha = 1.0f; 47 | red = [self colorComponentFrom:colorString start:0 length:2]; 48 | green = [self colorComponentFrom:colorString start:2 length:2]; 49 | blue = [self colorComponentFrom:colorString start:4 length:2]; 50 | } 51 | break; 52 | 53 | case 8: // #AARRGGBB 54 | { 55 | alpha = [self colorComponentFrom:colorString start:0 length:2]; 56 | red = [self colorComponentFrom:colorString start:2 length:2]; 57 | green = [self colorComponentFrom:colorString start:4 length:2]; 58 | blue = [self colorComponentFrom:colorString start:6 length:2]; 59 | } 60 | break; 61 | default: 62 | return nil; 63 | } 64 | return [UIColor colorWithRed:red green:green blue:blue alpha:alpha]; 65 | } 66 | @end 67 | -------------------------------------------------------------------------------- /Demo/PickerViewDemo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // PickerViewDemo 4 | // 5 | // Created by piggybear on 2017/7/26. 6 | // Copyright © 2017年 piggybear. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /Demo/PickerViewDemo/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // PickerViewDemo 4 | // 5 | // Created by piggybear on 2017/7/26. 6 | // Copyright © 2017年 piggybear. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "PGPickerView.h" 11 | 12 | @interface ViewController () 13 | @property (nonatomic, weak) IBOutlet PGPickerView *pickerView; 14 | @property (nonatomic, strong) NSString *string; 15 | @property (nonatomic, strong) NSArray *datas1; 16 | @property (nonatomic, strong) NSArray *datas2; 17 | @property (nonatomic, strong) NSArray *datas3; 18 | @end 19 | 20 | #define kScreenWidth [UIScreen mainScreen].bounds.size.width 21 | #define kScreenHeight [UIScreen mainScreen].bounds.size.height 22 | @implementation ViewController 23 | 24 | - (void)viewDidLoad { 25 | [super viewDidLoad]; 26 | self.datas1 = @[@"北京", @"上海", @"天津", @"重庆", @"四川", @"贵州", @"云南", @"西藏", @"河南", @"湖北"]; 27 | self.datas2 = @[@"东城区",@"西城区",@"崇文区",@"宣武区",@"朝阳区",@"丰台区",@"石景山区",@"海淀区",@"门头沟区",@"房山区"]; 28 | self.datas3 = @[@"黄浦区",@"卢湾区",@"徐汇区",@"长宁区",@"静安区",@"普陀区",@"闸北区",@"虹口区",@"杨浦区",@"宝山区"]; 29 | self.pickerView.delegate = self; 30 | self.pickerView.dataSource = self; 31 | self.pickerView.type = PGPickerViewLineTypelineSegment; 32 | 33 | [self.pickerView selectRow:5 inComponent:0 animated:true]; 34 | [self.pickerView selectRow:7 inComponent:1 animated:true]; 35 | self.pickerView.rowHeight = 45; 36 | self.pickerView.isHiddenMiddleText = false; 37 | 38 | //设置线条的颜色 39 | self.pickerView.lineBackgroundColor = [UIColor redColor]; 40 | //设置选中行的字体颜色 41 | self.pickerView.textColorOfSelectedRow = [UIColor blueColor]; 42 | //设置未选中行的字体颜色 43 | self.pickerView.textColorOfOtherRow = [UIColor blackColor]; 44 | } 45 | 46 | #pragma UIPickerViewDataSource 47 | - (NSInteger)numberOfComponentsInPickerView:(PGPickerView *)pickerView { 48 | return 3; 49 | } 50 | 51 | - (NSInteger)pickerView:(PGPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { 52 | return self.datas1.count; 53 | } 54 | #pragma UIPickerViewDelegate 55 | - (nullable NSString *)pickerView:(PGPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component { 56 | if (component == 0) { 57 | return self.datas1[row]; 58 | } 59 | if (component == 1) { 60 | return self.datas2[row]; 61 | } 62 | return self.datas3[row]; 63 | } 64 | 65 | - (void)pickerView:(PGPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { 66 | NSLog(@"row = %ld component = %ld", row, component); 67 | } 68 | 69 | @end 70 | -------------------------------------------------------------------------------- /Demo/PickerViewDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // PickerViewDemo 4 | // 5 | // Created by piggybear on 2017/7/26. 6 | // Copyright © 2017年 piggybear. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Images/middle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaozhuxiong121/PGPickerView/59790a5cf0a46fce5784c27c55678ecfc6263ce7/Images/middle.png -------------------------------------------------------------------------------- /Images/type1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaozhuxiong121/PGPickerView/59790a5cf0a46fce5784c27c55678ecfc6263ce7/Images/type1.png -------------------------------------------------------------------------------- /Images/type2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaozhuxiong121/PGPickerView/59790a5cf0a46fce5784c27c55678ecfc6263ce7/Images/type2.png -------------------------------------------------------------------------------- /Images/type3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaozhuxiong121/PGPickerView/59790a5cf0a46fce5784c27c55678ecfc6263ce7/Images/type3.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 piggybear 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 | -------------------------------------------------------------------------------- /PGPickerView.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaozhuxiong121/PGPickerView/59790a5cf0a46fce5784c27c55678ecfc6263ce7/PGPickerView.gif -------------------------------------------------------------------------------- /PGPickerView.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "PGPickerView" 3 | s.version = "1.3.8" 4 | s.summary = "PGPickerView是将UIPickerView的弯曲弧度变成直列表,可以是单列表,多列表,还可以修改选中label的字体颜色等。" 5 | s.homepage = "https://github.com/xiaozhuxiong121/PGPickerView" 6 | s.license = "MIT" 7 | s.author = { "piggybear" => "piggybear_net@163.com" } 8 | s.platform = :ios, "7.0" 9 | s.source = { :git => "https://github.com/xiaozhuxiong121/PGPickerView.git", :tag => s.version } 10 | s.source_files = "PGPickerView", "PGPickerView/**/*.{h,m}" 11 | s.frameworks = "UIKit" 12 | s.requires_arc = true 13 | 14 | end 15 | 16 | -------------------------------------------------------------------------------- /PGPickerView/PGPickerColumnCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // PGPickerColumnCell.h 3 | // PGPickerView 4 | // 5 | // Created by piggybear on 2017/7/26. 6 | // Copyright © 2017年 piggybear. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface PGPickerColumnCell : UITableViewCell 12 | @property (nonatomic, weak) UILabel *label; 13 | 14 | - (void)transformWith:(CGFloat)angle scale:(CGFloat)scale; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /PGPickerView/PGPickerColumnCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // PGPickerColumnCell.m 3 | // PGPickerView 4 | // 5 | // Created by piggybear on 2017/7/26. 6 | // Copyright © 2017年 piggybear. All rights reserved. 7 | // 8 | 9 | #import "PGPickerColumnCell.h" 10 | 11 | @implementation PGPickerColumnCell 12 | 13 | #define kContentFont 17 14 | 15 | - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { 16 | if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) { 17 | self.selectionStyle = UITableViewCellSelectionStyleNone; 18 | self.backgroundColor = [UIColor clearColor]; 19 | } 20 | return self; 21 | } 22 | 23 | - (void)transformWith:(CGFloat)angle scale:(CGFloat)scale { 24 | CATransform3D transform = CATransform3DIdentity; 25 | transform = CATransform3DRotate(transform, angle, 1, 0, 0); 26 | transform = CATransform3DScale(transform, scale, scale, scale); 27 | self.layer.transform = transform; 28 | } 29 | 30 | - (void)layoutSubviews { 31 | [super layoutSubviews]; 32 | self.label.frame = self.contentView.bounds; 33 | } 34 | 35 | #pragma Getter 36 | - (UILabel *)label { 37 | if (!_label) { 38 | UILabel *label = [[UILabel alloc]initWithFrame:self.contentView.bounds]; 39 | label.font = [UIFont systemFontOfSize:kContentFont]; 40 | label.textAlignment = NSTextAlignmentCenter; 41 | [self.contentView addSubview:label]; 42 | _label = label; 43 | } 44 | return _label; 45 | } 46 | @end 47 | -------------------------------------------------------------------------------- /PGPickerView/PGPickerColumnView.h: -------------------------------------------------------------------------------- 1 | // 2 | // PGPickerColumnView.h 3 | // PGPickerView 4 | // 5 | // Created by piggybear on 2017/7/26. 6 | // Copyright © 2017年 piggybear. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @protocol PGPickerColumnViewDelegate; 12 | 13 | @interface PGPickerColumnView : UIView 14 | @property (nonatomic, weak) id delegate; 15 | @property (nonatomic, strong) NSArray *datas; 16 | @property (nonatomic, assign) NSUInteger component; 17 | @property (nonatomic, assign) NSUInteger selectedRow; 18 | @property (nonatomic, strong) NSArray *viewBackgroundColors; 19 | @property (nonatomic, assign) BOOL refresh; 20 | 21 | @property (nonatomic, copy) NSString *textOfSelectedRow; 22 | @property (nonatomic, strong)UIColor *textColorOfSelectedRow; 23 | @property(nonatomic, strong) UIFont *textFontOfSelectedRow; 24 | 25 | @property (nonatomic, strong)UIColor *textColorOfOtherRow; 26 | @property(nonatomic, strong) UIFont *textFontOfOtherRow; 27 | 28 | @property(nonatomic, assign) BOOL isHiddenWheels; 29 | @property(nonatomic, assign) BOOL isCycleScroll; 30 | 31 | - (instancetype)initWithFrame:(CGRect)frame rowHeight:(CGFloat)rowHeight upLineHeight:(CGFloat)upLineHeight downLineHeight:(CGFloat)downLineHeight isCycleScroll:(BOOL)isCycleScroll datas:(NSArray *)datas; 32 | - (void)selectRow:(NSInteger)row animated:(BOOL)animated; 33 | @end 34 | 35 | @protocol PGPickerColumnViewDelegate 36 | @optional 37 | - (void)pickerColumnView:(PGPickerColumnView *)pickerColumnView didSelectRow:(NSInteger)row; 38 | - (void)pickerColumnView:(PGPickerColumnView *)pickerColumnView title:(NSString *)title didSelectRow:(NSInteger)row; 39 | 40 | - (UIFont *)pickerColumnView:(PGPickerColumnView *)pickerColumnView textFontOfOtherRow:(NSInteger)row InComponent:(NSInteger)component; 41 | - (UIColor *)pickerColumnView:(PGPickerColumnView *)pickerColumnView textColorOfOtherRow:(NSInteger)row InComponent:(NSInteger)component; 42 | @end 43 | -------------------------------------------------------------------------------- /PGPickerView/PGPickerColumnView.m: -------------------------------------------------------------------------------- 1 | // 2 | // PGPickerColumnView.m 3 | // PGPickerView 4 | // 5 | // Created by piggybear on 2017/7/26. 6 | // Copyright © 2017年 piggybear. All rights reserved. 7 | // 8 | 9 | #import "PGPickerColumnView.h" 10 | #import "PGPickerColumnCell.h" 11 | #import "PGPickerTableView.h" 12 | 13 | @interface PGPickerColumnView() 14 | @property (nonatomic) CGFloat rowHeight; 15 | 16 | @property (nonatomic, weak) UIView *upView; 17 | @property (nonatomic, weak) UIView *centerView; 18 | @property (nonatomic, weak) UIView *downView; 19 | 20 | @property (nonatomic, weak) PGPickerTableView *upTableView; 21 | @property (nonatomic, weak) PGPickerTableView *centerTableView; 22 | @property (nonatomic, weak) PGPickerTableView *downTableView; 23 | 24 | @property (nonatomic, assign) CGFloat offset; 25 | @property (nonatomic, assign) NSInteger offsetCount; 26 | @property (nonatomic) CGFloat upLinePosY; 27 | 28 | @property (nonatomic, assign) CGFloat upLineHeight; 29 | @property (nonatomic, assign) CGFloat downLineHeight; 30 | 31 | @property (nonatomic, assign) CGFloat showCount; 32 | 33 | @property (nonatomic, assign) BOOL isSubViewLayouted; 34 | @property (nonatomic, assign) CGFloat circumference; 35 | @property (nonatomic, assign) CGFloat radius; 36 | 37 | @property(nonatomic, assign) BOOL copyCycleScroll; 38 | @property (nonatomic, assign) NSInteger copyOffsetCount; 39 | 40 | @property(nonatomic, assign) BOOL isSelectedRow; 41 | @end 42 | 43 | @implementation PGPickerColumnView 44 | 45 | #define kWidth self.frame.size.width 46 | #define kHeight self.frame.size.height 47 | 48 | static NSString *const cellReuseIdentifier = @"PGPickerColumnCell"; 49 | 50 | - (instancetype)initWithFrame:(CGRect)frame rowHeight:(CGFloat)rowHeight upLineHeight:(CGFloat)upLineHeight downLineHeight:(CGFloat)downLineHeight isCycleScroll:(BOOL)isCycleScroll datas:(NSArray *)datas { 51 | if (self = [super initWithFrame:frame]) { 52 | self.isCycleScroll = isCycleScroll; 53 | self.copyCycleScroll = isCycleScroll; 54 | self.rowHeight = rowHeight; 55 | self.upLineHeight = upLineHeight; 56 | self.downLineHeight = downLineHeight; 57 | self.backgroundColor = [UIColor clearColor]; 58 | self.upLinePosY = (self.bounds.size.height - self.rowHeight) / 2 - self.upLineHeight; 59 | NSInteger index = self.upLinePosY / self.rowHeight; 60 | self.offsetCount = index + 1; 61 | self.offset = self.offsetCount * self.rowHeight - self.upLinePosY; 62 | if (self.offset == self.rowHeight) { 63 | self.offset = 0; 64 | self.offsetCount -= 1; 65 | } 66 | self.showCount = (frame.size.height / self.rowHeight - 1) / 2; 67 | self.circumference = self.rowHeight * self.showCount * 2 - 25; 68 | self.radius = self.circumference / M_PI * 2; 69 | self.copyOffsetCount = self.offsetCount; 70 | 71 | [self setupCycleScrollWithDatas:datas]; 72 | [self setupView]; 73 | } 74 | return self; 75 | } 76 | 77 | - (void)layoutSubviews { 78 | [super layoutSubviews]; 79 | if (self.isSubViewLayouted) { 80 | return; 81 | } 82 | self.isSubViewLayouted = true; 83 | } 84 | 85 | - (void)setupCycleScrollWithDatas:(NSArray *)datas { 86 | if (self.frame.size.height >= self.rowHeight * datas.count) { 87 | self.isCycleScroll = false; 88 | }else { 89 | self.isCycleScroll = self.copyCycleScroll; 90 | } 91 | if (self.isCycleScroll) { 92 | self.offsetCount = 0; 93 | }else { 94 | self.offsetCount = self.copyOffsetCount; 95 | } 96 | } 97 | 98 | - (void)setupView { 99 | CGFloat upViewHeight = kHeight / 2 - self.rowHeight / 2 - self.upLineHeight; 100 | CGFloat centerViewPosY = upViewHeight + self.upLineHeight; 101 | CGFloat downViewPosY = centerViewPosY + self.rowHeight + self.downLineHeight; 102 | 103 | UIView *upView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, kWidth, upViewHeight)]; 104 | upView.backgroundColor = [UIColor clearColor]; 105 | upView.clipsToBounds = true; 106 | [self addSubview:upView]; 107 | self.upView = upView; 108 | 109 | UIView *downView = [[UIView alloc]initWithFrame:CGRectMake(0, downViewPosY, kWidth, kHeight - downViewPosY)]; 110 | downView.backgroundColor = [UIColor clearColor]; 111 | downView.clipsToBounds = true; 112 | [self addSubview:downView]; 113 | self.downView = downView; 114 | 115 | UIView *centerView = [[UIView alloc]initWithFrame:CGRectMake(0, centerViewPosY, kWidth, self.rowHeight)]; 116 | centerView.backgroundColor = [UIColor clearColor]; 117 | centerView.clipsToBounds = true; 118 | [self addSubview:centerView]; 119 | self.centerView = centerView; 120 | [self setupTableView]; 121 | } 122 | 123 | - (void)setupTableView { 124 | { 125 | CGRect frame = self.bounds; 126 | frame.origin.y = -self.offset; 127 | frame.size.height += self.offset; 128 | PGPickerTableView *tableView = [[PGPickerTableView alloc]initWithFrame:frame style:UITableViewStylePlain]; 129 | [tableView registerClass:[PGPickerColumnCell class] forCellReuseIdentifier:cellReuseIdentifier]; 130 | tableView.delegate = self; 131 | tableView.dataSource = self; 132 | tableView.showsVerticalScrollIndicator = false; 133 | tableView.showsHorizontalScrollIndicator = false; 134 | [self.upView addSubview:tableView]; 135 | self.upTableView = tableView; 136 | } 137 | { 138 | CGRect frame = [self convertRect:self.upTableView.frame toView:self.centerView]; 139 | PGPickerTableView *tableView = [[PGPickerTableView alloc]initWithFrame:frame style:UITableViewStylePlain]; 140 | [tableView registerClass:[PGPickerColumnCell class] forCellReuseIdentifier:cellReuseIdentifier]; 141 | tableView.delegate = self; 142 | tableView.dataSource = self; 143 | tableView.showsVerticalScrollIndicator = false; 144 | tableView.showsHorizontalScrollIndicator = false; 145 | [self.centerView addSubview:tableView]; 146 | self.centerTableView = tableView; 147 | [self bringSubviewToFront:tableView]; 148 | } 149 | 150 | { 151 | CGRect frame = [self convertRect:self.upTableView.frame toView:self.downView]; 152 | PGPickerTableView *tableView = [[PGPickerTableView alloc]initWithFrame:frame style:UITableViewStylePlain]; 153 | [tableView registerClass:[PGPickerColumnCell class] forCellReuseIdentifier:cellReuseIdentifier]; 154 | tableView.delegate = self; 155 | tableView.dataSource = self; 156 | tableView.showsVerticalScrollIndicator = false; 157 | tableView.showsHorizontalScrollIndicator = false; 158 | [self.downView addSubview:tableView]; 159 | self.downTableView = tableView; 160 | } 161 | } 162 | 163 | - (NSInteger)setupSelectedRow { 164 | NSInteger row = self.centerTableView.contentOffset.y / self.rowHeight + 0.5; 165 | if (self.isCycleScroll) { 166 | CGFloat posY = self.centerTableView.contentOffset.y + self.copyOffsetCount * self.rowHeight + self.rowHeight / 2; 167 | NSInteger count = posY / (self.datas.count * self.rowHeight); 168 | CGFloat newPosY = (self.centerTableView.contentOffset.y + self.copyOffsetCount * self.rowHeight) - (self.datas.count * self.rowHeight) * count; 169 | if (newPosY < 0) { 170 | newPosY = 0; 171 | } 172 | row = newPosY / self.rowHeight + 0.5; 173 | } 174 | return row; 175 | } 176 | 177 | - (void)setupTableViewScroll:(UITableView *)tableView animated:(BOOL)animated { 178 | CGPoint offsetPoint = CGPointMake(tableView.contentOffset.x, tableView.contentOffset.y + self.rowHeight / 2); 179 | NSIndexPath *indexPath = [tableView indexPathForRowAtPoint: offsetPoint]; 180 | [tableView scrollToRowAtIndexPath: indexPath atScrollPosition: UITableViewScrollPositionTop animated:animated]; 181 | } 182 | 183 | - (void)selectRow:(NSInteger)row animated:(BOOL)animated { 184 | NSInteger newRow = row; 185 | if (self.isCycleScroll) { 186 | newRow = row - self.copyOffsetCount; 187 | } 188 | if (animated) { 189 | NSIndexPath *indexPath = [NSIndexPath indexPathForRow:newRow inSection:0]; 190 | [self.centerTableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:true]; 191 | self.selectedRow = row; 192 | self.isSelectedRow = true; 193 | }else { 194 | self.centerTableView.contentOffset = CGPointMake(0, newRow * self.rowHeight); 195 | [self scrollViewDidEndDecelerating: self.centerTableView]; 196 | } 197 | } 198 | 199 | #pragma mark - UIScrollViewDelegate 200 | - (void)scrollViewDidScroll:(UITableView *)tableView { 201 | CGPoint offset = tableView.contentOffset; 202 | NSInteger rowHeight = self.rowHeight; 203 | NSInteger posY = offset.y; 204 | NSInteger value = posY % rowHeight; 205 | CGFloat itemAngle = value * ((rowHeight / self.radius) / rowHeight); 206 | 207 | if (self.isCycleScroll) { 208 | if (posY < self.rowHeight * self.datas.count * 2) { 209 | posY = posY + self.rowHeight * self.datas.count; 210 | } 211 | if (posY > self.rowHeight * self.datas.count * 3) { 212 | posY = posY - self.rowHeight * self.datas.count; 213 | } 214 | } 215 | 216 | if (self.centerTableView == tableView) { 217 | self.upTableView.contentOffset = CGPointMake(0, posY); 218 | self.downTableView.contentOffset = CGPointMake(0, posY); 219 | return; 220 | } 221 | 222 | if (tableView == self.downTableView) { 223 | self.centerTableView.contentOffset = CGPointMake(0, posY); 224 | if (!self.isHiddenWheels) { 225 | [tableView.visibleCells enumerateObjectsUsingBlock:^(__kindof PGPickerColumnCell * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 226 | NSUInteger index = idx - self.showCount; 227 | NSInteger length = index * rowHeight; 228 | CGFloat angle = length / self.radius - itemAngle; 229 | CGFloat scale = cos(angle / 2); 230 | [obj transformWith:angle scale:scale]; 231 | }]; 232 | } 233 | return; 234 | } 235 | 236 | if (tableView == self.upTableView) { 237 | self.centerTableView.contentOffset = CGPointMake(0, posY); 238 | if (!self.isHiddenWheels) { 239 | [tableView.visibleCells enumerateObjectsUsingBlock:^(__kindof PGPickerColumnCell * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 240 | NSUInteger index = self.showCount - idx; 241 | NSInteger length = index * rowHeight; 242 | CGFloat angle = length / self.radius + itemAngle; 243 | CGFloat scale = cos(angle / 2); 244 | [obj transformWith:angle scale: scale]; 245 | }]; 246 | } 247 | } 248 | } 249 | 250 | - (void)scrollViewDidEndDragging:(UITableView *)scrollView willDecelerate:(BOOL)decelerate{ 251 | if (decelerate) return; 252 | [self scrollViewDidEndDecelerating:scrollView]; 253 | } 254 | 255 | - (void)scrollViewDidEndDecelerating:(UITableView *)tableView { 256 | [self setupTableViewScroll:tableView animated:true]; 257 | self.selectedRow = [self setupSelectedRow]; 258 | } 259 | 260 | - (void)scrollViewDidEndScrollingAnimation:(UITableView *)tableView { 261 | if (!self.isSelectedRow) { 262 | [self setupTableViewScroll:tableView animated:false]; 263 | NSUInteger row = [self setupSelectedRow]; 264 | self.selectedRow = row; 265 | } 266 | if (self.isSelectedRow) { 267 | self.isSelectedRow = false; 268 | } 269 | 270 | } 271 | 272 | #pragma mark - row logic 273 | - (NSUInteger)numberOfRowsInTableView { 274 | return self.datas.count + self.offsetCount * 2; 275 | } 276 | 277 | #pragma mark - UITableViewDataSource 278 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 279 | if (self.isCycleScroll) { 280 | return 10; 281 | } 282 | return 1; 283 | } 284 | 285 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 286 | return [self numberOfRowsInTableView]; 287 | } 288 | 289 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 290 | tableView.separatorStyle = UITableViewCellSeparatorStyleNone; 291 | PGPickerColumnCell *cell = [tableView dequeueReusableCellWithIdentifier:cellReuseIdentifier]; 292 | NSInteger row = indexPath.row - self.offsetCount; 293 | 294 | if (indexPath.row < self.offsetCount || row >= self.datas.count) { 295 | cell.label.attributedText = [[NSAttributedString alloc] initWithString: @""]; 296 | cell.contentView.backgroundColor = [UIColor clearColor]; 297 | }else { 298 | cell.label.attributedText = self.datas[row]; 299 | cell.contentView.backgroundColor = self.viewBackgroundColors[row]; 300 | 301 | if (!self.isHiddenWheels) { 302 | if (tableView == self.downTableView) { 303 | NSUInteger index = row - self.selectedRow; 304 | NSInteger length = index * self.rowHeight; 305 | CGFloat angle = length / self.radius; 306 | CGFloat scale = cos(angle / 2); 307 | [cell transformWith:angle scale:scale]; 308 | }else if (tableView == self.upTableView) { 309 | NSUInteger index = self.selectedRow - row; 310 | NSInteger length = index * self.rowHeight; 311 | CGFloat angle = length / self.radius; 312 | CGFloat scale = cos(angle / 2); 313 | [cell transformWith:angle scale:scale]; 314 | } 315 | } 316 | } 317 | if (tableView == self.centerTableView) { 318 | cell.label.textColor = self.textColorOfSelectedRow; 319 | cell.label.font = self.textFontOfSelectedRow; 320 | }else { 321 | cell.label.textColor = [self textColorOfOtherRow:row]; 322 | cell.label.font = [self textFontOfOtherRow:row]; 323 | } 324 | return cell; 325 | } 326 | 327 | #pragma mark - UITableViewDelegate 328 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 329 | NSInteger row = indexPath.row; 330 | if (row < self.offsetCount || row >= self.datas.count + self.offsetCount) { 331 | return; 332 | } 333 | UITableViewScrollPosition position = UITableViewScrollPositionTop; 334 | if (self.isCycleScroll) { 335 | position = UITableViewScrollPositionMiddle; 336 | } 337 | row = indexPath.row - self.offsetCount; 338 | [tableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:indexPath.row - self.offsetCount inSection: indexPath.section] animated:true scrollPosition:position]; 339 | self.selectedRow = indexPath.row - self.offsetCount; 340 | } 341 | 342 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 343 | if ([self numberOfRowsInTableView] - 1 == indexPath.row && !self.isCycleScroll) { 344 | CGFloat tmp = self.offsetCount * self.rowHeight - self.upLinePosY; 345 | if (self.rowHeight > 44) { 346 | return fabs(tmp - self.rowHeight); 347 | } 348 | } 349 | return self.rowHeight; 350 | } 351 | 352 | - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath { 353 | return self.rowHeight; 354 | } 355 | 356 | #pragma mark - Setter 357 | - (void)setSelectedRow:(NSUInteger)selectedRow { 358 | _selectedRow = selectedRow; 359 | if (self.datas.count > selectedRow) { 360 | NSAttributedString *attriString = self.datas[selectedRow]; 361 | self.textOfSelectedRow = attriString.string; 362 | } 363 | if (self.delegate && [self.delegate respondsToSelector:@selector(pickerColumnView:didSelectRow:)]) { 364 | [self.delegate pickerColumnView:self didSelectRow:selectedRow]; 365 | } 366 | if (self.delegate && [self.delegate respondsToSelector:@selector(pickerColumnView:title:didSelectRow:)]) { 367 | [self.delegate pickerColumnView:self title:self.textOfSelectedRow didSelectRow:selectedRow]; 368 | } 369 | } 370 | 371 | - (void)setDatas:(NSArray *)datas { 372 | _datas = datas; 373 | [self setupCycleScrollWithDatas:datas]; 374 | [self safeReloadData]; 375 | } 376 | 377 | #pragma mark - other 378 | - (UIFont *)textFontOfOtherRow:(NSInteger)row { 379 | if (self.delegate && [self.delegate respondsToSelector:@selector(pickerColumnView:textFontOfOtherRow:InComponent:)]) { 380 | return [self.delegate pickerColumnView:self textFontOfOtherRow:row InComponent:self.component]; 381 | } 382 | return self.textFontOfOtherRow; 383 | } 384 | 385 | - (UIColor *)textColorOfOtherRow:(NSInteger)row { 386 | if (self.delegate && [self.delegate respondsToSelector:@selector(pickerColumnView:textColorOfOtherRow:InComponent:)]) { 387 | return [self.delegate pickerColumnView:self textColorOfOtherRow:row InComponent:self.component]; 388 | } 389 | return self.textColorOfOtherRow; 390 | } 391 | 392 | - (void)safeReloadData { 393 | [self.centerTableView reloadData]; 394 | [self.upTableView reloadData]; 395 | [self.downTableView reloadData]; 396 | 397 | NSInteger index = [self setupSelectedRow]; 398 | NSAttributedString *attriString = [[NSAttributedString alloc]initWithString:@""]; 399 | if (self.datas.count > index) { 400 | attriString = self.datas[index]; 401 | self.textOfSelectedRow = attriString.string; 402 | } 403 | } 404 | 405 | 406 | @end 407 | -------------------------------------------------------------------------------- /PGPickerView/PGPickerTableView.h: -------------------------------------------------------------------------------- 1 | // 2 | // PGPickerTableView.h 3 | // PGPickerView 4 | // 5 | // Created by piggybear on 2017/7/26. 6 | // Copyright © 2017年 piggybear. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface PGPickerTableView : UITableView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /PGPickerView/PGPickerTableView.m: -------------------------------------------------------------------------------- 1 | // 2 | // PGPickerTableView.m 3 | // PGPickerView 4 | // 5 | // Created by piggybear on 2017/7/26. 6 | // Copyright © 2017年 piggybear. All rights reserved. 7 | // 8 | 9 | #import "PGPickerTableView.h" 10 | 11 | @implementation PGPickerTableView 12 | - (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style { 13 | if (self = [super initWithFrame:frame style:style]) { 14 | self.separatorInset = UIEdgeInsetsMake(0, 0, 0, 0); 15 | self.tableFooterView = [UIView new]; 16 | self.separatorStyle = UITableViewCellSeparatorStyleNone; 17 | self.backgroundColor = [UIColor clearColor]; 18 | self.scrollsToTop = false; 19 | } 20 | return self; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /PGPickerView/PGPickerView.h: -------------------------------------------------------------------------------- 1 | // 2 | // PGPickerView.h 3 | // PGPickerView 4 | // 5 | // Created by piggybear on 2017/7/26. 6 | // Copyright © 2017年 piggybear. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef NS_ENUM(NSUInteger, PGPickerViewLineType) { 12 | PGPickerViewLineTypeline, 13 | PGPickerViewLineTypelineSegment, 14 | PGPickerViewLineTypelineVertical, 15 | }; 16 | 17 | @protocol PGPickerViewDataSource, PGPickerViewDelegate; 18 | @interface PGPickerView : UIView 19 | @property(nonatomic, assign) PGPickerViewLineType type; 20 | @property(nonatomic,weak) id dataSource; // default is nil. weak reference 21 | @property(nonatomic,weak) id delegate; // default is nil. weak reference 22 | 23 | @property(nonatomic, strong) UIColor *lineBackgroundColor; // default is [UIColor grayColor] 24 | @property (nonatomic, assign) CGFloat lineHeight; // default is 0.5 25 | 26 | @property(nonatomic, strong) UIColor *verticalLineBackgroundColor; // default is [UIColor grayColor] type3 vertical line 27 | @property (nonatomic, assign) CGFloat verticalLineWidth; // default is 0.5 28 | 29 | @property (nonatomic, strong)UIColor *textColorOfSelectedRow; // [UIColor blackColor] 30 | @property(nonatomic, strong) UIFont *textFontOfSelectedRow; 31 | 32 | @property (nonatomic, strong)UIColor *textColorOfOtherRow; // default is [UIColor grayColor] 33 | @property(nonatomic, strong) UIFont *textFontOfOtherRow; 34 | 35 | // info that was fetched and cached from the data source and delegate 36 | @property(nonatomic,readonly) NSInteger numberOfComponents; 37 | 38 | @property (nonatomic) CGFloat rowHeight; // default is 44 39 | 40 | @property(nonatomic, assign) BOOL isHiddenMiddleText; // default is true true -> hidden 41 | @property(nonatomic, strong) UIColor *middleTextColor; 42 | @property(nonatomic, strong) UIFont *middleTextFont; 43 | 44 | @property(nonatomic, assign) BOOL isHiddenWheels; // default is true true -> hidden 45 | @property(nonatomic, assign) BOOL isCycleScroll; //default is false 46 | 47 | - (NSInteger)numberOfRowsInComponent:(NSInteger)component; 48 | 49 | // selection. in this case, it means showing the appropriate row in the middle 50 | - (void)selectRow:(NSInteger)row inComponent:(NSInteger)component animated:(BOOL)animated;// scrolls the specified row to center. 51 | 52 | - (NSInteger)selectedRowInComponent:(NSInteger)component;// returns selected row. -1 if nothing selected 53 | - (NSString *)textOfSelectedRowInComponent:(NSInteger)component; 54 | // Reloading whole view or single component 55 | - (void)reloadAllComponents; 56 | - (void)reloadComponent:(NSInteger)component; 57 | - (void)reloadComponent:(NSInteger)component refresh:(BOOL)refresh; 58 | @end 59 | 60 | @protocol PGPickerViewDataSource 61 | @required 62 | // returns the number of 'columns' to display. 63 | - (NSInteger)numberOfComponentsInPickerView:(PGPickerView *)pickerView; 64 | 65 | // returns the # of rows in each component.. 66 | - (NSInteger)pickerView:(PGPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component; 67 | @end 68 | 69 | @protocol PGPickerViewDelegate 70 | @optional 71 | // these methods return either a plain NSString, a NSAttributedString, or a view (e.g UILabel) to display the row for the component. 72 | // for the view versions, we cache any hidden and thus unused views and pass them back for reuse. 73 | // If you return back a different object, the old one will be released. the view will be centered in the row rect 74 | - (NSString *)pickerView:(PGPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component; 75 | - (NSAttributedString *)pickerView:(PGPickerView *)pickerView attributedTitleForRow:(NSInteger)row forComponent:(NSInteger)component; // attributed title is favored if both methods are implemented 76 | - (UIColor *)pickerView:(PGPickerView *)pickerView viewBackgroundColorForRow:(NSInteger)row forComponent:(NSInteger)component; 77 | 78 | - (void)pickerView:(PGPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component; 79 | - (void)pickerView:(PGPickerView *)pickerView title:(NSString *)title didSelectRow:(NSInteger)row inComponent:(NSInteger)component; 80 | 81 | - (CGFloat)rowHeightInPickerView:(PGPickerView *)pickerView forComponent:(NSInteger)component; 82 | 83 | - (NSString *)pickerView:(PGPickerView *)pickerView middleTextForcomponent:(NSInteger)component; 84 | - (CGFloat)pickerView:(PGPickerView *)pickerView middleTextSpaceForcomponent:(NSInteger)component; 85 | 86 | // type is PGPickerViewLineTypelineVertical vertical line 87 | - (UIColor *)pickerView:(PGPickerView *)pickerView verticalLineBackgroundColorForComponent:(NSInteger)component; 88 | - (CGFloat)pickerView:(PGPickerView *)pickerView verticalLineWidthForComponent:(NSInteger)component; 89 | 90 | - (UIColor *)pickerView:(PGPickerView *)pickerView upLineBackgroundColorForComponent:(NSInteger)component; 91 | - (UIColor *)pickerView:(PGPickerView *)pickerView downLineBackgroundColorForComponent:(NSInteger)component; 92 | 93 | - (CGFloat)pickerView:(PGPickerView *)pickerView upLineHeightForComponent:(NSInteger)component; 94 | - (CGFloat)pickerView:(PGPickerView *)pickerView downLineHeightForComponent:(NSInteger)component; 95 | 96 | - (UIFont *)pickerView:(PGPickerView *)pickerView textFontOfSelectedRowInComponent:(NSInteger)component; 97 | - (UIFont *)pickerView:(PGPickerView *)pickerView textFontOfOtherRowInComponent:(NSInteger)component; 98 | 99 | - (UIColor *)pickerView:(PGPickerView *)pickerView textColorOfSelectedRowInComponent:(NSInteger)component; 100 | - (UIColor *)pickerView:(PGPickerView *)pickerView textColorOfOtherRowInComponent:(NSInteger)component; 101 | 102 | - (UIFont *)pickerView:(PGPickerView *)pickerView textFontOfOtherRow:(NSInteger)row InComponent:(NSInteger)component; 103 | - (UIColor *)pickerView:(PGPickerView *)pickerView textColorOfOtherRow:(NSInteger)row InComponent:(NSInteger)component; 104 | @end 105 | -------------------------------------------------------------------------------- /PGPickerView/PGPickerView.m: -------------------------------------------------------------------------------- 1 | // 2 | // PGPickerView.m 3 | // PGPickerView 4 | // 5 | // Created by piggybear on 2017/7/26. 6 | // Copyright © 2017年 piggybear. All rights reserved. 7 | // 8 | 9 | #import "PGPickerView.h" 10 | #import "PGPickerColumnView.h" 11 | 12 | @interface PGPickerView() 13 | 14 | @property (nonatomic, strong) NSMutableArray *animationOfSelectedRowList; 15 | @property (nonatomic, strong) NSMutableArray *numberOfSelectedRowList; 16 | @property (nonatomic, strong) NSMutableArray *numberOfSelectedComponentList; 17 | 18 | @property (nonatomic, strong) NSArray *upLines; 19 | @property (nonatomic, strong) NSArray *downLines; 20 | @property (nonatomic, assign) NSUInteger numberOfRows; 21 | @property (nonatomic, strong) NSArray *columnViewList; 22 | 23 | @property (nonatomic, assign) BOOL isSubViewLayouted; 24 | @property (nonatomic, assign) BOOL isSelected; 25 | @end 26 | 27 | @implementation PGPickerView 28 | 29 | #define kWidth self.frame.size.width 30 | #define kHeight self.frame.size.height 31 | 32 | - (instancetype)initWithFrame:(CGRect)frame { 33 | if (self = [super initWithFrame:frame]) { 34 | [self setup]; 35 | } 36 | return self; 37 | } 38 | 39 | - (instancetype)initWithCoder:(NSCoder *)aDecoder { 40 | if (self = [super initWithCoder:aDecoder]) { 41 | [self setup]; 42 | } 43 | return self; 44 | } 45 | 46 | - (void)layoutSubviews { 47 | [super layoutSubviews]; 48 | if (_isSubViewLayouted) { 49 | return; 50 | } 51 | _isSubViewLayouted = true; 52 | [self setupColumnView]; 53 | [self setupView]; 54 | [self.upLines enumerateObjectsUsingBlock:^(UIView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 55 | [self bringSubviewToFront:obj]; 56 | [self bringSubviewToFront:self.downLines[idx]]; 57 | }]; 58 | 59 | if (_isSelected) { 60 | [self.numberOfSelectedRowList enumerateObjectsUsingBlock:^(NSNumber * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 61 | NSInteger component = [self.numberOfSelectedComponentList[idx] integerValue]; 62 | BOOL isAnimation = [self.animationOfSelectedRowList[idx] boolValue]; 63 | [self selectRow:[obj integerValue] inComponent:component animated:isAnimation]; 64 | }]; 65 | } 66 | } 67 | 68 | - (void)setup { 69 | self.lineBackgroundColor = [UIColor lightGrayColor]; 70 | self.textColorOfSelectedRow = [UIColor blackColor]; 71 | self.textColorOfOtherRow = [UIColor lightGrayColor]; 72 | self.isHiddenMiddleText = true; 73 | self.isHiddenWheels = true; 74 | self.lineHeight = 0.5; 75 | self.verticalLineWidth = 0.5; 76 | self.verticalLineBackgroundColor = self.lineBackgroundColor; 77 | } 78 | 79 | - (PGPickerColumnView *)createColumnViewAtComponent:(NSUInteger)component refresh:(BOOL)refresh { 80 | CGFloat width = kWidth / _numberOfComponents; 81 | NSUInteger row = [self.dataSource pickerView:self numberOfRowsInComponent:component]; 82 | NSMutableArray *datas = [NSMutableArray arrayWithCapacity:row]; 83 | NSMutableArray *colors = [NSMutableArray arrayWithCapacity:row]; 84 | for (int j = 0; j < row; j++) { 85 | BOOL tf = true; 86 | NSAttributedString *attriStr = [[NSAttributedString alloc]initWithString:@"?"]; 87 | UIColor *color = [UIColor clearColor]; 88 | if (self.delegate) { 89 | if ([self.delegate respondsToSelector:@selector(pickerView:attributedTitleForRow:forComponent:)]) { 90 | attriStr = [self.delegate pickerView:self attributedTitleForRow:j forComponent:component]; 91 | if (!attriStr) { 92 | tf = false; 93 | } 94 | }else { 95 | tf = false; 96 | } 97 | if (!tf && [self.delegate respondsToSelector:@selector(pickerView:titleForRow:forComponent:)]) { 98 | NSString *title = [self.delegate pickerView:self titleForRow:j forComponent:component]; 99 | title = title ? title : @"?"; 100 | attriStr = [[NSAttributedString alloc]initWithString:title]; 101 | } 102 | 103 | if ([self.delegate respondsToSelector:@selector(pickerView:viewBackgroundColorForRow:forComponent:)]) { 104 | UIColor *temp = [self.delegate pickerView:self viewBackgroundColorForRow:j forComponent:component]; 105 | if (temp) { 106 | color = temp; 107 | } 108 | } 109 | } 110 | [colors addObject:color]; 111 | [datas addObject:attriStr]; 112 | } 113 | PGPickerColumnView *view = [self columnViewInComponent:component]; 114 | if (!view) { 115 | CGFloat rowHeight = [self rowHeightInComponent:component]; 116 | CGFloat upLineHeight = [self upLineHeightForComponent:component]; 117 | CGFloat downLineHeight = [self downLineHeightForComponent:component]; 118 | view = [[PGPickerColumnView alloc]initWithFrame:CGRectMake(component * width, 0, width, kHeight) rowHeight: rowHeight upLineHeight:upLineHeight downLineHeight:downLineHeight isCycleScroll:self.isCycleScroll datas:datas]; 119 | view.delegate = self; 120 | [self addSubview:view]; 121 | } 122 | view.isHiddenWheels = self.isHiddenWheels; 123 | view.refresh = refresh; 124 | view.viewBackgroundColors = colors; 125 | view.textFontOfSelectedRow = [self textFontOfSelectedRowInComponent:component]; 126 | view.textFontOfOtherRow = [self textFontOfOtherRowInComponent:component]; 127 | view.component = component; 128 | view.datas = datas; 129 | view.textColorOfSelectedRow = [self textColorOfSelectedRowInComponent:component]; 130 | view.textColorOfOtherRow = [self textColorOfOtherRowInComponent:component]; 131 | return view; 132 | } 133 | 134 | - (void)setupColumnView { 135 | NSMutableArray *columnViewList = [NSMutableArray arrayWithCapacity:_numberOfComponents]; 136 | for (int i = 0; i < _numberOfComponents; i++) { 137 | PGPickerColumnView *view = [self createColumnViewAtComponent:i refresh:false]; 138 | [columnViewList addObject:view]; 139 | } 140 | self.columnViewList = columnViewList; 141 | } 142 | 143 | - (void)setupView { 144 | if (!self.isHiddenMiddleText) { 145 | [self setupMiddleTextLogic]; 146 | } 147 | switch (self.type) { 148 | case PGPickerViewLineTypeline: 149 | { 150 | [self setupLineView1]; 151 | return; 152 | } 153 | case PGPickerViewLineTypelineSegment: 154 | { 155 | [self setupLineView2]; 156 | return; 157 | } 158 | case PGPickerViewLineTypelineVertical: 159 | { 160 | [self setupLineView3]; 161 | return; 162 | } 163 | } 164 | } 165 | 166 | - (void)setupLineView1 { 167 | NSMutableArray *upLines = [NSMutableArray arrayWithCapacity:_numberOfComponents]; 168 | NSMutableArray *downLines = [NSMutableArray arrayWithCapacity:_numberOfComponents]; 169 | CGFloat lineWidth = (kWidth / _numberOfComponents); 170 | for (int i = 0; i < _numberOfComponents; i++) { 171 | CGFloat rowHeight = [self rowHeightInComponent:i]; 172 | CGFloat upLineHeight = [self upLineHeightForComponent:i]; 173 | CGFloat upLinePosY = kHeight / 2 - rowHeight / 2 - upLineHeight; 174 | UIView *upLine = [[UIView alloc]initWithFrame:CGRectMake(i * lineWidth, upLinePosY, lineWidth, upLineHeight)]; 175 | upLine.backgroundColor = self.lineBackgroundColor; 176 | [self addSubview:upLine]; 177 | [upLines addObject:upLine]; 178 | 179 | CGFloat downLineHeight = [self downLineHeightForComponent:i]; 180 | CGFloat downLinePosY = CGRectGetMaxY(upLine.frame) + rowHeight; 181 | UIView *downLine = [[UIView alloc]initWithFrame:CGRectMake(i * lineWidth, downLinePosY, lineWidth, downLineHeight)]; 182 | downLine.backgroundColor = self.lineBackgroundColor; 183 | [self addSubview:downLine]; 184 | [downLines addObject:downLine]; 185 | } 186 | self.upLines = upLines; 187 | self.downLines = downLines; 188 | } 189 | 190 | - (void)setupLineView2 { 191 | NSMutableArray *upLines = [NSMutableArray arrayWithCapacity:_numberOfComponents]; 192 | NSMutableArray *downLines = [NSMutableArray arrayWithCapacity:_numberOfComponents]; 193 | CGFloat lineWidth = (self.frame.size.width / _numberOfComponents) - 20; 194 | CGFloat space = (self.frame.size.width / _numberOfComponents); 195 | if (_numberOfComponents == 1) { 196 | CGFloat rowHeight = [self rowHeightInComponent:0]; 197 | CGFloat upLineHeight = [self upLineHeightForComponent:0]; 198 | upLineHeight = upLineHeight > 1.5 ? upLineHeight: 1.5; 199 | CGFloat upLinePosY = kHeight / 2 - rowHeight / 2 - upLineHeight; 200 | UIView *upLine = [[UIView alloc]initWithFrame:CGRectMake(self.frame.size.width / 2 - 43, upLinePosY, 90, upLineHeight)]; 201 | upLine.backgroundColor = self.lineBackgroundColor; 202 | [self addSubview:upLine]; 203 | [upLines addObject:upLine]; 204 | 205 | CGFloat downLineHeight = [self downLineHeightForComponent:0]; 206 | downLineHeight = downLineHeight > 1.5 ? downLineHeight: 1.5; 207 | CGFloat downLinePosY = CGRectGetMaxY(upLine.frame) + rowHeight; 208 | UIView *downLine = [[UIView alloc]initWithFrame:CGRectMake(self.frame.size.width / 2 - 43, downLinePosY, 90, downLineHeight)]; 209 | downLine.backgroundColor = self.lineBackgroundColor; 210 | [self addSubview:downLine]; 211 | [downLines addObject:downLine]; 212 | 213 | self.upLines = upLines; 214 | self.downLines = downLines; 215 | return; 216 | } 217 | for (int i = 0; i < _numberOfComponents; i++) { 218 | CGFloat rowHeight = [self rowHeightInComponent:i]; 219 | CGFloat upLineHeight = [self upLineHeightForComponent:i]; 220 | upLineHeight = upLineHeight > 1.5 ? upLineHeight: 1.5; 221 | CGFloat upLinePosY = kHeight / 2 - rowHeight / 2 - upLineHeight; 222 | UIView *upLine = [[UIView alloc]initWithFrame:CGRectMake(10 + space * i, upLinePosY, lineWidth, upLineHeight)]; 223 | upLine.backgroundColor = [self upLineBackgroundColorForComponent:i]; 224 | [self addSubview:upLine]; 225 | [upLines addObject:upLine]; 226 | 227 | CGFloat downLineHeight = [self downLineHeightForComponent:i]; 228 | downLineHeight = downLineHeight > 1.5 ? downLineHeight: 1.5; 229 | CGFloat downLinePosY = CGRectGetMaxY(upLine.frame) + rowHeight; 230 | UIView *downLine = [[UIView alloc]initWithFrame:CGRectMake(10 + space * i, downLinePosY, lineWidth, downLineHeight)]; 231 | downLine.backgroundColor = [self downLineBackgroundColorForComponent:i]; 232 | [self addSubview:downLine]; 233 | [downLines addObject:downLine]; 234 | } 235 | self.upLines = upLines; 236 | self.downLines = downLines; 237 | } 238 | 239 | - (void)setupLineView3 { 240 | CGFloat space = (self.frame.size.width / _numberOfComponents); 241 | [self setupLineView2]; 242 | for (int i = 0; i < _numberOfComponents; i++) { 243 | if (i != _numberOfComponents - 1) { 244 | CGFloat width = [self verticalLineWidthForComponent:i]; 245 | UIView *verticalLine = [[UIView alloc]initWithFrame:CGRectMake(space * (i+1), 0, width, kHeight)]; 246 | verticalLine.backgroundColor = [self verticalLineBackgroundColorForComponent:i]; 247 | [self addSubview:verticalLine]; 248 | } 249 | } 250 | } 251 | 252 | - (void)setupMiddleTextLogic { 253 | CGFloat lineWidth = (self.frame.size.width / _numberOfComponents); 254 | CGFloat space = 10; 255 | for (int i = 0; i < _numberOfComponents; i++) { 256 | UILabel *label = [[UILabel alloc]init]; 257 | if ([self.delegate respondsToSelector:@selector(pickerView:middleTextSpaceForcomponent:)]) { 258 | space = [self.delegate pickerView:self middleTextSpaceForcomponent:i]; 259 | } 260 | label.frame = CGRectMake(lineWidth / 2 + lineWidth * i + space, kHeight / 2 - 15, 30, 30); 261 | NSString *text = @""; 262 | if ([self.delegate respondsToSelector:@selector(pickerView:middleTextForcomponent:)]) { 263 | text = [self.delegate pickerView:self middleTextForcomponent:i]; 264 | } 265 | label.text = text; 266 | label.textColor = self.middleTextColor; 267 | label.font = self.middleTextFont; 268 | [self addSubview:label]; 269 | } 270 | } 271 | 272 | - (UIColor *)verticalLineBackgroundColorForComponent:(NSInteger)component { 273 | if (self.delegate && [self.delegate respondsToSelector:@selector(pickerView:verticalLineBackgroundColorForComponent:)]) { 274 | return [self.delegate pickerView:self verticalLineBackgroundColorForComponent:component]; 275 | } 276 | return self.verticalLineBackgroundColor; 277 | } 278 | 279 | - (CGFloat)verticalLineWidthForComponent:(NSInteger)component { 280 | if (self.delegate && [self.delegate respondsToSelector:@selector(pickerView:verticalLineWidthForComponent:)]) { 281 | return [self.delegate pickerView:self verticalLineWidthForComponent:component]; 282 | } 283 | return self.verticalLineWidth; 284 | } 285 | 286 | - (UIColor *)upLineBackgroundColorForComponent:(NSInteger)component { 287 | if (self.delegate && [self.delegate respondsToSelector:@selector(pickerView:upLineBackgroundColorForComponent:)]) { 288 | return [self.delegate pickerView:self upLineBackgroundColorForComponent:component]; 289 | } 290 | return self.lineBackgroundColor; 291 | } 292 | 293 | - (UIColor *)downLineBackgroundColorForComponent:(NSInteger)component { 294 | if (self.delegate && [self.delegate respondsToSelector:@selector(pickerView:downLineBackgroundColorForComponent:)]) { 295 | return [self.delegate pickerView:self downLineBackgroundColorForComponent:component]; 296 | } 297 | return self.lineBackgroundColor; 298 | } 299 | 300 | - (CGFloat)upLineHeightForComponent:(NSInteger)component { 301 | if (self.delegate && [self.delegate respondsToSelector:@selector(pickerView:upLineHeightForComponent:)]) { 302 | return [self.delegate pickerView:self upLineHeightForComponent:component]; 303 | } 304 | return self.lineHeight; 305 | } 306 | 307 | - (CGFloat)downLineHeightForComponent:(NSInteger)component { 308 | if (self.delegate && [self.delegate respondsToSelector:@selector(pickerView:downLineHeightForComponent:)]) { 309 | return [self.delegate pickerView:self downLineHeightForComponent:component]; 310 | } 311 | return self.lineHeight; 312 | } 313 | 314 | - (UIColor *)textColorOfSelectedRowInComponent:(NSInteger)component { 315 | if (self.delegate && [self.delegate respondsToSelector:@selector(pickerView:textColorOfSelectedRowInComponent:)]) { 316 | return [self.delegate pickerView:self textColorOfSelectedRowInComponent:component]; 317 | } 318 | return self.textColorOfSelectedRow; 319 | } 320 | 321 | - (UIColor *)textColorOfOtherRowInComponent:(NSInteger)component { 322 | if (self.delegate && [self.delegate respondsToSelector:@selector(pickerView:textColorOfOtherRowInComponent:)]) { 323 | return [self.delegate pickerView:self textColorOfOtherRowInComponent:component]; 324 | } 325 | return self.textColorOfOtherRow; 326 | } 327 | 328 | - (NSInteger)numberOfRowsInComponent:(NSInteger)component { 329 | if (self.dataSource && [self.dataSource respondsToSelector:@selector(pickerView:numberOfRowsInComponent:)]) { 330 | return [self.dataSource pickerView:self numberOfRowsInComponent:component]; 331 | } 332 | return 0; 333 | } 334 | 335 | - (NSInteger)selectedRowInComponent:(NSInteger)component { 336 | PGPickerColumnView *view = [self columnViewInComponent:component]; 337 | if (view) { 338 | return view.selectedRow; 339 | } 340 | return -1; 341 | } 342 | 343 | - (NSString *)textOfSelectedRowInComponent:(NSInteger)component { 344 | PGPickerColumnView *view = [self columnViewInComponent:component]; 345 | if (view) { 346 | return view.textOfSelectedRow; 347 | } 348 | return nil; 349 | } 350 | 351 | - (void)selectRow:(NSInteger)row inComponent:(NSInteger)component animated:(BOOL)animated { 352 | if (_isSubViewLayouted) { 353 | PGPickerColumnView *view = [self columnViewInComponent:component]; 354 | [view selectRow:row animated:animated]; 355 | return; 356 | } 357 | if (!_isSubViewLayouted) { 358 | [self.numberOfSelectedComponentList addObject:@(component)]; 359 | [self.numberOfSelectedRowList addObject:@(row)]; 360 | [self.animationOfSelectedRowList addObject:@(animated)]; 361 | } 362 | _isSelected = true; 363 | } 364 | 365 | - (CGFloat)rowHeightInComponent:(NSInteger)component { 366 | if (self.delegate && [self.delegate respondsToSelector:@selector(rowHeightInPickerView:forComponent:)]) { 367 | return [self.delegate rowHeightInPickerView:self forComponent: component]; 368 | }else if (self.rowHeight != 0) { 369 | return self.rowHeight; 370 | } 371 | self.rowHeight = 44; 372 | return self.rowHeight; 373 | } 374 | 375 | - (UIFont *)textFontOfSelectedRowInComponent:(NSInteger)component { 376 | if (self.delegate && [self.delegate respondsToSelector:@selector(pickerView:textFontOfSelectedRowInComponent:)]) { 377 | return [self.delegate pickerView:self textFontOfSelectedRowInComponent:component]; 378 | } 379 | return self.textFontOfSelectedRow; 380 | } 381 | 382 | - (UIFont *)textFontOfOtherRowInComponent:(NSInteger)component { 383 | if (self.delegate && [self.delegate respondsToSelector:@selector(pickerView:textFontOfOtherRowInComponent:)]) { 384 | return [self.delegate pickerView:self textFontOfOtherRowInComponent:component]; 385 | } 386 | return self.textFontOfOtherRow; 387 | } 388 | 389 | - (PGPickerColumnView *)columnViewInComponent:(NSUInteger)component { 390 | if (!self.columnViewList || self.columnViewList.count == 0) { 391 | return nil; 392 | } 393 | __block PGPickerColumnView *view = nil; 394 | [self.columnViewList enumerateObjectsUsingBlock:^(PGPickerColumnView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 395 | if (obj.component == component) { 396 | view = obj; 397 | *stop = true; 398 | } 399 | }]; 400 | return view; 401 | } 402 | 403 | - (void)reloadComponent:(NSInteger)component { 404 | [self createColumnViewAtComponent:component refresh:false]; 405 | } 406 | 407 | - (void)reloadComponent:(NSInteger)component refresh:(BOOL)refresh { 408 | [self createColumnViewAtComponent:component refresh:refresh]; 409 | } 410 | 411 | - (void)reloadAllComponents { 412 | [self setupColumnView]; 413 | } 414 | 415 | #pragma mark - PGPickerColumnViewDelegate 416 | - (void)pickerColumnView:(PGPickerColumnView *)pickerColumnView didSelectRow:(NSInteger)row { 417 | if (self.delegate && [self.delegate respondsToSelector:@selector(pickerView:didSelectRow:inComponent:)]) { 418 | [self.delegate pickerView:self didSelectRow:row inComponent:pickerColumnView.component]; 419 | } 420 | } 421 | 422 | - (void)pickerColumnView:(PGPickerColumnView *)pickerColumnView title:(NSString *)title didSelectRow:(NSInteger)row { 423 | if (self.delegate && [self.delegate respondsToSelector:@selector(pickerView:title:didSelectRow:inComponent:)]) { 424 | [self.delegate pickerView:self title:title didSelectRow:row inComponent:pickerColumnView.component]; 425 | } 426 | } 427 | 428 | - (UIFont *)pickerColumnView:(PGPickerColumnView *)pickerColumnView textFontOfOtherRow:(NSInteger)row InComponent:(NSInteger)component { 429 | if (self.delegate && [self.delegate respondsToSelector:@selector(pickerView:textFontOfOtherRow:InComponent:)]) { 430 | return [self.delegate pickerView:self textFontOfOtherRow:row InComponent:component]; 431 | } 432 | return self.textFontOfOtherRow; 433 | } 434 | 435 | - (UIColor *)pickerColumnView:(PGPickerColumnView *)pickerColumnView textColorOfOtherRow:(NSInteger)row InComponent:(NSInteger)component { 436 | if (self.delegate && [self.delegate respondsToSelector:@selector(pickerView:textColorOfOtherRow:InComponent:)]) { 437 | return [self.delegate pickerView:self textColorOfOtherRow:row InComponent:component]; 438 | } 439 | return self.textColorOfOtherRow; 440 | } 441 | 442 | #pragma mark - Setter 443 | - (void)setDataSource:(id)dataSource { 444 | _dataSource = dataSource; 445 | if (dataSource && [dataSource respondsToSelector:@selector(numberOfComponentsInPickerView:)]) { 446 | _numberOfComponents = [dataSource numberOfComponentsInPickerView:self]; 447 | } 448 | } 449 | 450 | - (void)setTextColorOfSelectedRow:(UIColor *)textColorOfSelectedRow { 451 | _textColorOfSelectedRow = textColorOfSelectedRow; 452 | [self.columnViewList enumerateObjectsUsingBlock:^(PGPickerColumnView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 453 | obj.textColorOfSelectedRow = textColorOfSelectedRow; 454 | }]; 455 | } 456 | 457 | - (void)setTextColorOfOtherRow:(UIColor *)textColorOfOtherRow { 458 | _textColorOfOtherRow = textColorOfOtherRow; 459 | [self.columnViewList enumerateObjectsUsingBlock:^(PGPickerColumnView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 460 | obj.textColorOfOtherRow = textColorOfOtherRow; 461 | }]; 462 | } 463 | 464 | - (void)setLineBackgroundColor:(UIColor *)lineBackgroundColor { 465 | _lineBackgroundColor = lineBackgroundColor; 466 | [self.upLines enumerateObjectsUsingBlock:^(UIView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 467 | obj.backgroundColor = lineBackgroundColor; 468 | self.downLines[idx].backgroundColor = lineBackgroundColor; 469 | }]; 470 | } 471 | 472 | #pragma mark - Getter 473 | - (NSUInteger)numberOfRows { 474 | if (!_numberOfRows) { 475 | if (self.dataSource && [self.dataSource respondsToSelector:@selector(pickerView:numberOfRowsInComponent:)]) { 476 | _numberOfRows = [self.dataSource pickerView:self numberOfRowsInComponent:_numberOfComponents]; 477 | }else { 478 | _numberOfRows = 0; 479 | } 480 | } 481 | return _numberOfRows; 482 | } 483 | 484 | - (NSMutableArray *)animationOfSelectedRowList { 485 | if (!_animationOfSelectedRowList) { 486 | _animationOfSelectedRowList = [NSMutableArray array]; 487 | } 488 | return _animationOfSelectedRowList; 489 | } 490 | 491 | - (NSMutableArray *)numberOfSelectedRowList { 492 | if (!_numberOfSelectedRowList) { 493 | _numberOfSelectedRowList = [NSMutableArray array]; 494 | } 495 | return _numberOfSelectedRowList; 496 | } 497 | 498 | - (NSMutableArray *)numberOfSelectedComponentList { 499 | if (!_numberOfSelectedComponentList) { 500 | _numberOfSelectedComponentList = [NSMutableArray array]; 501 | } 502 | return _numberOfSelectedComponentList; 503 | } 504 | 505 | @end 506 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PGPickerView 2 | PGPickerView是将UIPickerView的弯曲弧度变成直列表,可以是单列表,多列表,还可以修改选中label的字体颜色等,用法跟UIPickerView一样。 3 | ![](01F3FA58-E2F9-4BFF-9F49-F07BD32322DD.png) 4 | 5 | [![CocoaPods compatible](https://img.shields.io/cocoapods/v/PGPickerView.svg)](https://cocoapods.org/pods/PGPickerView) 6 | ![](https://img.shields.io/badge/platform-iOS-red.svg) ![](https://img.shields.io/badge/language-Objective--C-orange.svg) 7 | ![](https://img.shields.io/badge/license-MIT%20License-brightgreen.svg) 8 | [![](https://img.shields.io/badge/jianshu-piggybear-red.svg)](http://www.jianshu.com/u/3740632b2002) 9 | 10 | ![PGPickerView.gif](PGPickerView.gif) 11 | 12 | > 内置3中样式 13 | 14 | # 样式一 15 | ![样式一](Images/type1.png) 16 | 17 | 18 | # 样式二 19 | ![样式一](Images/type2.png) 20 | 21 | # 样式三 22 | ![样式一](Images/type3.png) 23 | 24 | # 显示中间字 25 | ![middle](Images/middle.png) 26 | 27 | # CocoaPods安装 28 | 29 | ``` 30 | pod 'PGPickerView', '>= 1.2.1' 31 | ``` 32 | 33 | # 使用 34 | 35 | ``` 36 | PGPickerView *pickerView = [[PGPickerView alloc]initWithFrame:self.view.bounds]; 37 | pickerView.delegate = self; 38 | pickerView.dataSource = self; 39 | [self.view addSubview:pickerView]; 40 | 41 | #pragma PGPickerViewDataSource 42 | - (NSInteger)numberOfComponentsInPickerView:(PGPickerView *)pickerView { 43 | return 2; 44 | } 45 | 46 | - (NSInteger)pickerView:(PGPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { 47 | return 10; 48 | } 49 | #pragma PGPickerViewDelegate 50 | - (nullable NSString *)pickerView:(PGPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component { 51 | return [NSString stringWithFormat:@"label%ld--%ld", component, row]; 52 | } 53 | ``` 54 | # 设置样式 55 | ``` 56 | //设置线条的颜色 57 | pickerView.lineBackgroundColor = [UIColor redColor]; 58 | //设置选中行的字体颜色 59 | pickerView.textColorOfSelectedRow = [UIColor blueColor]; 60 | //设置未选中行的字体颜色 61 | pickerView.textColorOfOtherRow = [UIColor blackColor]; 62 | 63 | ``` 64 | 65 | **更多的使用方法请下载[demo](https://github.com/xiaozhuxiong121/PGPickerView)查看** 66 | 67 | # 许可证 68 | 69 | PGPickerView 使用 MIT 许可证,详情见 [LICENSE](LICENSE) 文件。 70 | --------------------------------------------------------------------------------