├── .gitignore ├── CircularProgressBar.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── CircularProgressBar ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── CircularProgressBar.h ├── CircularProgressBar.m ├── CustomIOSAlertView.h ├── CustomIOSAlertView.m ├── Info.plist ├── MyTimePicker.h ├── MyTimePicker.m ├── TimeHelper.h ├── TimeHelper.m ├── ViewController.h ├── ViewController.m └── main.m ├── CircularProgressBarTests ├── CircularProgressBarTests.m └── Info.plist ├── CircularProgressBarUITests ├── CircularProgressBarUITests.m └── Info.plist ├── ExampleImage ├── Screen Shot 2015-10-10 at 11.10.22 AM.png ├── Screen Shot 2015-10-10 at 11.10.35 AM.png └── Screen Shot 2015-10-10 at 11.11.02 AM.png ├── Intermediates └── CircularProgressBar.build │ └── Debug-iphoneos │ └── CircularProgressBar.build │ ├── Objects-normal │ └── arm64 │ │ └── CircularProgressBar.LinkFileList │ ├── dgph │ └── dgph~ └── 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 | *.xccheckout 22 | *.moved-aside 23 | *.xcuserstate 24 | *.xcscmblueprint 25 | 26 | ## Obj-C/Swift specific 27 | *.hmap 28 | *.ipa 29 | 30 | # CocoaPods 31 | # 32 | # We recommend against adding the Pods directory to your .gitignore. However 33 | # you should judge for yourself, the pros and cons are mentioned at: 34 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 35 | # 36 | #Pods/ 37 | 38 | # Carthage 39 | # 40 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 41 | # Carthage/Checkouts 42 | 43 | Carthage/Build 44 | -------------------------------------------------------------------------------- /CircularProgressBar.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | C50106CA1BC79B84007F012C /* CustomIOSAlertView.m in Sources */ = {isa = PBXBuildFile; fileRef = C50106C91BC79B84007F012C /* CustomIOSAlertView.m */; }; 11 | C50106D01BC7B9B6007F012C /* MyTimePicker.m in Sources */ = {isa = PBXBuildFile; fileRef = C50106CF1BC7B9B6007F012C /* MyTimePicker.m */; }; 12 | C5506B561BC635B20016881E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C5506B551BC635B20016881E /* main.m */; }; 13 | C5506B591BC635B20016881E /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = C5506B581BC635B20016881E /* AppDelegate.m */; }; 14 | C5506B5C1BC635B20016881E /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C5506B5B1BC635B20016881E /* ViewController.m */; }; 15 | C5506B5F1BC635B20016881E /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C5506B5D1BC635B20016881E /* Main.storyboard */; }; 16 | C5506B611BC635B20016881E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C5506B601BC635B20016881E /* Assets.xcassets */; }; 17 | C5506B641BC635B20016881E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C5506B621BC635B20016881E /* LaunchScreen.storyboard */; }; 18 | C5506B6F1BC635B30016881E /* CircularProgressBarTests.m in Sources */ = {isa = PBXBuildFile; fileRef = C5506B6E1BC635B30016881E /* CircularProgressBarTests.m */; }; 19 | C5506B7A1BC635B30016881E /* CircularProgressBarUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = C5506B791BC635B30016881E /* CircularProgressBarUITests.m */; }; 20 | C5506BAC1BC6367D0016881E /* CircularProgressBar.m in Sources */ = {isa = PBXBuildFile; fileRef = C5506BAB1BC6367D0016881E /* CircularProgressBar.m */; }; 21 | C5506BAF1BC662E80016881E /* TimeHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = C5506BAE1BC662E80016881E /* TimeHelper.m */; }; 22 | /* End PBXBuildFile section */ 23 | 24 | /* Begin PBXContainerItemProxy section */ 25 | C5506B6B1BC635B30016881E /* PBXContainerItemProxy */ = { 26 | isa = PBXContainerItemProxy; 27 | containerPortal = C5506B491BC635B20016881E /* Project object */; 28 | proxyType = 1; 29 | remoteGlobalIDString = C5506B501BC635B20016881E; 30 | remoteInfo = CircularProgressBar; 31 | }; 32 | C5506B761BC635B30016881E /* PBXContainerItemProxy */ = { 33 | isa = PBXContainerItemProxy; 34 | containerPortal = C5506B491BC635B20016881E /* Project object */; 35 | proxyType = 1; 36 | remoteGlobalIDString = C5506B501BC635B20016881E; 37 | remoteInfo = CircularProgressBar; 38 | }; 39 | /* End PBXContainerItemProxy section */ 40 | 41 | /* Begin PBXFileReference section */ 42 | C50106C81BC79B84007F012C /* CustomIOSAlertView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CustomIOSAlertView.h; sourceTree = ""; }; 43 | C50106C91BC79B84007F012C /* CustomIOSAlertView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CustomIOSAlertView.m; sourceTree = ""; }; 44 | C50106CE1BC7B9B6007F012C /* MyTimePicker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MyTimePicker.h; sourceTree = ""; }; 45 | C50106CF1BC7B9B6007F012C /* MyTimePicker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MyTimePicker.m; sourceTree = ""; }; 46 | C5506B511BC635B20016881E /* CircularProgressBar.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CircularProgressBar.app; sourceTree = BUILT_PRODUCTS_DIR; }; 47 | C5506B551BC635B20016881E /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 48 | C5506B571BC635B20016881E /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 49 | C5506B581BC635B20016881E /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 50 | C5506B5A1BC635B20016881E /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 51 | C5506B5B1BC635B20016881E /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 52 | C5506B5E1BC635B20016881E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 53 | C5506B601BC635B20016881E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 54 | C5506B631BC635B20016881E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 55 | C5506B651BC635B20016881E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 56 | C5506B6A1BC635B30016881E /* CircularProgressBarTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CircularProgressBarTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 57 | C5506B6E1BC635B30016881E /* CircularProgressBarTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CircularProgressBarTests.m; sourceTree = ""; }; 58 | C5506B701BC635B30016881E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 59 | C5506B751BC635B30016881E /* CircularProgressBarUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CircularProgressBarUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 60 | C5506B791BC635B30016881E /* CircularProgressBarUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CircularProgressBarUITests.m; sourceTree = ""; }; 61 | C5506B7B1BC635B30016881E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 62 | C5506BAA1BC6367D0016881E /* CircularProgressBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CircularProgressBar.h; sourceTree = ""; }; 63 | C5506BAB1BC6367D0016881E /* CircularProgressBar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CircularProgressBar.m; sourceTree = ""; }; 64 | C5506BAD1BC662E80016881E /* TimeHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TimeHelper.h; sourceTree = ""; }; 65 | C5506BAE1BC662E80016881E /* TimeHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TimeHelper.m; sourceTree = ""; }; 66 | /* End PBXFileReference section */ 67 | 68 | /* Begin PBXFrameworksBuildPhase section */ 69 | C5506B4E1BC635B20016881E /* Frameworks */ = { 70 | isa = PBXFrameworksBuildPhase; 71 | buildActionMask = 2147483647; 72 | files = ( 73 | ); 74 | runOnlyForDeploymentPostprocessing = 0; 75 | }; 76 | C5506B671BC635B30016881E /* Frameworks */ = { 77 | isa = PBXFrameworksBuildPhase; 78 | buildActionMask = 2147483647; 79 | files = ( 80 | ); 81 | runOnlyForDeploymentPostprocessing = 0; 82 | }; 83 | C5506B721BC635B30016881E /* Frameworks */ = { 84 | isa = PBXFrameworksBuildPhase; 85 | buildActionMask = 2147483647; 86 | files = ( 87 | ); 88 | runOnlyForDeploymentPostprocessing = 0; 89 | }; 90 | /* End PBXFrameworksBuildPhase section */ 91 | 92 | /* Begin PBXGroup section */ 93 | C5506B481BC635B20016881E = { 94 | isa = PBXGroup; 95 | children = ( 96 | C5506B531BC635B20016881E /* CircularProgressBar */, 97 | C5506B6D1BC635B30016881E /* CircularProgressBarTests */, 98 | C5506B781BC635B30016881E /* CircularProgressBarUITests */, 99 | C5506B521BC635B20016881E /* Products */, 100 | ); 101 | sourceTree = ""; 102 | }; 103 | C5506B521BC635B20016881E /* Products */ = { 104 | isa = PBXGroup; 105 | children = ( 106 | C5506B511BC635B20016881E /* CircularProgressBar.app */, 107 | C5506B6A1BC635B30016881E /* CircularProgressBarTests.xctest */, 108 | C5506B751BC635B30016881E /* CircularProgressBarUITests.xctest */, 109 | ); 110 | name = Products; 111 | sourceTree = ""; 112 | }; 113 | C5506B531BC635B20016881E /* CircularProgressBar */ = { 114 | isa = PBXGroup; 115 | children = ( 116 | C5506B571BC635B20016881E /* AppDelegate.h */, 117 | C5506B581BC635B20016881E /* AppDelegate.m */, 118 | C5506B5A1BC635B20016881E /* ViewController.h */, 119 | C5506B5B1BC635B20016881E /* ViewController.m */, 120 | C5506BAA1BC6367D0016881E /* CircularProgressBar.h */, 121 | C5506BAB1BC6367D0016881E /* CircularProgressBar.m */, 122 | C5506BAD1BC662E80016881E /* TimeHelper.h */, 123 | C5506BAE1BC662E80016881E /* TimeHelper.m */, 124 | C5506B5D1BC635B20016881E /* Main.storyboard */, 125 | C5506B601BC635B20016881E /* Assets.xcassets */, 126 | C5506B621BC635B20016881E /* LaunchScreen.storyboard */, 127 | C5506B651BC635B20016881E /* Info.plist */, 128 | C5506B541BC635B20016881E /* Supporting Files */, 129 | C50106C81BC79B84007F012C /* CustomIOSAlertView.h */, 130 | C50106C91BC79B84007F012C /* CustomIOSAlertView.m */, 131 | C50106CE1BC7B9B6007F012C /* MyTimePicker.h */, 132 | C50106CF1BC7B9B6007F012C /* MyTimePicker.m */, 133 | ); 134 | path = CircularProgressBar; 135 | sourceTree = ""; 136 | }; 137 | C5506B541BC635B20016881E /* Supporting Files */ = { 138 | isa = PBXGroup; 139 | children = ( 140 | C5506B551BC635B20016881E /* main.m */, 141 | ); 142 | name = "Supporting Files"; 143 | sourceTree = ""; 144 | }; 145 | C5506B6D1BC635B30016881E /* CircularProgressBarTests */ = { 146 | isa = PBXGroup; 147 | children = ( 148 | C5506B6E1BC635B30016881E /* CircularProgressBarTests.m */, 149 | C5506B701BC635B30016881E /* Info.plist */, 150 | ); 151 | path = CircularProgressBarTests; 152 | sourceTree = ""; 153 | }; 154 | C5506B781BC635B30016881E /* CircularProgressBarUITests */ = { 155 | isa = PBXGroup; 156 | children = ( 157 | C5506B791BC635B30016881E /* CircularProgressBarUITests.m */, 158 | C5506B7B1BC635B30016881E /* Info.plist */, 159 | ); 160 | path = CircularProgressBarUITests; 161 | sourceTree = ""; 162 | }; 163 | /* End PBXGroup section */ 164 | 165 | /* Begin PBXNativeTarget section */ 166 | C5506B501BC635B20016881E /* CircularProgressBar */ = { 167 | isa = PBXNativeTarget; 168 | buildConfigurationList = C5506B7E1BC635B30016881E /* Build configuration list for PBXNativeTarget "CircularProgressBar" */; 169 | buildPhases = ( 170 | C5506B4D1BC635B20016881E /* Sources */, 171 | C5506B4E1BC635B20016881E /* Frameworks */, 172 | C5506B4F1BC635B20016881E /* Resources */, 173 | ); 174 | buildRules = ( 175 | ); 176 | dependencies = ( 177 | ); 178 | name = CircularProgressBar; 179 | productName = CircularProgressBar; 180 | productReference = C5506B511BC635B20016881E /* CircularProgressBar.app */; 181 | productType = "com.apple.product-type.application"; 182 | }; 183 | C5506B691BC635B30016881E /* CircularProgressBarTests */ = { 184 | isa = PBXNativeTarget; 185 | buildConfigurationList = C5506B811BC635B30016881E /* Build configuration list for PBXNativeTarget "CircularProgressBarTests" */; 186 | buildPhases = ( 187 | C5506B661BC635B30016881E /* Sources */, 188 | C5506B671BC635B30016881E /* Frameworks */, 189 | C5506B681BC635B30016881E /* Resources */, 190 | ); 191 | buildRules = ( 192 | ); 193 | dependencies = ( 194 | C5506B6C1BC635B30016881E /* PBXTargetDependency */, 195 | ); 196 | name = CircularProgressBarTests; 197 | productName = CircularProgressBarTests; 198 | productReference = C5506B6A1BC635B30016881E /* CircularProgressBarTests.xctest */; 199 | productType = "com.apple.product-type.bundle.unit-test"; 200 | }; 201 | C5506B741BC635B30016881E /* CircularProgressBarUITests */ = { 202 | isa = PBXNativeTarget; 203 | buildConfigurationList = C5506B841BC635B30016881E /* Build configuration list for PBXNativeTarget "CircularProgressBarUITests" */; 204 | buildPhases = ( 205 | C5506B711BC635B30016881E /* Sources */, 206 | C5506B721BC635B30016881E /* Frameworks */, 207 | C5506B731BC635B30016881E /* Resources */, 208 | ); 209 | buildRules = ( 210 | ); 211 | dependencies = ( 212 | C5506B771BC635B30016881E /* PBXTargetDependency */, 213 | ); 214 | name = CircularProgressBarUITests; 215 | productName = CircularProgressBarUITests; 216 | productReference = C5506B751BC635B30016881E /* CircularProgressBarUITests.xctest */; 217 | productType = "com.apple.product-type.bundle.ui-testing"; 218 | }; 219 | /* End PBXNativeTarget section */ 220 | 221 | /* Begin PBXProject section */ 222 | C5506B491BC635B20016881E /* Project object */ = { 223 | isa = PBXProject; 224 | attributes = { 225 | LastUpgradeCheck = 0700; 226 | ORGANIZATIONNAME = du; 227 | TargetAttributes = { 228 | C5506B501BC635B20016881E = { 229 | CreatedOnToolsVersion = 7.0; 230 | SystemCapabilities = { 231 | com.apple.BackgroundModes = { 232 | enabled = 1; 233 | }; 234 | }; 235 | }; 236 | C5506B691BC635B30016881E = { 237 | CreatedOnToolsVersion = 7.0; 238 | TestTargetID = C5506B501BC635B20016881E; 239 | }; 240 | C5506B741BC635B30016881E = { 241 | CreatedOnToolsVersion = 7.0; 242 | TestTargetID = C5506B501BC635B20016881E; 243 | }; 244 | }; 245 | }; 246 | buildConfigurationList = C5506B4C1BC635B20016881E /* Build configuration list for PBXProject "CircularProgressBar" */; 247 | compatibilityVersion = "Xcode 3.2"; 248 | developmentRegion = English; 249 | hasScannedForEncodings = 0; 250 | knownRegions = ( 251 | en, 252 | Base, 253 | ); 254 | mainGroup = C5506B481BC635B20016881E; 255 | productRefGroup = C5506B521BC635B20016881E /* Products */; 256 | projectDirPath = ""; 257 | projectRoot = ""; 258 | targets = ( 259 | C5506B501BC635B20016881E /* CircularProgressBar */, 260 | C5506B691BC635B30016881E /* CircularProgressBarTests */, 261 | C5506B741BC635B30016881E /* CircularProgressBarUITests */, 262 | ); 263 | }; 264 | /* End PBXProject section */ 265 | 266 | /* Begin PBXResourcesBuildPhase section */ 267 | C5506B4F1BC635B20016881E /* Resources */ = { 268 | isa = PBXResourcesBuildPhase; 269 | buildActionMask = 2147483647; 270 | files = ( 271 | C5506B641BC635B20016881E /* LaunchScreen.storyboard in Resources */, 272 | C5506B611BC635B20016881E /* Assets.xcassets in Resources */, 273 | C5506B5F1BC635B20016881E /* Main.storyboard in Resources */, 274 | ); 275 | runOnlyForDeploymentPostprocessing = 0; 276 | }; 277 | C5506B681BC635B30016881E /* Resources */ = { 278 | isa = PBXResourcesBuildPhase; 279 | buildActionMask = 2147483647; 280 | files = ( 281 | ); 282 | runOnlyForDeploymentPostprocessing = 0; 283 | }; 284 | C5506B731BC635B30016881E /* Resources */ = { 285 | isa = PBXResourcesBuildPhase; 286 | buildActionMask = 2147483647; 287 | files = ( 288 | ); 289 | runOnlyForDeploymentPostprocessing = 0; 290 | }; 291 | /* End PBXResourcesBuildPhase section */ 292 | 293 | /* Begin PBXSourcesBuildPhase section */ 294 | C5506B4D1BC635B20016881E /* Sources */ = { 295 | isa = PBXSourcesBuildPhase; 296 | buildActionMask = 2147483647; 297 | files = ( 298 | C5506B5C1BC635B20016881E /* ViewController.m in Sources */, 299 | C5506BAF1BC662E80016881E /* TimeHelper.m in Sources */, 300 | C50106CA1BC79B84007F012C /* CustomIOSAlertView.m in Sources */, 301 | C5506B591BC635B20016881E /* AppDelegate.m in Sources */, 302 | C50106D01BC7B9B6007F012C /* MyTimePicker.m in Sources */, 303 | C5506B561BC635B20016881E /* main.m in Sources */, 304 | C5506BAC1BC6367D0016881E /* CircularProgressBar.m in Sources */, 305 | ); 306 | runOnlyForDeploymentPostprocessing = 0; 307 | }; 308 | C5506B661BC635B30016881E /* Sources */ = { 309 | isa = PBXSourcesBuildPhase; 310 | buildActionMask = 2147483647; 311 | files = ( 312 | C5506B6F1BC635B30016881E /* CircularProgressBarTests.m in Sources */, 313 | ); 314 | runOnlyForDeploymentPostprocessing = 0; 315 | }; 316 | C5506B711BC635B30016881E /* Sources */ = { 317 | isa = PBXSourcesBuildPhase; 318 | buildActionMask = 2147483647; 319 | files = ( 320 | C5506B7A1BC635B30016881E /* CircularProgressBarUITests.m in Sources */, 321 | ); 322 | runOnlyForDeploymentPostprocessing = 0; 323 | }; 324 | /* End PBXSourcesBuildPhase section */ 325 | 326 | /* Begin PBXTargetDependency section */ 327 | C5506B6C1BC635B30016881E /* PBXTargetDependency */ = { 328 | isa = PBXTargetDependency; 329 | target = C5506B501BC635B20016881E /* CircularProgressBar */; 330 | targetProxy = C5506B6B1BC635B30016881E /* PBXContainerItemProxy */; 331 | }; 332 | C5506B771BC635B30016881E /* PBXTargetDependency */ = { 333 | isa = PBXTargetDependency; 334 | target = C5506B501BC635B20016881E /* CircularProgressBar */; 335 | targetProxy = C5506B761BC635B30016881E /* PBXContainerItemProxy */; 336 | }; 337 | /* End PBXTargetDependency section */ 338 | 339 | /* Begin PBXVariantGroup section */ 340 | C5506B5D1BC635B20016881E /* Main.storyboard */ = { 341 | isa = PBXVariantGroup; 342 | children = ( 343 | C5506B5E1BC635B20016881E /* Base */, 344 | ); 345 | name = Main.storyboard; 346 | sourceTree = ""; 347 | }; 348 | C5506B621BC635B20016881E /* LaunchScreen.storyboard */ = { 349 | isa = PBXVariantGroup; 350 | children = ( 351 | C5506B631BC635B20016881E /* Base */, 352 | ); 353 | name = LaunchScreen.storyboard; 354 | sourceTree = ""; 355 | }; 356 | /* End PBXVariantGroup section */ 357 | 358 | /* Begin XCBuildConfiguration section */ 359 | C5506B7C1BC635B30016881E /* Debug */ = { 360 | isa = XCBuildConfiguration; 361 | buildSettings = { 362 | ALWAYS_SEARCH_USER_PATHS = NO; 363 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 364 | CLANG_CXX_LIBRARY = "libc++"; 365 | CLANG_ENABLE_MODULES = YES; 366 | CLANG_ENABLE_OBJC_ARC = YES; 367 | CLANG_WARN_BOOL_CONVERSION = YES; 368 | CLANG_WARN_CONSTANT_CONVERSION = YES; 369 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 370 | CLANG_WARN_EMPTY_BODY = YES; 371 | CLANG_WARN_ENUM_CONVERSION = YES; 372 | CLANG_WARN_INT_CONVERSION = YES; 373 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 374 | CLANG_WARN_UNREACHABLE_CODE = YES; 375 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 376 | CODE_SIGN_IDENTITY = "iPhone Developer: hongbin gao (25ZUX9GCVP)"; 377 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer: hongbin gao (25ZUX9GCVP)"; 378 | COPY_PHASE_STRIP = NO; 379 | DEBUG_INFORMATION_FORMAT = dwarf; 380 | ENABLE_STRICT_OBJC_MSGSEND = YES; 381 | ENABLE_TESTABILITY = YES; 382 | GCC_C_LANGUAGE_STANDARD = gnu99; 383 | GCC_DYNAMIC_NO_PIC = NO; 384 | GCC_NO_COMMON_BLOCKS = YES; 385 | GCC_OPTIMIZATION_LEVEL = 0; 386 | GCC_PREPROCESSOR_DEFINITIONS = ( 387 | "DEBUG=1", 388 | "$(inherited)", 389 | ); 390 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 391 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 392 | GCC_WARN_UNDECLARED_SELECTOR = YES; 393 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 394 | GCC_WARN_UNUSED_FUNCTION = YES; 395 | GCC_WARN_UNUSED_VARIABLE = YES; 396 | IPHONEOS_DEPLOYMENT_TARGET = 8.4; 397 | MTL_ENABLE_DEBUG_INFO = YES; 398 | ONLY_ACTIVE_ARCH = YES; 399 | PROVISIONING_PROFILE = "8d8ca183-b1a4-4d8e-bded-cd9627d59d64"; 400 | SDKROOT = iphoneos; 401 | }; 402 | name = Debug; 403 | }; 404 | C5506B7D1BC635B30016881E /* Release */ = { 405 | isa = XCBuildConfiguration; 406 | buildSettings = { 407 | ALWAYS_SEARCH_USER_PATHS = NO; 408 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 409 | CLANG_CXX_LIBRARY = "libc++"; 410 | CLANG_ENABLE_MODULES = YES; 411 | CLANG_ENABLE_OBJC_ARC = YES; 412 | CLANG_WARN_BOOL_CONVERSION = YES; 413 | CLANG_WARN_CONSTANT_CONVERSION = YES; 414 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 415 | CLANG_WARN_EMPTY_BODY = YES; 416 | CLANG_WARN_ENUM_CONVERSION = YES; 417 | CLANG_WARN_INT_CONVERSION = YES; 418 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 419 | CLANG_WARN_UNREACHABLE_CODE = YES; 420 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 421 | CODE_SIGN_IDENTITY = "iPhone Distribution: Nanjing Universal Networks Co., Ltd."; 422 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution: Nanjing Universal Networks Co., Ltd."; 423 | COPY_PHASE_STRIP = NO; 424 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 425 | ENABLE_NS_ASSERTIONS = NO; 426 | ENABLE_STRICT_OBJC_MSGSEND = YES; 427 | GCC_C_LANGUAGE_STANDARD = gnu99; 428 | GCC_NO_COMMON_BLOCKS = YES; 429 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 430 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 431 | GCC_WARN_UNDECLARED_SELECTOR = YES; 432 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 433 | GCC_WARN_UNUSED_FUNCTION = YES; 434 | GCC_WARN_UNUSED_VARIABLE = YES; 435 | IPHONEOS_DEPLOYMENT_TARGET = 8.4; 436 | MTL_ENABLE_DEBUG_INFO = NO; 437 | PROVISIONING_PROFILE = "9c4b7bf6-2780-445f-b28f-938328a7e5ae"; 438 | SDKROOT = iphoneos; 439 | VALIDATE_PRODUCT = YES; 440 | }; 441 | name = Release; 442 | }; 443 | C5506B7F1BC635B30016881E /* Debug */ = { 444 | isa = XCBuildConfiguration; 445 | buildSettings = { 446 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 447 | CODE_SIGN_IDENTITY = ""; 448 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer: hongbin gao (25ZUX9GCVP)"; 449 | COPY_PHASE_STRIP = YES; 450 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 451 | ENABLE_BITCODE = NO; 452 | ENABLE_TESTABILITY = NO; 453 | INFOPLIST_FILE = CircularProgressBar/Info.plist; 454 | IPHONEOS_DEPLOYMENT_TARGET = 8.4; 455 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 456 | PRODUCT_BUNDLE_IDENTIFIER = com.magewell.CircularProgressBar; 457 | PRODUCT_NAME = "$(TARGET_NAME)"; 458 | PROVISIONING_PROFILE = "f4bfad03-96e4-4ba9-a756-75893e19289a"; 459 | TARGETED_DEVICE_FAMILY = 1; 460 | }; 461 | name = Debug; 462 | }; 463 | C5506B801BC635B30016881E /* Release */ = { 464 | isa = XCBuildConfiguration; 465 | buildSettings = { 466 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 467 | CODE_SIGN_IDENTITY = ""; 468 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution: Nanjing Universal Networks Co., Ltd."; 469 | COPY_PHASE_STRIP = YES; 470 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 471 | ENABLE_BITCODE = NO; 472 | ENABLE_TESTABILITY = NO; 473 | INFOPLIST_FILE = CircularProgressBar/Info.plist; 474 | IPHONEOS_DEPLOYMENT_TARGET = 8.4; 475 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 476 | PRODUCT_BUNDLE_IDENTIFIER = com.magewell.CircularProgressBar; 477 | PRODUCT_NAME = "$(TARGET_NAME)"; 478 | PROVISIONING_PROFILE = "0a817618-cfaa-4f52-8c92-9b57a5a53de4"; 479 | TARGETED_DEVICE_FAMILY = 1; 480 | }; 481 | name = Release; 482 | }; 483 | C5506B821BC635B30016881E /* Debug */ = { 484 | isa = XCBuildConfiguration; 485 | buildSettings = { 486 | BUNDLE_LOADER = "$(TEST_HOST)"; 487 | INFOPLIST_FILE = CircularProgressBarTests/Info.plist; 488 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 489 | PRODUCT_BUNDLE_IDENTIFIER = com.du.CircularProgressBarTests; 490 | PRODUCT_NAME = "$(TARGET_NAME)"; 491 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/CircularProgressBar.app/CircularProgressBar"; 492 | }; 493 | name = Debug; 494 | }; 495 | C5506B831BC635B30016881E /* Release */ = { 496 | isa = XCBuildConfiguration; 497 | buildSettings = { 498 | BUNDLE_LOADER = "$(TEST_HOST)"; 499 | INFOPLIST_FILE = CircularProgressBarTests/Info.plist; 500 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 501 | PRODUCT_BUNDLE_IDENTIFIER = com.du.CircularProgressBarTests; 502 | PRODUCT_NAME = "$(TARGET_NAME)"; 503 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/CircularProgressBar.app/CircularProgressBar"; 504 | }; 505 | name = Release; 506 | }; 507 | C5506B851BC635B30016881E /* Debug */ = { 508 | isa = XCBuildConfiguration; 509 | buildSettings = { 510 | INFOPLIST_FILE = CircularProgressBarUITests/Info.plist; 511 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 512 | PRODUCT_BUNDLE_IDENTIFIER = com.du.CircularProgressBarUITests; 513 | PRODUCT_NAME = "$(TARGET_NAME)"; 514 | TEST_TARGET_NAME = CircularProgressBar; 515 | USES_XCTRUNNER = YES; 516 | }; 517 | name = Debug; 518 | }; 519 | C5506B861BC635B30016881E /* Release */ = { 520 | isa = XCBuildConfiguration; 521 | buildSettings = { 522 | INFOPLIST_FILE = CircularProgressBarUITests/Info.plist; 523 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 524 | PRODUCT_BUNDLE_IDENTIFIER = com.du.CircularProgressBarUITests; 525 | PRODUCT_NAME = "$(TARGET_NAME)"; 526 | TEST_TARGET_NAME = CircularProgressBar; 527 | USES_XCTRUNNER = YES; 528 | }; 529 | name = Release; 530 | }; 531 | /* End XCBuildConfiguration section */ 532 | 533 | /* Begin XCConfigurationList section */ 534 | C5506B4C1BC635B20016881E /* Build configuration list for PBXProject "CircularProgressBar" */ = { 535 | isa = XCConfigurationList; 536 | buildConfigurations = ( 537 | C5506B7C1BC635B30016881E /* Debug */, 538 | C5506B7D1BC635B30016881E /* Release */, 539 | ); 540 | defaultConfigurationIsVisible = 0; 541 | defaultConfigurationName = Release; 542 | }; 543 | C5506B7E1BC635B30016881E /* Build configuration list for PBXNativeTarget "CircularProgressBar" */ = { 544 | isa = XCConfigurationList; 545 | buildConfigurations = ( 546 | C5506B7F1BC635B30016881E /* Debug */, 547 | C5506B801BC635B30016881E /* Release */, 548 | ); 549 | defaultConfigurationIsVisible = 0; 550 | defaultConfigurationName = Release; 551 | }; 552 | C5506B811BC635B30016881E /* Build configuration list for PBXNativeTarget "CircularProgressBarTests" */ = { 553 | isa = XCConfigurationList; 554 | buildConfigurations = ( 555 | C5506B821BC635B30016881E /* Debug */, 556 | C5506B831BC635B30016881E /* Release */, 557 | ); 558 | defaultConfigurationIsVisible = 0; 559 | defaultConfigurationName = Release; 560 | }; 561 | C5506B841BC635B30016881E /* Build configuration list for PBXNativeTarget "CircularProgressBarUITests" */ = { 562 | isa = XCConfigurationList; 563 | buildConfigurations = ( 564 | C5506B851BC635B30016881E /* Debug */, 565 | C5506B861BC635B30016881E /* Release */, 566 | ); 567 | defaultConfigurationIsVisible = 0; 568 | defaultConfigurationName = Release; 569 | }; 570 | /* End XCConfigurationList section */ 571 | }; 572 | rootObject = C5506B491BC635B20016881E /* Project object */; 573 | } 574 | -------------------------------------------------------------------------------- /CircularProgressBar.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /CircularProgressBar/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // CircularProgressBar 4 | // 5 | // Created by du on 10/8/15. 6 | // Copyright © 2015 du. 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 | -------------------------------------------------------------------------------- /CircularProgressBar/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // CircularProgressBar 4 | // 5 | // Created by du on 10/8/15. 6 | // Copyright © 2015 du. 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 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // 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. 25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // 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. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // 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. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /CircularProgressBar/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /CircularProgressBar/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /CircularProgressBar/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /CircularProgressBar/CircularProgressBar.h: -------------------------------------------------------------------------------- 1 | // 2 | // CircularProgressBar.h 3 | // CircularProgressBar 4 | // 5 | // Created by du on 10/8/15. 6 | // Copyright © 2015 du. All rights reserved. 7 | // 8 | 9 | #import 10 | @protocol CircularProgressDelegate 11 | 12 | - (void)CircularProgressEnd; 13 | 14 | @end 15 | 16 | 17 | @interface CircularProgressBar : UIView 18 | { 19 | CGFloat startAngle; 20 | CGFloat endAngle; 21 | int totalTime; 22 | 23 | UIFont *textFont; 24 | UIColor *textColor; 25 | NSMutableParagraphStyle *textStyle; 26 | 27 | NSTimer *m_timer; 28 | bool b_timerRunning; 29 | } 30 | 31 | @property(nonatomic, assign) id delegate; 32 | @property(nonatomic)CGFloat time_left; 33 | 34 | - (void)setTotalSecondTime:(CGFloat)time; 35 | - (void)setTotalMinuteTime:(CGFloat)time; 36 | 37 | - (void)startTimer; 38 | - (void)stopTimer; 39 | - (void)pauseTimer; 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /CircularProgressBar/CircularProgressBar.m: -------------------------------------------------------------------------------- 1 | // 2 | // CircularProgressBar.m 3 | // CircularProgressBar 4 | // 5 | // Created by du on 10/8/15. 6 | // Copyright © 2015 du. All rights reserved. 7 | // 8 | 9 | #define RADIUS 200 10 | #define POINT_RADIUS 8 11 | #define CIRCLE_WIDTH 4 12 | #define PROGRESS_WIDTH 4 13 | #define TEXT_SIZE 140 14 | #define TIMER_INTERVAL 0.05 15 | 16 | #import "CircularProgressBar.h" 17 | #import "TimeHelper.h" 18 | 19 | @implementation CircularProgressBar 20 | 21 | @synthesize delegate; 22 | 23 | - (id)initWithFrame:(CGRect)frame { 24 | self = [super initWithFrame:frame]; 25 | if (self) { 26 | 27 | [self initData]; 28 | [self initView]; 29 | } 30 | return self; 31 | 32 | } 33 | 34 | - (void)initData { 35 | // 圆周为 2 * pi * R, 默认起始点于正右方向为 0 度, 改为正上为起始点 36 | startAngle = -0.5 * M_PI; 37 | endAngle = startAngle; 38 | 39 | totalTime = 0; 40 | 41 | textFont = [UIFont fontWithName: @"Helvetica Neue" size: TEXT_SIZE]; 42 | textColor = [UIColor lightGrayColor]; 43 | textStyle = [[NSMutableParagraphStyle defaultParagraphStyle] mutableCopy]; 44 | textStyle.lineBreakMode = NSLineBreakByWordWrapping; 45 | textStyle.alignment = NSTextAlignmentCenter; 46 | 47 | b_timerRunning = NO; 48 | 49 | } 50 | 51 | - (void)initView { 52 | self.backgroundColor = [UIColor darkGrayColor]; 53 | 54 | } 55 | 56 | - (void)drawRect:(CGRect)rect { 57 | if (totalTime == 0) 58 | endAngle = startAngle; 59 | else 60 | endAngle = (1 - self.time_left / totalTime) * 2 * M_PI + startAngle; 61 | 62 | UIBezierPath *circle = [UIBezierPath bezierPath]; 63 | [circle addArcWithCenter:CGPointMake(rect.size.width / 2, rect.size.height / 2) 64 | radius:RADIUS 65 | startAngle:0 66 | endAngle:2 * M_PI 67 | clockwise:YES]; 68 | circle.lineWidth = CIRCLE_WIDTH; 69 | [[UIColor lightGrayColor] setStroke]; 70 | [circle stroke]; 71 | 72 | 73 | UIBezierPath *progress = [UIBezierPath bezierPath]; 74 | [progress addArcWithCenter:CGPointMake(rect.size.width / 2, rect.size.height / 2) 75 | radius:RADIUS 76 | startAngle:startAngle 77 | endAngle:endAngle 78 | clockwise:YES]; 79 | progress.lineWidth = PROGRESS_WIDTH; 80 | // [[UIColor redColor] setStroke]; 81 | [[UIColor redColor] set]; 82 | [progress stroke]; 83 | 84 | CGPoint pos = [self getCurrentPointAtAngle:endAngle inRect:rect]; 85 | [self drawPointAt:pos]; 86 | 87 | // [[UIColor blackColor] setFill]; 88 | 89 | // NSString *textContent = [NSString stringWithFormat:@"%2.2f", self.time_left]; 90 | NSString *textContent = [TimeHelper formatTimeWithSecond:self.time_left]; 91 | 92 | CGSize textSize = [textContent sizeWithAttributes:@{NSFontAttributeName:textFont}]; 93 | 94 | CGRect textRect = CGRectMake(rect.size.width / 2 - textSize.width / 2, 95 | rect.size.height / 2 - textSize.height / 2, 96 | textSize.width , textSize.height); 97 | 98 | [textContent drawInRect:textRect withAttributes:@{NSFontAttributeName:textFont, NSForegroundColorAttributeName:textColor, NSParagraphStyleAttributeName:textStyle}]; 99 | 100 | } 101 | 102 | - (CGPoint)getCurrentPointAtAngle:(CGFloat)angle inRect:(CGRect)rect { 103 | //画个图就知道怎么用角度算了 104 | CGFloat y = sin(angle) * RADIUS; 105 | CGFloat x = cos(angle) * RADIUS; 106 | 107 | CGPoint pos = CGPointMake(rect.size.width / 2, rect.size.height / 2); 108 | pos.x += x; 109 | pos.y += y; 110 | return pos; 111 | } 112 | 113 | - (void)drawPointAt:(CGPoint)point { 114 | 115 | UIBezierPath *dot = [UIBezierPath bezierPath]; 116 | [dot addArcWithCenter:CGPointMake(point.x, point.y) 117 | radius:POINT_RADIUS 118 | startAngle:0 119 | endAngle:2 * M_PI 120 | clockwise:YES]; 121 | dot.lineWidth = 1; 122 | // [[UIColor redColor] setFill]; 123 | [dot fill]; 124 | 125 | } 126 | 127 | - (void)setTotalSecondTime:(CGFloat)time { 128 | totalTime = time; 129 | self.time_left = totalTime; 130 | } 131 | 132 | - (void)setTotalMinuteTime:(CGFloat)time { 133 | totalTime = time * 60; 134 | self.time_left = totalTime; 135 | } 136 | 137 | - (void)startTimer { 138 | if (!b_timerRunning) { 139 | m_timer = [NSTimer scheduledTimerWithTimeInterval:TIMER_INTERVAL target:self selector:@selector(setProgress) userInfo:nil repeats:YES]; 140 | b_timerRunning = YES; 141 | } 142 | } 143 | 144 | - (void)pauseTimer { 145 | if (b_timerRunning) { 146 | [m_timer invalidate]; 147 | m_timer = nil; 148 | b_timerRunning = NO; 149 | } 150 | } 151 | 152 | - (void)setProgress { 153 | if (self.time_left > 0) { 154 | self.time_left -= TIMER_INTERVAL; 155 | [self setNeedsDisplay]; 156 | } else { 157 | [self pauseTimer]; 158 | 159 | if (delegate) { 160 | [delegate CircularProgressEnd]; 161 | } 162 | } 163 | } 164 | 165 | - (void)stopTimer { 166 | [self pauseTimer]; 167 | 168 | startAngle = -0.5 * M_PI; 169 | endAngle = startAngle; 170 | self.time_left = totalTime; 171 | [self setNeedsDisplay]; 172 | 173 | } 174 | @end 175 | -------------------------------------------------------------------------------- /CircularProgressBar/CustomIOSAlertView.h: -------------------------------------------------------------------------------- 1 | // 2 | // CustomIOSAlertView.h 3 | // CustomIOSAlertView 4 | // 5 | // Created by Richard on 20/09/2013. 6 | // Copyright (c) 2013-2015 Wimagguc. 7 | // 8 | // Lincesed under The MIT License (MIT) 9 | // http://opensource.org/licenses/MIT 10 | // 11 | 12 | #import 13 | 14 | @protocol CustomIOSAlertViewDelegate 15 | 16 | - (void)customIOS7dialogButtonTouchUpInside:(id)alertView clickedButtonAtIndex:(NSInteger)buttonIndex; 17 | 18 | @end 19 | 20 | @interface CustomIOSAlertView : UIView 21 | 22 | @property (nonatomic, retain) UIView *parentView; // The parent view this 'dialog' is attached to 23 | @property (nonatomic, retain) UIView *dialogView; // Dialog's container view 24 | @property (nonatomic, retain) UIView *containerView; // Container within the dialog (place your ui elements here) 25 | 26 | @property (nonatomic, assign) id delegate; 27 | @property (nonatomic, retain) NSArray *buttonTitles; 28 | @property (nonatomic, assign) BOOL useMotionEffects; 29 | 30 | @property (copy) void (^onButtonTouchUpInside)(CustomIOSAlertView *alertView, int buttonIndex) ; 31 | 32 | - (id)init; 33 | 34 | /*! 35 | DEPRECATED: Use the [CustomIOSAlertView init] method without passing a parent view. 36 | */ 37 | - (id)initWithParentView: (UIView *)_parentView __attribute__ ((deprecated)); 38 | 39 | - (void)show; 40 | - (void)close; 41 | 42 | - (IBAction)customIOS7dialogButtonTouchUpInside:(id)sender; 43 | - (void)setOnButtonTouchUpInside:(void (^)(CustomIOSAlertView *alertView, int buttonIndex))onButtonTouchUpInside; 44 | 45 | - (void)deviceOrientationDidChange: (NSNotification *)notification; 46 | - (void)dealloc; 47 | 48 | @end -------------------------------------------------------------------------------- /CircularProgressBar/CustomIOSAlertView.m: -------------------------------------------------------------------------------- 1 | // 2 | // CustomIOSAlertView.m 3 | // CustomIOSAlertView 4 | // 5 | // Created by Richard on 20/09/2013. 6 | // Copyright (c) 2013-2015 Wimagguc. 7 | // 8 | // Lincesed under The MIT License (MIT) 9 | // http://opensource.org/licenses/MIT 10 | // 11 | 12 | #import "CustomIOSAlertView.h" 13 | #import 14 | 15 | const static CGFloat kCustomIOSAlertViewDefaultButtonHeight = 50; 16 | const static CGFloat kCustomIOSAlertViewDefaultButtonSpacerHeight = 1; 17 | const static CGFloat kCustomIOSAlertViewCornerRadius = 7; 18 | const static CGFloat kCustomIOS7MotionEffectExtent = 10.0; 19 | 20 | @implementation CustomIOSAlertView 21 | 22 | CGFloat buttonHeight = 0; 23 | CGFloat buttonSpacerHeight = 0; 24 | 25 | @synthesize parentView, containerView, dialogView, onButtonTouchUpInside; 26 | @synthesize delegate; 27 | @synthesize buttonTitles; 28 | @synthesize useMotionEffects; 29 | 30 | - (id)initWithParentView: (UIView *)_parentView 31 | { 32 | self = [self init]; 33 | if (_parentView) { 34 | self.frame = _parentView.frame; 35 | self.parentView = _parentView; 36 | } 37 | return self; 38 | } 39 | 40 | - (id)init 41 | { 42 | self = [super init]; 43 | if (self) { 44 | self.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height); 45 | 46 | delegate = self; 47 | useMotionEffects = false; 48 | buttonTitles = @[@"Close"]; 49 | 50 | [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; 51 | 52 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceOrientationDidChange:) name:UIDeviceOrientationDidChangeNotification object:nil]; 53 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; 54 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; 55 | } 56 | return self; 57 | } 58 | 59 | // Create the dialog view, and animate opening the dialog 60 | - (void)show 61 | { 62 | dialogView = [self createContainerView]; 63 | 64 | dialogView.layer.shouldRasterize = YES; 65 | dialogView.layer.rasterizationScale = [[UIScreen mainScreen] scale]; 66 | 67 | self.layer.shouldRasterize = YES; 68 | self.layer.rasterizationScale = [[UIScreen mainScreen] scale]; 69 | 70 | #if (defined(__IPHONE_7_0)) 71 | if (useMotionEffects) { 72 | [self applyMotionEffects]; 73 | } 74 | #endif 75 | 76 | self.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0]; 77 | 78 | [self addSubview:dialogView]; 79 | 80 | // Can be attached to a view or to the top most window 81 | // Attached to a view: 82 | if (parentView != NULL) { 83 | [parentView addSubview:self]; 84 | 85 | // Attached to the top most window 86 | } else { 87 | 88 | // On iOS7, calculate with orientation 89 | if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1) { 90 | 91 | UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation]; 92 | switch (interfaceOrientation) { 93 | case UIInterfaceOrientationLandscapeLeft: 94 | self.transform = CGAffineTransformMakeRotation(M_PI * 270.0 / 180.0); 95 | break; 96 | 97 | case UIInterfaceOrientationLandscapeRight: 98 | self.transform = CGAffineTransformMakeRotation(M_PI * 90.0 / 180.0); 99 | break; 100 | 101 | case UIInterfaceOrientationPortraitUpsideDown: 102 | self.transform = CGAffineTransformMakeRotation(M_PI * 180.0 / 180.0); 103 | break; 104 | 105 | default: 106 | break; 107 | } 108 | 109 | [self setFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)]; 110 | 111 | // On iOS8, just place the dialog in the middle 112 | } else { 113 | 114 | CGSize screenSize = [self countScreenSize]; 115 | CGSize dialogSize = [self countDialogSize]; 116 | CGSize keyboardSize = CGSizeMake(0, 0); 117 | 118 | dialogView.frame = CGRectMake((screenSize.width - dialogSize.width) / 2, (screenSize.height - keyboardSize.height - dialogSize.height) / 2, dialogSize.width, dialogSize.height); 119 | 120 | } 121 | 122 | [[[[UIApplication sharedApplication] windows] firstObject] addSubview:self]; 123 | } 124 | 125 | dialogView.layer.opacity = 0.5f; 126 | dialogView.layer.transform = CATransform3DMakeScale(1.3f, 1.3f, 1.0); 127 | 128 | [UIView animateWithDuration:0.2f delay:0.0 options:UIViewAnimationOptionCurveEaseInOut 129 | animations:^{ 130 | self.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.4f]; 131 | dialogView.layer.opacity = 1.0f; 132 | dialogView.layer.transform = CATransform3DMakeScale(1, 1, 1); 133 | } 134 | completion:NULL 135 | ]; 136 | 137 | } 138 | 139 | // Button has been touched 140 | - (IBAction)customIOS7dialogButtonTouchUpInside:(id)sender 141 | { 142 | if (delegate != NULL) { 143 | [delegate customIOS7dialogButtonTouchUpInside:self clickedButtonAtIndex:[sender tag]]; 144 | } 145 | 146 | if (onButtonTouchUpInside != NULL) { 147 | onButtonTouchUpInside(self, (int)[sender tag]); 148 | } 149 | } 150 | 151 | // Default button behaviour 152 | - (void)customIOS7dialogButtonTouchUpInside: (CustomIOSAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex 153 | { 154 | NSLog(@"Button Clicked! %d, %d", (int)buttonIndex, (int)[alertView tag]); 155 | [self close]; 156 | } 157 | 158 | // Dialog close animation then cleaning and removing the view from the parent 159 | - (void)close 160 | { 161 | CATransform3D currentTransform = dialogView.layer.transform; 162 | 163 | if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1) { 164 | CGFloat startRotation = [[dialogView valueForKeyPath:@"layer.transform.rotation.z"] floatValue]; 165 | CATransform3D rotation = CATransform3DMakeRotation(-startRotation + M_PI * 270.0 / 180.0, 0.0f, 0.0f, 0.0f); 166 | 167 | dialogView.layer.transform = CATransform3DConcat(rotation, CATransform3DMakeScale(1, 1, 1)); 168 | } 169 | 170 | dialogView.layer.opacity = 1.0f; 171 | 172 | [UIView animateWithDuration:0.2f delay:0.0 options:UIViewAnimationOptionTransitionNone 173 | animations:^{ 174 | self.backgroundColor = [UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.0f]; 175 | dialogView.layer.transform = CATransform3DConcat(currentTransform, CATransform3DMakeScale(0.6f, 0.6f, 1.0)); 176 | dialogView.layer.opacity = 0.0f; 177 | } 178 | completion:^(BOOL finished) { 179 | for (UIView *v in [self subviews]) { 180 | [v removeFromSuperview]; 181 | } 182 | [self removeFromSuperview]; 183 | } 184 | ]; 185 | } 186 | 187 | - (void)setSubView: (UIView *)subView 188 | { 189 | containerView = subView; 190 | } 191 | 192 | // Creates the container view here: create the dialog, then add the custom content and buttons 193 | - (UIView *)createContainerView 194 | { 195 | if (containerView == NULL) { 196 | containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 150)]; 197 | } 198 | 199 | CGSize screenSize = [self countScreenSize]; 200 | CGSize dialogSize = [self countDialogSize]; 201 | 202 | // For the black background 203 | [self setFrame:CGRectMake(0, 0, screenSize.width, screenSize.height)]; 204 | 205 | // This is the dialog's container; we attach the custom content and the buttons to this one 206 | UIView *dialogContainer = [[UIView alloc] initWithFrame:CGRectMake((screenSize.width - dialogSize.width) / 2, (screenSize.height - dialogSize.height) / 2, dialogSize.width, dialogSize.height)]; 207 | 208 | // First, we style the dialog to match the iOS7 UIAlertView >>> 209 | CAGradientLayer *gradient = [CAGradientLayer layer]; 210 | gradient.frame = dialogContainer.bounds; 211 | gradient.colors = [NSArray arrayWithObjects: 212 | (id)[[UIColor colorWithRed:218.0/255.0 green:218.0/255.0 blue:218.0/255.0 alpha:1.0f] CGColor], 213 | (id)[[UIColor colorWithRed:233.0/255.0 green:233.0/255.0 blue:233.0/255.0 alpha:1.0f] CGColor], 214 | (id)[[UIColor colorWithRed:218.0/255.0 green:218.0/255.0 blue:218.0/255.0 alpha:1.0f] CGColor], 215 | nil]; 216 | 217 | CGFloat cornerRadius = kCustomIOSAlertViewCornerRadius; 218 | gradient.cornerRadius = cornerRadius; 219 | [dialogContainer.layer insertSublayer:gradient atIndex:0]; 220 | 221 | dialogContainer.layer.cornerRadius = cornerRadius; 222 | dialogContainer.layer.borderColor = [[UIColor colorWithRed:198.0/255.0 green:198.0/255.0 blue:198.0/255.0 alpha:1.0f] CGColor]; 223 | dialogContainer.layer.borderWidth = 1; 224 | dialogContainer.layer.shadowRadius = cornerRadius + 5; 225 | dialogContainer.layer.shadowOpacity = 0.1f; 226 | dialogContainer.layer.shadowOffset = CGSizeMake(0 - (cornerRadius+5)/2, 0 - (cornerRadius+5)/2); 227 | dialogContainer.layer.shadowColor = [UIColor blackColor].CGColor; 228 | dialogContainer.layer.shadowPath = [UIBezierPath bezierPathWithRoundedRect:dialogContainer.bounds cornerRadius:dialogContainer.layer.cornerRadius].CGPath; 229 | 230 | // There is a line above the button 231 | UIView *lineView = [[UIView alloc] initWithFrame:CGRectMake(0, dialogContainer.bounds.size.height - buttonHeight - buttonSpacerHeight, dialogContainer.bounds.size.width, buttonSpacerHeight)]; 232 | lineView.backgroundColor = [UIColor colorWithRed:198.0/255.0 green:198.0/255.0 blue:198.0/255.0 alpha:1.0f]; 233 | [dialogContainer addSubview:lineView]; 234 | // ^^^ 235 | 236 | // Add the custom container if there is any 237 | [dialogContainer addSubview:containerView]; 238 | 239 | // Add the buttons too 240 | [self addButtonsToView:dialogContainer]; 241 | 242 | return dialogContainer; 243 | } 244 | 245 | // Helper function: add buttons to container 246 | - (void)addButtonsToView: (UIView *)container 247 | { 248 | if (buttonTitles==NULL) { return; } 249 | 250 | CGFloat buttonWidth = container.bounds.size.width / [buttonTitles count]; 251 | 252 | for (int i=0; i<[buttonTitles count]; i++) { 253 | 254 | UIButton *closeButton = [UIButton buttonWithType:UIButtonTypeCustom]; 255 | 256 | [closeButton setFrame:CGRectMake(i * buttonWidth, container.bounds.size.height - buttonHeight, buttonWidth, buttonHeight)]; 257 | 258 | [closeButton addTarget:self action:@selector(customIOS7dialogButtonTouchUpInside:) forControlEvents:UIControlEventTouchUpInside]; 259 | [closeButton setTag:i]; 260 | 261 | [closeButton setTitle:[buttonTitles objectAtIndex:i] forState:UIControlStateNormal]; 262 | [closeButton setTitleColor:[UIColor colorWithRed:0.0f green:0.5f blue:1.0f alpha:1.0f] forState:UIControlStateNormal]; 263 | [closeButton setTitleColor:[UIColor colorWithRed:0.2f green:0.2f blue:0.2f alpha:0.5f] forState:UIControlStateHighlighted]; 264 | [closeButton.titleLabel setFont:[UIFont boldSystemFontOfSize:14.0f]]; 265 | [closeButton.layer setCornerRadius:kCustomIOSAlertViewCornerRadius]; 266 | 267 | [container addSubview:closeButton]; 268 | } 269 | } 270 | 271 | // Helper function: count and return the dialog's size 272 | - (CGSize)countDialogSize 273 | { 274 | CGFloat dialogWidth = containerView.frame.size.width; 275 | CGFloat dialogHeight = containerView.frame.size.height + buttonHeight + buttonSpacerHeight; 276 | 277 | return CGSizeMake(dialogWidth, dialogHeight); 278 | } 279 | 280 | // Helper function: count and return the screen's size 281 | - (CGSize)countScreenSize 282 | { 283 | if (buttonTitles!=NULL && [buttonTitles count] > 0) { 284 | buttonHeight = kCustomIOSAlertViewDefaultButtonHeight; 285 | buttonSpacerHeight = kCustomIOSAlertViewDefaultButtonSpacerHeight; 286 | } else { 287 | buttonHeight = 0; 288 | buttonSpacerHeight = 0; 289 | } 290 | 291 | CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width; 292 | CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height; 293 | 294 | // On iOS7, screen width and height doesn't automatically follow orientation 295 | if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1) { 296 | UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation]; 297 | if (UIInterfaceOrientationIsLandscape(interfaceOrientation)) { 298 | CGFloat tmp = screenWidth; 299 | screenWidth = screenHeight; 300 | screenHeight = tmp; 301 | } 302 | } 303 | 304 | return CGSizeMake(screenWidth, screenHeight); 305 | } 306 | 307 | #if (defined(__IPHONE_7_0)) 308 | // Add motion effects 309 | - (void)applyMotionEffects { 310 | 311 | if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1) { 312 | return; 313 | } 314 | 315 | UIInterpolatingMotionEffect *horizontalEffect = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.x" 316 | type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis]; 317 | horizontalEffect.minimumRelativeValue = @(-kCustomIOS7MotionEffectExtent); 318 | horizontalEffect.maximumRelativeValue = @( kCustomIOS7MotionEffectExtent); 319 | 320 | UIInterpolatingMotionEffect *verticalEffect = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.y" 321 | type:UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis]; 322 | verticalEffect.minimumRelativeValue = @(-kCustomIOS7MotionEffectExtent); 323 | verticalEffect.maximumRelativeValue = @( kCustomIOS7MotionEffectExtent); 324 | 325 | UIMotionEffectGroup *motionEffectGroup = [[UIMotionEffectGroup alloc] init]; 326 | motionEffectGroup.motionEffects = @[horizontalEffect, verticalEffect]; 327 | 328 | [dialogView addMotionEffect:motionEffectGroup]; 329 | } 330 | #endif 331 | 332 | - (void)dealloc 333 | { 334 | [[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications]; 335 | 336 | [[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil]; 337 | [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil]; 338 | [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil]; 339 | } 340 | 341 | // Rotation changed, on iOS7 342 | - (void)changeOrientationForIOS7 { 343 | 344 | UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation]; 345 | 346 | CGFloat startRotation = [[self valueForKeyPath:@"layer.transform.rotation.z"] floatValue]; 347 | CGAffineTransform rotation; 348 | 349 | switch (interfaceOrientation) { 350 | case UIInterfaceOrientationLandscapeLeft: 351 | rotation = CGAffineTransformMakeRotation(-startRotation + M_PI * 270.0 / 180.0); 352 | break; 353 | 354 | case UIInterfaceOrientationLandscapeRight: 355 | rotation = CGAffineTransformMakeRotation(-startRotation + M_PI * 90.0 / 180.0); 356 | break; 357 | 358 | case UIInterfaceOrientationPortraitUpsideDown: 359 | rotation = CGAffineTransformMakeRotation(-startRotation + M_PI * 180.0 / 180.0); 360 | break; 361 | 362 | default: 363 | rotation = CGAffineTransformMakeRotation(-startRotation + 0.0); 364 | break; 365 | } 366 | 367 | [UIView animateWithDuration:0.2f delay:0.0 options:UIViewAnimationOptionTransitionNone 368 | animations:^{ 369 | dialogView.transform = rotation; 370 | 371 | } 372 | completion:nil 373 | ]; 374 | 375 | } 376 | 377 | // Rotation changed, on iOS8 378 | - (void)changeOrientationForIOS8: (NSNotification *)notification { 379 | 380 | CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width; 381 | CGFloat screenHeight = [UIScreen mainScreen].bounds.size.height; 382 | 383 | [UIView animateWithDuration:0.2f delay:0.0 options:UIViewAnimationOptionTransitionNone 384 | animations:^{ 385 | CGSize dialogSize = [self countDialogSize]; 386 | CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; 387 | self.frame = CGRectMake(0, 0, screenWidth, screenHeight); 388 | dialogView.frame = CGRectMake((screenWidth - dialogSize.width) / 2, (screenHeight - keyboardSize.height - dialogSize.height) / 2, dialogSize.width, dialogSize.height); 389 | } 390 | completion:nil 391 | ]; 392 | 393 | 394 | } 395 | 396 | // Handle device orientation changes 397 | - (void)deviceOrientationDidChange: (NSNotification *)notification 398 | { 399 | // If dialog is attached to the parent view, it probably wants to handle the orientation change itself 400 | if (parentView != NULL) { 401 | return; 402 | } 403 | 404 | if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1) { 405 | [self changeOrientationForIOS7]; 406 | } else { 407 | [self changeOrientationForIOS8:notification]; 408 | } 409 | } 410 | 411 | // Handle keyboard show/hide changes 412 | - (void)keyboardWillShow: (NSNotification *)notification 413 | { 414 | CGSize screenSize = [self countScreenSize]; 415 | CGSize dialogSize = [self countDialogSize]; 416 | CGSize keyboardSize = [[[notification userInfo] objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; 417 | 418 | UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation]; 419 | if (UIInterfaceOrientationIsLandscape(interfaceOrientation) && NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1) { 420 | CGFloat tmp = keyboardSize.height; 421 | keyboardSize.height = keyboardSize.width; 422 | keyboardSize.width = tmp; 423 | } 424 | 425 | [UIView animateWithDuration:0.2f delay:0.0 options:UIViewAnimationOptionTransitionNone 426 | animations:^{ 427 | dialogView.frame = CGRectMake((screenSize.width - dialogSize.width) / 2, (screenSize.height - keyboardSize.height - dialogSize.height) / 2, dialogSize.width, dialogSize.height); 428 | } 429 | completion:nil 430 | ]; 431 | } 432 | 433 | - (void)keyboardWillHide: (NSNotification *)notification 434 | { 435 | CGSize screenSize = [self countScreenSize]; 436 | CGSize dialogSize = [self countDialogSize]; 437 | 438 | [UIView animateWithDuration:0.2f delay:0.0 options:UIViewAnimationOptionTransitionNone 439 | animations:^{ 440 | dialogView.frame = CGRectMake((screenSize.width - dialogSize.width) / 2, (screenSize.height - dialogSize.height) / 2, dialogSize.width, dialogSize.height); 441 | } 442 | completion:nil 443 | ]; 444 | } 445 | 446 | @end -------------------------------------------------------------------------------- /CircularProgressBar/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 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 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | LSHasLocalizedDisplayName 22 | 23 | LSRequiresIPhoneOS 24 | 25 | UIBackgroundModes 26 | 27 | audio 28 | voip 29 | 30 | UIFileSharingEnabled 31 | 32 | UILaunchStoryboardName 33 | LaunchScreen 34 | UIMainStoryboardFile 35 | Main 36 | UIRequiredDeviceCapabilities 37 | 38 | armv7 39 | 40 | UISupportedInterfaceOrientations 41 | 42 | UIInterfaceOrientationPortrait 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /CircularProgressBar/MyTimePicker.h: -------------------------------------------------------------------------------- 1 | // 2 | // MyTimePicker.h 3 | // CircularProgressBar 4 | // 5 | // Created by mythware on 10/9/15. 6 | // Copyright © 2015 du. All rights reserved. 7 | // 8 | 9 | #import 10 | @protocol MyTimePickerDelegate 11 | 12 | - (void)timeSelected:(int)minute; 13 | 14 | @end 15 | 16 | 17 | @interface MyTimePicker : UIView 18 | { 19 | UIPickerView *m_pickerView; 20 | NSMutableArray *m_arrayData; 21 | 22 | UILabel *m_label; 23 | 24 | int m_selectedNum; 25 | } 26 | 27 | @property(nonatomic, assign) id delegate; 28 | 29 | @end 30 | 31 | -------------------------------------------------------------------------------- /CircularProgressBar/MyTimePicker.m: -------------------------------------------------------------------------------- 1 | // 2 | // MyTimePicker.m 3 | // CircularProgressBar 4 | // 5 | // Created by mythware on 10/9/15. 6 | // Copyright © 2015 du. All rights reserved. 7 | // 8 | 9 | #define MAX_ROWS 10000 10 | 11 | #import "MyTimePicker.h" 12 | 13 | @implementation MyTimePicker 14 | 15 | @synthesize delegate; 16 | 17 | - (id)initWithFrame:(CGRect)frame { 18 | self = [super initWithFrame:frame]; 19 | if (self) { 20 | [self initData]; 21 | [self initView]; 22 | } 23 | return self; 24 | } 25 | 26 | - (void)initData { 27 | m_selectedNum = 0; 28 | 29 | m_arrayData = [NSMutableArray array]; 30 | for (int time = 0; time < 100; time++) { 31 | [m_arrayData addObject:[NSString stringWithFormat:@"%d", time]]; 32 | } 33 | 34 | 35 | m_pickerView = [[UIPickerView alloc] initWithFrame:CGRectMake((self.frame.size.width - 320) / 2.0, 36 | (self.frame.size.height - 216) / 2.0, 37 | 320.0, 216.0)]; 38 | m_pickerView.delegate = self; 39 | m_pickerView.dataSource = self; 40 | m_pickerView.showsSelectionIndicator = YES; 41 | 42 | NSInteger selectedRow = 0; 43 | [m_pickerView selectRow:(((NSInteger)((MAX_ROWS / 2) / [m_arrayData count])) * [m_arrayData count]) + (selectedRow % [m_arrayData count]) inComponent:0 animated:NO]; //计算就是取MAX_ROWS的中间位置 并取整 如果默认不是起始的0 则加上偏移位置 44 | 45 | 46 | m_label = [[UILabel alloc] initWithFrame:CGRectMake(self.frame.size.width / 2.0 + 20, 47 | self.frame.size.height/ 2.0 - 20, 48 | 60, 40)]; 49 | m_label.text = @"分钟"; 50 | m_label.font = [UIFont fontWithName:@"Helvetica-Bold" size:16]; 51 | 52 | [self addSubview:m_pickerView]; 53 | [self addSubview:m_label]; 54 | } 55 | 56 | - (void)initView { 57 | self.backgroundColor = [UIColor colorWithRed:0xec / 255.0f 58 | green:0xeb / 255.0f 59 | blue:0xf1 / 255.0f 60 | alpha:1.0f]; 61 | 62 | 63 | } 64 | 65 | - (void)drawRect:(CGRect)rect { 66 | UIBezierPath *circle = [UIBezierPath bezierPath]; 67 | [circle addArcWithCenter:CGPointMake(rect.size.width / 2, rect.size.height / 2) 68 | radius:200 69 | startAngle:0 70 | endAngle:2 * M_PI 71 | clockwise:YES]; 72 | circle.lineWidth = 10; 73 | [[UIColor whiteColor] setStroke]; 74 | [circle stroke]; 75 | 76 | } 77 | 78 | #pragma mark - picker delegate 79 | -(NSArray *)pickerViewAnimalAtIndexes:(NSIndexSet *)indexes 80 | { 81 | return nil; 82 | } 83 | 84 | //返回滚轮中row的样式 85 | -(NSAttributedString *)pickerView:(UIPickerView *)pickerView attributedTitleForRow:(NSInteger)row forComponent:(NSInteger)component 86 | { 87 | return nil; 88 | } 89 | 90 | //返回滚轮的row的高度 91 | -(CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component 92 | { 93 | return 30; 94 | } 95 | 96 | #pragma mark - picker dataSource 97 | //返回滚轮的数量 98 | -(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView 99 | { 100 | //原来为了显示 “分钟” 使用2列滑轮的方法,在第二列显示 “分钟”, 101 | //但其有拖动效果,和系统的不一样。 102 | //所以为了解决这个问题,采用放一个label的方法固定显示,label的坐标需要调整好 103 | // return 2; 104 | return 1; 105 | } 106 | 107 | 108 | //当row被选中的时候 109 | -(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component 110 | { 111 | // NSLog(@"第%d个row被选中", row % [m_arrayData count]); 112 | if (delegate) { 113 | [delegate timeSelected:(int)row % [m_arrayData count]]; 114 | } 115 | } 116 | 117 | //返回滚轮的row数量 118 | -(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component 119 | { 120 | if (component == 0) { 121 | // return [m_arrayData count]; 122 | return MAX_ROWS; 123 | } else { 124 | return 1; 125 | } 126 | } 127 | 128 | 129 | 130 | //返回row显示的标题 131 | -(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component 132 | { 133 | // return [m_arrayData objectAtIndex:row]; 134 | if (component == 0) { 135 | return [m_arrayData objectAtIndex:(row % [m_arrayData count])]; 136 | } 137 | else { 138 | return @"分钟"; 139 | } 140 | } 141 | 142 | /* 143 | 注意,该方法只有当需要使用,需要自定义row的视图的时候,才能重写,并且返回一个具体的视图,如果返回一个nil,那么将会导致不现实row的内容,因为row的视图为nil 144 | //自定义row的view 145 | -(UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view 146 | { 147 | return nil; 148 | } 149 | 150 | */ 151 | 152 | //返回滚轮的宽度 153 | -(CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component 154 | { 155 | return 60; 156 | } 157 | 158 | @end 159 | 160 | -------------------------------------------------------------------------------- /CircularProgressBar/TimeHelper.h: -------------------------------------------------------------------------------- 1 | // 2 | // TimeHelper.h 3 | // CircularProgressBar 4 | // 5 | // Created by du on 10/8/15. 6 | // Copyright © 2015 du. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface TimeHelper : NSObject 13 | 14 | + (NSString *)formatTimeWithSecond:(CGFloat)left_time; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /CircularProgressBar/TimeHelper.m: -------------------------------------------------------------------------------- 1 | // 2 | // TimeHelper.m 3 | // CircularProgressBar 4 | // 5 | // Created by du on 10/8/15. 6 | // Copyright © 2015 du. All rights reserved. 7 | // 8 | 9 | #import "TimeHelper.h" 10 | 11 | @implementation TimeHelper 12 | 13 | + (NSString *)formatTimeWithSecond:(CGFloat)left_time { 14 | // left_time % 60 15 | 16 | NSString *str_sec; 17 | int sec = (int)ceil(left_time) % 60; //ceil 向上取整 18 | if (sec < 10) { 19 | str_sec = [@"0" stringByAppendingString:[NSString stringWithFormat:@"%d", sec]]; 20 | } else { 21 | str_sec = [NSString stringWithFormat:@"%d", sec]; 22 | } 23 | 24 | NSString *str_min; 25 | int min = (int)ceil(left_time) / 60; 26 | if (min < 10) { 27 | str_min = [@"0" stringByAppendingString:[NSString stringWithFormat:@"%d", min]]; 28 | } else { 29 | str_min = [NSString stringWithFormat:@"%d", min]; 30 | } 31 | 32 | NSString *str = [str_min stringByAppendingString:@":"]; 33 | str = [str stringByAppendingString:str_sec]; 34 | return str; 35 | } 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /CircularProgressBar/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // CircularProgressBar 4 | // 5 | // Created by du on 10/8/15. 6 | // Copyright © 2015 du. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "CircularProgressBar.h" 11 | #import "CustomIOSAlertView.h" 12 | #import "MyTimePicker.h" 13 | 14 | @interface ViewController : UIViewController 15 | { 16 | CircularProgressBar *m_circularProgressBar; 17 | NSTimer *m_timer; 18 | int m_timeSelected; 19 | } 20 | 21 | @end 22 | 23 | -------------------------------------------------------------------------------- /CircularProgressBar/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // CircularProgressBar 4 | // 5 | // Created by du on 10/8/15. 6 | // Copyright © 2015 du. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | 11 | @interface ViewController () 12 | 13 | @end 14 | 15 | @implementation ViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | // Do any additional setup after loading the view, typically from a nib. 20 | 21 | m_timeSelected = 0; 22 | 23 | m_circularProgressBar = [[CircularProgressBar alloc] initWithFrame:self.view.bounds]; 24 | m_circularProgressBar.delegate = self; 25 | [m_circularProgressBar setTotalSecondTime:0]; 26 | [self.view addSubview:m_circularProgressBar]; 27 | 28 | //单击开始 29 | UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapDetected)]; 30 | singleTap.numberOfTapsRequired = 1; 31 | [m_circularProgressBar setUserInteractionEnabled:YES]; 32 | [m_circularProgressBar addGestureRecognizer:singleTap]; 33 | //双击暂停 34 | UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTapDetected)]; 35 | doubleTap.numberOfTapsRequired = 2; 36 | [m_circularProgressBar addGestureRecognizer:doubleTap]; 37 | } 38 | 39 | - (void)viewDidAppear:(BOOL)animated { 40 | 41 | } 42 | 43 | - (void)didReceiveMemoryWarning { 44 | [super didReceiveMemoryWarning]; 45 | // Dispose of any resources that can be recreated. 46 | } 47 | 48 | 49 | 50 | 51 | - (void)singleTapDetected{ 52 | CustomIOSAlertView *alertView = [[CustomIOSAlertView alloc] init]; 53 | MyTimePicker *timePicker = [[MyTimePicker alloc] initWithFrame:CGRectMake(0, 0, 500, 500)]; 54 | [timePicker setDelegate:self]; 55 | 56 | [alertView setContainerView:timePicker]; 57 | [alertView setDelegate:self]; 58 | [alertView setButtonTitles:[NSMutableArray arrayWithObjects:@"Done", @"Cancel", nil]]; 59 | [alertView show]; 60 | 61 | } 62 | 63 | - (void)doubleTapDetected { 64 | [m_circularProgressBar pauseTimer]; 65 | } 66 | 67 | #pragma mark - progress bar delegate 68 | - (void)CircularProgressEnd { 69 | [m_circularProgressBar stopTimer]; 70 | m_timeSelected = 0; 71 | } 72 | 73 | #pragma mark - picker delegate 74 | - (void)timeSelected:(int)minute { 75 | m_timeSelected = minute; 76 | } 77 | 78 | #pragma mark - popup delegate 79 | - (void)customIOS7dialogButtonTouchUpInside: (CustomIOSAlertView *)alertView clickedButtonAtIndex: (NSInteger)buttonIndex 80 | { 81 | if (buttonIndex == 0) { 82 | [m_circularProgressBar setTotalMinuteTime:m_timeSelected]; 83 | [m_circularProgressBar startTimer]; 84 | } 85 | [alertView close]; 86 | } 87 | 88 | @end 89 | -------------------------------------------------------------------------------- /CircularProgressBar/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // CircularProgressBar 4 | // 5 | // Created by du on 10/8/15. 6 | // Copyright © 2015 du. 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 | -------------------------------------------------------------------------------- /CircularProgressBarTests/CircularProgressBarTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // CircularProgressBarTests.m 3 | // CircularProgressBarTests 4 | // 5 | // Created by du on 10/8/15. 6 | // Copyright © 2015 du. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface CircularProgressBarTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation CircularProgressBarTests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | // Put setup code here. This method is called before the invocation of each test method in the class. 20 | } 21 | 22 | - (void)tearDown { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample { 28 | // This is an example of a functional test case. 29 | // Use XCTAssert and related functions to verify your tests produce the correct results. 30 | } 31 | 32 | - (void)testPerformanceExample { 33 | // This is an example of a performance test case. 34 | [self measureBlock:^{ 35 | // Put the code you want to measure the time of here. 36 | }]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /CircularProgressBarTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /CircularProgressBarUITests/CircularProgressBarUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // CircularProgressBarUITests.m 3 | // CircularProgressBarUITests 4 | // 5 | // Created by du on 10/8/15. 6 | // Copyright © 2015 du. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface CircularProgressBarUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation CircularProgressBarUITests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | 22 | // In UI tests it is usually best to stop immediately when a failure occurs. 23 | self.continueAfterFailure = NO; 24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 25 | [[[XCUIApplication alloc] init] launch]; 26 | } 27 | 28 | - (void)tearDown { 29 | // Put teardown code here. This method is called after the invocation of each test method in the class. 30 | [super tearDown]; 31 | } 32 | 33 | - (void)testExample { 34 | // Use recording to get started writing UI tests. 35 | // Use XCTAssert and related functions to verify your tests produce the correct results. 36 | } 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /CircularProgressBarUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /ExampleImage/Screen Shot 2015-10-10 at 11.10.22 AM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wossoneri/CircularProgressBar/60ec4f9a1eb61dd78cd3cc5f77f33ea0e6d15d8a/ExampleImage/Screen Shot 2015-10-10 at 11.10.22 AM.png -------------------------------------------------------------------------------- /ExampleImage/Screen Shot 2015-10-10 at 11.10.35 AM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wossoneri/CircularProgressBar/60ec4f9a1eb61dd78cd3cc5f77f33ea0e6d15d8a/ExampleImage/Screen Shot 2015-10-10 at 11.10.35 AM.png -------------------------------------------------------------------------------- /ExampleImage/Screen Shot 2015-10-10 at 11.11.02 AM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wossoneri/CircularProgressBar/60ec4f9a1eb61dd78cd3cc5f77f33ea0e6d15d8a/ExampleImage/Screen Shot 2015-10-10 at 11.11.02 AM.png -------------------------------------------------------------------------------- /Intermediates/CircularProgressBar.build/Debug-iphoneos/CircularProgressBar.build/Objects-normal/arm64/CircularProgressBar.LinkFileList: -------------------------------------------------------------------------------- 1 | /Volumes/TrueCrypt/Github/CircularProgressBar/Intermediates/CircularProgressBar.build/Debug-iphoneos/CircularProgressBar.build/Objects-normal/arm64/ViewController.o 2 | /Volumes/TrueCrypt/Github/CircularProgressBar/Intermediates/CircularProgressBar.build/Debug-iphoneos/CircularProgressBar.build/Objects-normal/arm64/TimeHelper.o 3 | /Volumes/TrueCrypt/Github/CircularProgressBar/Intermediates/CircularProgressBar.build/Debug-iphoneos/CircularProgressBar.build/Objects-normal/arm64/CustomIOSAlertView.o 4 | /Volumes/TrueCrypt/Github/CircularProgressBar/Intermediates/CircularProgressBar.build/Debug-iphoneos/CircularProgressBar.build/Objects-normal/arm64/AppDelegate.o 5 | /Volumes/TrueCrypt/Github/CircularProgressBar/Intermediates/CircularProgressBar.build/Debug-iphoneos/CircularProgressBar.build/Objects-normal/arm64/MyTimePicker.o 6 | /Volumes/TrueCrypt/Github/CircularProgressBar/Intermediates/CircularProgressBar.build/Debug-iphoneos/CircularProgressBar.build/Objects-normal/arm64/main.o 7 | /Volumes/TrueCrypt/Github/CircularProgressBar/Intermediates/CircularProgressBar.build/Debug-iphoneos/CircularProgressBar.build/Objects-normal/arm64/CircularProgressBar.o 8 | -------------------------------------------------------------------------------- /Intermediates/CircularProgressBar.build/Debug-iphoneos/CircularProgressBar.build/dgph: -------------------------------------------------------------------------------- 1 | DGPH1.04 Oct 5 201513:59:07h/Volumes TrueCryptGithubCircularProgressBarRunImage IntermediatestmpCircularProgressBar.dstvar 2 | folders _g yb3jdg6d4rj4z9pxt_8xr61m0000gn Ccom.apple.DeveloperTools 7.1-7B91bXcodeDebug-iphoneosCircularProgressBar.buildDebug-iphoneosPrecompiledHeaders Applications Xcode.appContents Developer PlatformsiPhoneOS.platform DeveloperSDKsiPhoneOS9.1.sdkCircularProgressBar 3 | Info.plistCircularProgressBar.build!DerivedSourcesCircularProgressBar.app# 4 | Info.plist#PkgInfo#CircularProgressBarOnDemandResourcesViewController.m!Objects-normal)arm64*ViewController.oSDKSettings.plistSystem-Library. CoreServices/SystemVersion.plist 5 | Toolchains1XcodeDefault.xctoolchain2usr3lib4clang57.0.06include7module.modulemap*ViewController.ast TimeHelper.m* TimeHelper.o*TimeHelper.astCustomIOSAlertView.m*CustomIOSAlertView.o*CustomIOSAlertView.ast AppDelegate.m* AppDelegate.o*AppDelegate.astMyTimePicker.m*MyTimePicker.o*MyTimePicker.astmain.m*main.o*main.astCircularProgressBar.m*CircularProgressBar.o*CircularProgressBar.ast* CircularProgressBar.LinkFileListCircularProgressBar.app.dSYMAssets.xcassets!!assetcatalog_generated_info.plist! 6 | Base.lproj# 7 | Base.lproj 8 | Base.lprojRLaunchScreen.storyboardPLaunchScreen.storyboardc! LaunchScreen-SBPartialInfo.plistRMain.storyboardPMain.storyboardc!Main-SBPartialInfo.plistQLaunchScreen.storyboardcQMain.storyboardcUsers[mythware\Library] MobileDevice^Provisioning Profiles_4f4bfad03-96e4-4ba9-a756-75893e19289a.mobileprovision#embedded.mobileprovisionhEntitlements.plist!CircularProgressBar.app.xcent!'com.apple.build-tools.platform.validate#Headers#PrivateHeaders#PlugIns -------------------------------------------------------------------------------- /Intermediates/CircularProgressBar.build/Debug-iphoneos/CircularProgressBar.build/dgph~: -------------------------------------------------------------------------------- 1 | DGPH1.04 Oct 5 201513:59:07h/Volumes TrueCryptGithubCircularProgressBarRunImage IntermediatestmpCircularProgressBar.dstvar 2 | folders _g yb3jdg6d4rj4z9pxt_8xr61m0000gn Ccom.apple.DeveloperTools 7.1-7B91bXcodeDebug-iphoneosCircularProgressBar.buildDebug-iphoneosPrecompiledHeaders Applications Xcode.appContents Developer PlatformsiPhoneOS.platform DeveloperSDKsiPhoneOS9.1.sdkCircularProgressBar 3 | Info.plistCircularProgressBar.build!DerivedSourcesCircularProgressBar.app# 4 | Info.plist#PkgInfo#CircularProgressBarOnDemandResourcesViewController.m!Objects-normal)arm64*ViewController.oSDKSettings.plistSystem-Library. CoreServices/SystemVersion.plist 5 | Toolchains1XcodeDefault.xctoolchain2usr3lib4clang57.0.06include7module.modulemap*ViewController.ast TimeHelper.m* TimeHelper.o*TimeHelper.astCustomIOSAlertView.m*CustomIOSAlertView.o*CustomIOSAlertView.ast AppDelegate.m* AppDelegate.o*AppDelegate.astMyTimePicker.m*MyTimePicker.o*MyTimePicker.astmain.m*main.o*main.astCircularProgressBar.m*CircularProgressBar.o*CircularProgressBar.ast* CircularProgressBar.LinkFileListCircularProgressBar.app.dSYMAssets.xcassets!!assetcatalog_generated_info.plist! 6 | Base.lproj# 7 | Base.lproj 8 | Base.lprojRLaunchScreen.storyboardPLaunchScreen.storyboardc! LaunchScreen-SBPartialInfo.plistRMain.storyboardPMain.storyboardc!Main-SBPartialInfo.plistQLaunchScreen.storyboardcQMain.storyboardcUsers[mythware\Library] MobileDevice^Provisioning Profiles_4f4bfad03-96e4-4ba9-a756-75893e19289a.mobileprovision#embedded.mobileprovisionhEntitlements.plist!CircularProgressBar.app.xcent!'com.apple.build-tools.platform.validate#Headers#PrivateHeaders#PlugIns -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CircularProgressBar 2 | My test crcular progress bar 3 | 4 | 圆形进度条和计时器 5 | 6 | System timer: 7 | ![](https://github.com/wossoneri/CircularProgressBar/blob/master/ExampleImage/Screen%20Shot%202015-10-10%20at%2011.11.02%20AM.png?raw=true) 8 | 9 | and my timer: 10 | ![](https://github.com/wossoneri/CircularProgressBar/blob/master/ExampleImage/Screen%20Shot%202015-10-10%20at%2011.10.22%20AM.png?raw=true) 11 | chose time: 12 | ![](https://github.com/wossoneri/CircularProgressBar/blob/master/ExampleImage/Screen%20Shot%202015-10-10%20at%2011.10.35%20AM.png?raw=true) 13 | 14 | 单击选择时间,确定则开始倒计时。 15 | UIPickerView 支持内容循环显示,单位“分钟”固定显示 --------------------------------------------------------------------------------