├── .DS_Store ├── .gitattributes ├── CircularProgressView.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ └── mahdimac.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── mahdimac.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ └── xcschememanagement.plist ├── CircularProgressView ├── AppIconView.swift ├── Assets.xcassets │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ ├── 1024.png │ │ ├── 120-1.png │ │ ├── 120.png │ │ ├── 152.png │ │ ├── 167.png │ │ ├── 180.png │ │ ├── 20.png │ │ ├── 29.png │ │ ├── 40-1.png │ │ ├── 40-2.png │ │ ├── 40.png │ │ ├── 58-1.png │ │ ├── 58.png │ │ ├── 60.png │ │ ├── 76.png │ │ ├── 80-1.png │ │ ├── 80.png │ │ ├── 87.png │ │ └── Contents.json │ └── Contents.json ├── CircleArc.swift ├── CircularProgressView.entitlements ├── CircularProgressViewApp.swift ├── ContentView.swift ├── Preview Content │ └── Preview Assets.xcassets │ │ └── Contents.json └── ProgressGeometry.swift ├── LICENSE └── README.md /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MahdiBM/CircularProgressView/cc9413067644bc5f9b804766246227f15e6c973b/.DS_Store -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /CircularProgressView.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 55; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 19192916267AD4E90001ABE7 /* CircleArc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19192915267AD4E90001ABE7 /* CircleArc.swift */; }; 11 | 19192918267AD4F70001ABE7 /* CircleOnPerimeter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19192917267AD4F70001ABE7 /* CircleOnPerimeter.swift */; }; 12 | 19E663FD2678DEE200898BA9 /* CircularProgressViewApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19E663FC2678DEE200898BA9 /* CircularProgressViewApp.swift */; }; 13 | 19E663FF2678DEE200898BA9 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19E663FE2678DEE200898BA9 /* ContentView.swift */; }; 14 | 19E664012678DEE400898BA9 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 19E664002678DEE400898BA9 /* Assets.xcassets */; }; 15 | 19E664042678DEE400898BA9 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 19E664032678DEE400898BA9 /* Preview Assets.xcassets */; }; 16 | 19E98B9F267B72FE0010EF6C /* ProgressGeometry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19E98B9E267B72FE0010EF6C /* ProgressGeometry.swift */; }; 17 | 19E98BA1267B93F40010EF6C /* AppIconView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 19E98BA0267B93F40010EF6C /* AppIconView.swift */; }; 18 | /* End PBXBuildFile section */ 19 | 20 | /* Begin PBXFileReference section */ 21 | 19192915267AD4E90001ABE7 /* CircleArc.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CircleArc.swift; sourceTree = ""; }; 22 | 19192917267AD4F70001ABE7 /* CircleOnPerimeter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CircleOnPerimeter.swift; sourceTree = ""; }; 23 | 19E663F92678DEE200898BA9 /* CircularProgressView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CircularProgressView.app; sourceTree = BUILT_PRODUCTS_DIR; }; 24 | 19E663FC2678DEE200898BA9 /* CircularProgressViewApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CircularProgressViewApp.swift; sourceTree = ""; }; 25 | 19E663FE2678DEE200898BA9 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; 26 | 19E664002678DEE400898BA9 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 27 | 19E664032678DEE400898BA9 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 28 | 19E98B9E267B72FE0010EF6C /* ProgressGeometry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressGeometry.swift; sourceTree = ""; }; 29 | 19E98BA0267B93F40010EF6C /* AppIconView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppIconView.swift; sourceTree = ""; }; 30 | 19E98BA2267B97690010EF6C /* CircularProgressView.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = CircularProgressView.entitlements; sourceTree = ""; }; 31 | /* End PBXFileReference section */ 32 | 33 | /* Begin PBXFrameworksBuildPhase section */ 34 | 19E663F62678DEE200898BA9 /* Frameworks */ = { 35 | isa = PBXFrameworksBuildPhase; 36 | buildActionMask = 2147483647; 37 | files = ( 38 | ); 39 | runOnlyForDeploymentPostprocessing = 0; 40 | }; 41 | /* End PBXFrameworksBuildPhase section */ 42 | 43 | /* Begin PBXGroup section */ 44 | 19E663F02678DEE200898BA9 = { 45 | isa = PBXGroup; 46 | children = ( 47 | 19E663FB2678DEE200898BA9 /* CircularProgressView */, 48 | 19E663FA2678DEE200898BA9 /* Products */, 49 | ); 50 | sourceTree = ""; 51 | }; 52 | 19E663FA2678DEE200898BA9 /* Products */ = { 53 | isa = PBXGroup; 54 | children = ( 55 | 19E663F92678DEE200898BA9 /* CircularProgressView.app */, 56 | ); 57 | name = Products; 58 | sourceTree = ""; 59 | }; 60 | 19E663FB2678DEE200898BA9 /* CircularProgressView */ = { 61 | isa = PBXGroup; 62 | children = ( 63 | 19E98BA2267B97690010EF6C /* CircularProgressView.entitlements */, 64 | 19E663FC2678DEE200898BA9 /* CircularProgressViewApp.swift */, 65 | 19E663FE2678DEE200898BA9 /* ContentView.swift */, 66 | 19192917267AD4F70001ABE7 /* CircleOnPerimeter.swift */, 67 | 19192915267AD4E90001ABE7 /* CircleArc.swift */, 68 | 19E98B9E267B72FE0010EF6C /* ProgressGeometry.swift */, 69 | 19E98BA0267B93F40010EF6C /* AppIconView.swift */, 70 | 19E664002678DEE400898BA9 /* Assets.xcassets */, 71 | 19E664022678DEE400898BA9 /* Preview Content */, 72 | ); 73 | path = CircularProgressView; 74 | sourceTree = ""; 75 | }; 76 | 19E664022678DEE400898BA9 /* Preview Content */ = { 77 | isa = PBXGroup; 78 | children = ( 79 | 19E664032678DEE400898BA9 /* Preview Assets.xcassets */, 80 | ); 81 | path = "Preview Content"; 82 | sourceTree = ""; 83 | }; 84 | /* End PBXGroup section */ 85 | 86 | /* Begin PBXNativeTarget section */ 87 | 19E663F82678DEE200898BA9 /* CircularProgressView */ = { 88 | isa = PBXNativeTarget; 89 | buildConfigurationList = 19E664072678DEE400898BA9 /* Build configuration list for PBXNativeTarget "CircularProgressView" */; 90 | buildPhases = ( 91 | 19E663F52678DEE200898BA9 /* Sources */, 92 | 19E663F62678DEE200898BA9 /* Frameworks */, 93 | 19E663F72678DEE200898BA9 /* Resources */, 94 | ); 95 | buildRules = ( 96 | ); 97 | dependencies = ( 98 | ); 99 | name = CircularProgressView; 100 | productName = CircularProgressView; 101 | productReference = 19E663F92678DEE200898BA9 /* CircularProgressView.app */; 102 | productType = "com.apple.product-type.application"; 103 | }; 104 | /* End PBXNativeTarget section */ 105 | 106 | /* Begin PBXProject section */ 107 | 19E663F12678DEE200898BA9 /* Project object */ = { 108 | isa = PBXProject; 109 | attributes = { 110 | BuildIndependentTargetsInParallel = 1; 111 | LastSwiftUpdateCheck = 1300; 112 | LastUpgradeCheck = 1300; 113 | TargetAttributes = { 114 | 19E663F82678DEE200898BA9 = { 115 | CreatedOnToolsVersion = 13.0; 116 | }; 117 | }; 118 | }; 119 | buildConfigurationList = 19E663F42678DEE200898BA9 /* Build configuration list for PBXProject "CircularProgressView" */; 120 | compatibilityVersion = "Xcode 13.0"; 121 | developmentRegion = en; 122 | hasScannedForEncodings = 0; 123 | knownRegions = ( 124 | en, 125 | Base, 126 | ); 127 | mainGroup = 19E663F02678DEE200898BA9; 128 | productRefGroup = 19E663FA2678DEE200898BA9 /* Products */; 129 | projectDirPath = ""; 130 | projectRoot = ""; 131 | targets = ( 132 | 19E663F82678DEE200898BA9 /* CircularProgressView */, 133 | ); 134 | }; 135 | /* End PBXProject section */ 136 | 137 | /* Begin PBXResourcesBuildPhase section */ 138 | 19E663F72678DEE200898BA9 /* Resources */ = { 139 | isa = PBXResourcesBuildPhase; 140 | buildActionMask = 2147483647; 141 | files = ( 142 | 19E664042678DEE400898BA9 /* Preview Assets.xcassets in Resources */, 143 | 19E664012678DEE400898BA9 /* Assets.xcassets in Resources */, 144 | ); 145 | runOnlyForDeploymentPostprocessing = 0; 146 | }; 147 | /* End PBXResourcesBuildPhase section */ 148 | 149 | /* Begin PBXSourcesBuildPhase section */ 150 | 19E663F52678DEE200898BA9 /* Sources */ = { 151 | isa = PBXSourcesBuildPhase; 152 | buildActionMask = 2147483647; 153 | files = ( 154 | 19192916267AD4E90001ABE7 /* CircleArc.swift in Sources */, 155 | 19E663FF2678DEE200898BA9 /* ContentView.swift in Sources */, 156 | 19192918267AD4F70001ABE7 /* CircleOnPerimeter.swift in Sources */, 157 | 19E98B9F267B72FE0010EF6C /* ProgressGeometry.swift in Sources */, 158 | 19E663FD2678DEE200898BA9 /* CircularProgressViewApp.swift in Sources */, 159 | 19E98BA1267B93F40010EF6C /* AppIconView.swift in Sources */, 160 | ); 161 | runOnlyForDeploymentPostprocessing = 0; 162 | }; 163 | /* End PBXSourcesBuildPhase section */ 164 | 165 | /* Begin XCBuildConfiguration section */ 166 | 19E664052678DEE400898BA9 /* Debug */ = { 167 | isa = XCBuildConfiguration; 168 | buildSettings = { 169 | ALWAYS_SEARCH_USER_PATHS = NO; 170 | CLANG_ANALYZER_NONNULL = YES; 171 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 172 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 173 | CLANG_CXX_LIBRARY = "libc++"; 174 | CLANG_ENABLE_MODULES = YES; 175 | CLANG_ENABLE_OBJC_ARC = YES; 176 | CLANG_ENABLE_OBJC_WEAK = YES; 177 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 178 | CLANG_WARN_BOOL_CONVERSION = YES; 179 | CLANG_WARN_COMMA = YES; 180 | CLANG_WARN_CONSTANT_CONVERSION = YES; 181 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 182 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 183 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 184 | CLANG_WARN_EMPTY_BODY = YES; 185 | CLANG_WARN_ENUM_CONVERSION = YES; 186 | CLANG_WARN_INFINITE_RECURSION = YES; 187 | CLANG_WARN_INT_CONVERSION = YES; 188 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 189 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 190 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 191 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 192 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 193 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 194 | CLANG_WARN_STRICT_PROTOTYPES = YES; 195 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 196 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 197 | CLANG_WARN_UNREACHABLE_CODE = YES; 198 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 199 | COPY_PHASE_STRIP = NO; 200 | DEBUG_INFORMATION_FORMAT = dwarf; 201 | ENABLE_STRICT_OBJC_MSGSEND = YES; 202 | ENABLE_TESTABILITY = YES; 203 | GCC_C_LANGUAGE_STANDARD = gnu11; 204 | GCC_DYNAMIC_NO_PIC = NO; 205 | GCC_NO_COMMON_BLOCKS = YES; 206 | GCC_OPTIMIZATION_LEVEL = 0; 207 | GCC_PREPROCESSOR_DEFINITIONS = ( 208 | "DEBUG=1", 209 | "$(inherited)", 210 | ); 211 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 212 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 213 | GCC_WARN_UNDECLARED_SELECTOR = YES; 214 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 215 | GCC_WARN_UNUSED_FUNCTION = YES; 216 | GCC_WARN_UNUSED_VARIABLE = YES; 217 | IPHONEOS_DEPLOYMENT_TARGET = 15.0; 218 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 219 | MTL_FAST_MATH = YES; 220 | ONLY_ACTIVE_ARCH = YES; 221 | SDKROOT = iphoneos; 222 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 223 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 224 | }; 225 | name = Debug; 226 | }; 227 | 19E664062678DEE400898BA9 /* Release */ = { 228 | isa = XCBuildConfiguration; 229 | buildSettings = { 230 | ALWAYS_SEARCH_USER_PATHS = NO; 231 | CLANG_ANALYZER_NONNULL = YES; 232 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 233 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 234 | CLANG_CXX_LIBRARY = "libc++"; 235 | CLANG_ENABLE_MODULES = YES; 236 | CLANG_ENABLE_OBJC_ARC = YES; 237 | CLANG_ENABLE_OBJC_WEAK = YES; 238 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 239 | CLANG_WARN_BOOL_CONVERSION = YES; 240 | CLANG_WARN_COMMA = YES; 241 | CLANG_WARN_CONSTANT_CONVERSION = YES; 242 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 243 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 244 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 245 | CLANG_WARN_EMPTY_BODY = YES; 246 | CLANG_WARN_ENUM_CONVERSION = YES; 247 | CLANG_WARN_INFINITE_RECURSION = YES; 248 | CLANG_WARN_INT_CONVERSION = YES; 249 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 250 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 251 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 252 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 253 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 254 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 255 | CLANG_WARN_STRICT_PROTOTYPES = YES; 256 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 257 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 258 | CLANG_WARN_UNREACHABLE_CODE = YES; 259 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 260 | COPY_PHASE_STRIP = NO; 261 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 262 | ENABLE_NS_ASSERTIONS = NO; 263 | ENABLE_STRICT_OBJC_MSGSEND = YES; 264 | GCC_C_LANGUAGE_STANDARD = gnu11; 265 | GCC_NO_COMMON_BLOCKS = YES; 266 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 267 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 268 | GCC_WARN_UNDECLARED_SELECTOR = YES; 269 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 270 | GCC_WARN_UNUSED_FUNCTION = YES; 271 | GCC_WARN_UNUSED_VARIABLE = YES; 272 | IPHONEOS_DEPLOYMENT_TARGET = 15.0; 273 | MTL_ENABLE_DEBUG_INFO = NO; 274 | MTL_FAST_MATH = YES; 275 | SDKROOT = iphoneos; 276 | SWIFT_COMPILATION_MODE = wholemodule; 277 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 278 | VALIDATE_PRODUCT = YES; 279 | }; 280 | name = Release; 281 | }; 282 | 19E664082678DEE400898BA9 /* Debug */ = { 283 | isa = XCBuildConfiguration; 284 | buildSettings = { 285 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 286 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 287 | CODE_SIGN_ENTITLEMENTS = CircularProgressView/CircularProgressView.entitlements; 288 | CODE_SIGN_STYLE = Automatic; 289 | CURRENT_PROJECT_VERSION = 1; 290 | DEVELOPMENT_ASSET_PATHS = "\"CircularProgressView/Preview Content\""; 291 | DEVELOPMENT_TEAM = WK3R397ZR4; 292 | ENABLE_PREVIEWS = YES; 293 | GENERATE_INFOPLIST_FILE = YES; 294 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; 295 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 296 | INFOPLIST_KEY_UILaunchScreen_Generation = YES; 297 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 298 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 299 | IPHONEOS_DEPLOYMENT_TARGET = 14.0; 300 | LD_RUNPATH_SEARCH_PATHS = ( 301 | "$(inherited)", 302 | "@executable_path/Frameworks", 303 | ); 304 | MARKETING_VERSION = 1.0; 305 | PRODUCT_BUNDLE_IDENTIFIER = com.bm.CircularProgressView; 306 | PRODUCT_NAME = "$(TARGET_NAME)"; 307 | SUPPORTS_MACCATALYST = YES; 308 | SWIFT_EMIT_LOC_STRINGS = YES; 309 | SWIFT_VERSION = 5.0; 310 | TARGETED_DEVICE_FAMILY = "1,2"; 311 | }; 312 | name = Debug; 313 | }; 314 | 19E664092678DEE400898BA9 /* Release */ = { 315 | isa = XCBuildConfiguration; 316 | buildSettings = { 317 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 318 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 319 | CODE_SIGN_ENTITLEMENTS = CircularProgressView/CircularProgressView.entitlements; 320 | CODE_SIGN_STYLE = Automatic; 321 | CURRENT_PROJECT_VERSION = 1; 322 | DEVELOPMENT_ASSET_PATHS = "\"CircularProgressView/Preview Content\""; 323 | DEVELOPMENT_TEAM = WK3R397ZR4; 324 | ENABLE_PREVIEWS = YES; 325 | GENERATE_INFOPLIST_FILE = YES; 326 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; 327 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 328 | INFOPLIST_KEY_UILaunchScreen_Generation = YES; 329 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 330 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 331 | IPHONEOS_DEPLOYMENT_TARGET = 14.0; 332 | LD_RUNPATH_SEARCH_PATHS = ( 333 | "$(inherited)", 334 | "@executable_path/Frameworks", 335 | ); 336 | MARKETING_VERSION = 1.0; 337 | PRODUCT_BUNDLE_IDENTIFIER = com.bm.CircularProgressView; 338 | PRODUCT_NAME = "$(TARGET_NAME)"; 339 | SUPPORTS_MACCATALYST = YES; 340 | SWIFT_EMIT_LOC_STRINGS = YES; 341 | SWIFT_VERSION = 5.0; 342 | TARGETED_DEVICE_FAMILY = "1,2"; 343 | }; 344 | name = Release; 345 | }; 346 | /* End XCBuildConfiguration section */ 347 | 348 | /* Begin XCConfigurationList section */ 349 | 19E663F42678DEE200898BA9 /* Build configuration list for PBXProject "CircularProgressView" */ = { 350 | isa = XCConfigurationList; 351 | buildConfigurations = ( 352 | 19E664052678DEE400898BA9 /* Debug */, 353 | 19E664062678DEE400898BA9 /* Release */, 354 | ); 355 | defaultConfigurationIsVisible = 0; 356 | defaultConfigurationName = Release; 357 | }; 358 | 19E664072678DEE400898BA9 /* Build configuration list for PBXNativeTarget "CircularProgressView" */ = { 359 | isa = XCConfigurationList; 360 | buildConfigurations = ( 361 | 19E664082678DEE400898BA9 /* Debug */, 362 | 19E664092678DEE400898BA9 /* Release */, 363 | ); 364 | defaultConfigurationIsVisible = 0; 365 | defaultConfigurationName = Release; 366 | }; 367 | /* End XCConfigurationList section */ 368 | }; 369 | rootObject = 19E663F12678DEE200898BA9 /* Project object */; 370 | } 371 | -------------------------------------------------------------------------------- /CircularProgressView.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /CircularProgressView.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /CircularProgressView.xcodeproj/project.xcworkspace/xcuserdata/mahdimac.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MahdiBM/CircularProgressView/cc9413067644bc5f9b804766246227f15e6c973b/CircularProgressView.xcodeproj/project.xcworkspace/xcuserdata/mahdimac.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /CircularProgressView.xcodeproj/xcuserdata/mahdimac.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /CircularProgressView.xcodeproj/xcuserdata/mahdimac.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | CircularProgressView.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /CircularProgressView/AppIconView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppIconView.swift 3 | // CircularProgressView 4 | // 5 | // Created by Mahdi 6 | // 7 | 8 | import SwiftUI 9 | 10 | /// The view used to make the app's icon. 11 | struct AppIconView: View { 12 | 13 | let radius = UIScreen.main.bounds.width * 2 / 5 14 | 15 | var body: some View { 16 | CircleArc.init( 17 | startAngle: .radians(-.pi / 5), 18 | endAngle: .radians(.pi * 6 / 5), 19 | lineWidth: 12 20 | ) 21 | .foregroundColor(.gray) 22 | .frame(width: radius * 2, height: radius * 2) 23 | .overlay( 24 | CircleArc.init( 25 | startAngle: .radians(-.pi / 5), 26 | endAngle: .radians(.pi * 4 / 5), 27 | lineWidth: 12 28 | ) 29 | .foregroundColor(.blue) 30 | ) 31 | .overlay( 32 | Circle() 33 | .frame(width: 20, height: 20) 34 | .foregroundColor(.green) 35 | .offset(x: radius) 36 | .rotationEffect(-.radians(.pi * 4 / 5)) 37 | ) 38 | .overlay( 39 | Image(systemName: "airplane") 40 | .resizable() 41 | .frame(maxWidth: 20, maxHeight: 20) 42 | .rotationEffect(.radians(.pi)) 43 | .foregroundColor(.red) 44 | .offset(x: radius) 45 | .rotationEffect(-.radians(.pi * 4 / 5)) 46 | ) 47 | } 48 | } 49 | 50 | // Preview Provider 51 | struct AppIconView_Previews: PreviewProvider { 52 | static var previews: some View { 53 | AppIconView() 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /CircularProgressView/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /CircularProgressView/Assets.xcassets/AppIcon.appiconset/1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MahdiBM/CircularProgressView/cc9413067644bc5f9b804766246227f15e6c973b/CircularProgressView/Assets.xcassets/AppIcon.appiconset/1024.png -------------------------------------------------------------------------------- /CircularProgressView/Assets.xcassets/AppIcon.appiconset/120-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MahdiBM/CircularProgressView/cc9413067644bc5f9b804766246227f15e6c973b/CircularProgressView/Assets.xcassets/AppIcon.appiconset/120-1.png -------------------------------------------------------------------------------- /CircularProgressView/Assets.xcassets/AppIcon.appiconset/120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MahdiBM/CircularProgressView/cc9413067644bc5f9b804766246227f15e6c973b/CircularProgressView/Assets.xcassets/AppIcon.appiconset/120.png -------------------------------------------------------------------------------- /CircularProgressView/Assets.xcassets/AppIcon.appiconset/152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MahdiBM/CircularProgressView/cc9413067644bc5f9b804766246227f15e6c973b/CircularProgressView/Assets.xcassets/AppIcon.appiconset/152.png -------------------------------------------------------------------------------- /CircularProgressView/Assets.xcassets/AppIcon.appiconset/167.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MahdiBM/CircularProgressView/cc9413067644bc5f9b804766246227f15e6c973b/CircularProgressView/Assets.xcassets/AppIcon.appiconset/167.png -------------------------------------------------------------------------------- /CircularProgressView/Assets.xcassets/AppIcon.appiconset/180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MahdiBM/CircularProgressView/cc9413067644bc5f9b804766246227f15e6c973b/CircularProgressView/Assets.xcassets/AppIcon.appiconset/180.png -------------------------------------------------------------------------------- /CircularProgressView/Assets.xcassets/AppIcon.appiconset/20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MahdiBM/CircularProgressView/cc9413067644bc5f9b804766246227f15e6c973b/CircularProgressView/Assets.xcassets/AppIcon.appiconset/20.png -------------------------------------------------------------------------------- /CircularProgressView/Assets.xcassets/AppIcon.appiconset/29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MahdiBM/CircularProgressView/cc9413067644bc5f9b804766246227f15e6c973b/CircularProgressView/Assets.xcassets/AppIcon.appiconset/29.png -------------------------------------------------------------------------------- /CircularProgressView/Assets.xcassets/AppIcon.appiconset/40-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MahdiBM/CircularProgressView/cc9413067644bc5f9b804766246227f15e6c973b/CircularProgressView/Assets.xcassets/AppIcon.appiconset/40-1.png -------------------------------------------------------------------------------- /CircularProgressView/Assets.xcassets/AppIcon.appiconset/40-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MahdiBM/CircularProgressView/cc9413067644bc5f9b804766246227f15e6c973b/CircularProgressView/Assets.xcassets/AppIcon.appiconset/40-2.png -------------------------------------------------------------------------------- /CircularProgressView/Assets.xcassets/AppIcon.appiconset/40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MahdiBM/CircularProgressView/cc9413067644bc5f9b804766246227f15e6c973b/CircularProgressView/Assets.xcassets/AppIcon.appiconset/40.png -------------------------------------------------------------------------------- /CircularProgressView/Assets.xcassets/AppIcon.appiconset/58-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MahdiBM/CircularProgressView/cc9413067644bc5f9b804766246227f15e6c973b/CircularProgressView/Assets.xcassets/AppIcon.appiconset/58-1.png -------------------------------------------------------------------------------- /CircularProgressView/Assets.xcassets/AppIcon.appiconset/58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MahdiBM/CircularProgressView/cc9413067644bc5f9b804766246227f15e6c973b/CircularProgressView/Assets.xcassets/AppIcon.appiconset/58.png -------------------------------------------------------------------------------- /CircularProgressView/Assets.xcassets/AppIcon.appiconset/60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MahdiBM/CircularProgressView/cc9413067644bc5f9b804766246227f15e6c973b/CircularProgressView/Assets.xcassets/AppIcon.appiconset/60.png -------------------------------------------------------------------------------- /CircularProgressView/Assets.xcassets/AppIcon.appiconset/76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MahdiBM/CircularProgressView/cc9413067644bc5f9b804766246227f15e6c973b/CircularProgressView/Assets.xcassets/AppIcon.appiconset/76.png -------------------------------------------------------------------------------- /CircularProgressView/Assets.xcassets/AppIcon.appiconset/80-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MahdiBM/CircularProgressView/cc9413067644bc5f9b804766246227f15e6c973b/CircularProgressView/Assets.xcassets/AppIcon.appiconset/80-1.png -------------------------------------------------------------------------------- /CircularProgressView/Assets.xcassets/AppIcon.appiconset/80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MahdiBM/CircularProgressView/cc9413067644bc5f9b804766246227f15e6c973b/CircularProgressView/Assets.xcassets/AppIcon.appiconset/80.png -------------------------------------------------------------------------------- /CircularProgressView/Assets.xcassets/AppIcon.appiconset/87.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MahdiBM/CircularProgressView/cc9413067644bc5f9b804766246227f15e6c973b/CircularProgressView/Assets.xcassets/AppIcon.appiconset/87.png -------------------------------------------------------------------------------- /CircularProgressView/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "40.png", 5 | "idiom" : "iphone", 6 | "scale" : "2x", 7 | "size" : "20x20" 8 | }, 9 | { 10 | "filename" : "60.png", 11 | "idiom" : "iphone", 12 | "scale" : "3x", 13 | "size" : "20x20" 14 | }, 15 | { 16 | "filename" : "58.png", 17 | "idiom" : "iphone", 18 | "scale" : "2x", 19 | "size" : "29x29" 20 | }, 21 | { 22 | "filename" : "87.png", 23 | "idiom" : "iphone", 24 | "scale" : "3x", 25 | "size" : "29x29" 26 | }, 27 | { 28 | "filename" : "80.png", 29 | "idiom" : "iphone", 30 | "scale" : "2x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "filename" : "120.png", 35 | "idiom" : "iphone", 36 | "scale" : "3x", 37 | "size" : "40x40" 38 | }, 39 | { 40 | "filename" : "120-1.png", 41 | "idiom" : "iphone", 42 | "scale" : "2x", 43 | "size" : "60x60" 44 | }, 45 | { 46 | "filename" : "180.png", 47 | "idiom" : "iphone", 48 | "scale" : "3x", 49 | "size" : "60x60" 50 | }, 51 | { 52 | "filename" : "20.png", 53 | "idiom" : "ipad", 54 | "scale" : "1x", 55 | "size" : "20x20" 56 | }, 57 | { 58 | "filename" : "40-1.png", 59 | "idiom" : "ipad", 60 | "scale" : "2x", 61 | "size" : "20x20" 62 | }, 63 | { 64 | "filename" : "29.png", 65 | "idiom" : "ipad", 66 | "scale" : "1x", 67 | "size" : "29x29" 68 | }, 69 | { 70 | "filename" : "58-1.png", 71 | "idiom" : "ipad", 72 | "scale" : "2x", 73 | "size" : "29x29" 74 | }, 75 | { 76 | "filename" : "40-2.png", 77 | "idiom" : "ipad", 78 | "scale" : "1x", 79 | "size" : "40x40" 80 | }, 81 | { 82 | "filename" : "80-1.png", 83 | "idiom" : "ipad", 84 | "scale" : "2x", 85 | "size" : "40x40" 86 | }, 87 | { 88 | "filename" : "76.png", 89 | "idiom" : "ipad", 90 | "scale" : "1x", 91 | "size" : "76x76" 92 | }, 93 | { 94 | "filename" : "152.png", 95 | "idiom" : "ipad", 96 | "scale" : "2x", 97 | "size" : "76x76" 98 | }, 99 | { 100 | "filename" : "167.png", 101 | "idiom" : "ipad", 102 | "scale" : "2x", 103 | "size" : "83.5x83.5" 104 | }, 105 | { 106 | "filename" : "1024.png", 107 | "idiom" : "ios-marketing", 108 | "scale" : "1x", 109 | "size" : "1024x1024" 110 | } 111 | ], 112 | "info" : { 113 | "author" : "xcode", 114 | "version" : 1 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /CircularProgressView/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /CircularProgressView/CircleArc.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CircleArc.swift 3 | // CircularProgressView 4 | // 5 | // Created by Mahdi 6 | // 7 | 8 | import SwiftUI 9 | 10 | /// Draws a stroked path of an arc of a circle. 11 | struct CircleArc: Shape { 12 | /// The left hand angle. 13 | var startAngle: Angle 14 | /// The right hand angle. 15 | var endAngle: Angle 16 | /// The width of the stroke. 17 | var lineWidth: CGFloat 18 | 19 | func path(in rect: CGRect) -> Path { 20 | Path { path in 21 | /// Don't really know why, but to draw a pod-clockwise arc from 22 | /// `startAngle` to `endAngle` you need to pass their negative values 23 | /// with `clockwise` set to `true`. (apple's fault) 24 | path.addArc( 25 | center: CGPoint(x: rect.midX, y: rect.midY), 26 | radius: rect.width / 2, 27 | startAngle: -startAngle, 28 | endAngle: -endAngle, 29 | clockwise: true 30 | ) 31 | path = path.strokedPath(.init(lineWidth: lineWidth, lineCap: .round)) 32 | } 33 | } 34 | } 35 | 36 | // Animatable conformance 37 | extension CircleArc: Animatable { 38 | var animatableData: AnimatablePair { 39 | get { .init(startAngle.radians, endAngle.radians) } 40 | set { 41 | startAngle = .radians(newValue.first) 42 | endAngle = .radians(newValue.second) 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /CircularProgressView/CircularProgressView.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.network.client 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /CircularProgressView/CircularProgressViewApp.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CircularProgressViewApp.swift 3 | // CircularProgressView 4 | // 5 | // Created by Mahdi 6 | // 7 | 8 | import SwiftUI 9 | 10 | @main 11 | struct CircularProgressViewApp: App { 12 | var body: some Scene { 13 | WindowGroup { 14 | ContentView() 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /CircularProgressView/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // CircularProgressView 4 | // 5 | // Created by Mahdi 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ContentView: View { 11 | /// The radius of the bigger circle everything is drawn on. 12 | let radius: CGFloat = 120 13 | /// The Progress. 14 | @State private var progress: CGFloat = 0.333 /* 0 <= progress <= 1 */ 15 | /// Angle number 1. 16 | @State private var angle1: Angle = .zero 17 | /// Angle number 2. 18 | @State private var angle2: Angle = .radians(3 * .pi / 2) 19 | /// The stroke's width. 20 | @State private var lineWidth: CGFloat = 8 21 | /// Right to left or left to right progressing. 22 | @State private var rightToLeft: Bool = false 23 | /// The angle to offset `angle.start` and `angles.end` with. 24 | /// This will just turn the circle to make creating some arcs possible. 25 | @State private var offsetAngle: Angle = .radians(.pi / 4) 26 | /// The geometry used to draw shapes. 27 | @State private var geo: ProgressGeometry = .zero 28 | 29 | var body: some View { 30 | 31 | populateProgressGeometry() 32 | 33 | return VStack(spacing: 2) { 34 | 35 | /// Progress View 36 | 37 | CircleArc(startAngle: geo.angles.start, endAngle: geo.angles.end, lineWidth: lineWidth) 38 | .frame(width: radius * 2, height: radius * 2) 39 | .foregroundColor(.gray) 40 | .overlay( 41 | CircleArc( 42 | startAngle: geo.progressAngles.start, 43 | endAngle: geo.progressAngles.end, 44 | lineWidth: lineWidth 45 | ).foregroundColor(.blue) 46 | ) 47 | .overlay( 48 | Circle() 49 | .frame(width: geo.indicatorRadius * 2, height: geo.indicatorRadius * 2) 50 | .foregroundColor(.green) 51 | .offset(x: radius) 52 | /// My calculations are pod-clockwise, but `rotationEffect(_:)` works 53 | /// clockwise (apple's fault), thats the reason of the `-` sign. 54 | .rotationEffect(-geo.circleAngle) 55 | ) 56 | .overlay( 57 | Image(systemName: "airplane") 58 | .resizable() 59 | .frame(maxWidth: geo.indicatorRadius, maxHeight: geo.indicatorRadius) 60 | .scaledToFit() 61 | /// This keeps the plane always pointing to the same point, even when rotated. 62 | .rotationEffect(geo.circleAngle + (rightToLeft ? .radians(.pi) : .zero)) 63 | .foregroundColor(.red) 64 | .offset(x: radius) 65 | /// My calculations are pod-clockwise, but `rotationEffect(_:)` works 66 | /// clockwise (apple's fault), thats the reason of the `-` sign. 67 | .rotationEffect(-geo.circleAngle) 68 | ) 69 | 70 | /// Controllers 71 | VStack { 72 | HStack { 73 | Button("right to left: \(rightToLeft.description)") { 74 | rightToLeft.toggle() 75 | } 76 | .padding(6) 77 | 78 | Button("toggle progress") { 79 | if progress.rounded(.toNearestOrEven) == 0 { 80 | progress = 1 81 | } else { 82 | progress = 0 83 | } 84 | } 85 | .padding(6) 86 | } 87 | .font(.headline) 88 | 89 | Group { 90 | Text("progress: \(progress)") 91 | Slider(value: $progress, in: (0.001)...1) 92 | 93 | Text("\(angle1 > angle2 ? "end" : "start"): \(angle1.degrees)") 94 | Slider(value: .init( 95 | get: { angle1.degrees }, 96 | set: { angle1 = .degrees($0) } 97 | ), in: 0...360) 98 | 99 | Text("\(angle1 > angle2 ? "start" : "end"): \(angle2.degrees)") 100 | Slider(value: .init( 101 | get: { angle2.degrees }, 102 | set: { angle2 = .degrees($0) } 103 | ), in: (0.1)...359.9) 104 | 105 | Text("offset angle: \(offsetAngle.degrees)") 106 | Slider(value: .init( 107 | get: { offsetAngle.degrees }, 108 | set: { offsetAngle = .degrees($0) } 109 | ), in: (0.1)...359.9) 110 | 111 | Text("width: \(lineWidth)") 112 | Slider(value: $lineWidth, in: 1...40) 113 | } 114 | } 115 | .padding(.horizontal) 116 | 117 | } 118 | .animation(.easeInOut.speed(0.5)) 119 | .onChange(of: progress) { newValue in 120 | /// Progress == 0 might result in animation errors. 121 | if newValue == 0 { progress = 0.001 } 122 | } 123 | } 124 | 125 | private func populateProgressGeometry() { 126 | DispatchQueue.main.async { 127 | self.geo = .init( 128 | progress: self.progress, 129 | radius: self.radius, 130 | angle1: self.angle1, 131 | angle2: self.angle2, 132 | lineWidth: self.lineWidth, 133 | rightToLeft: self.rightToLeft, 134 | offsetAngle: self.offsetAngle 135 | ) 136 | } 137 | } 138 | 139 | } 140 | 141 | // Preview Provider 142 | struct ContentView_Previews: PreviewProvider { 143 | static var previews: some View { 144 | ContentView() 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /CircularProgressView/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /CircularProgressView/ProgressGeometry.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ProgressGeometry.swift 3 | // CircularProgressView 4 | // 5 | // Created by Mahdi 6 | // 7 | 8 | import SwiftUI 9 | 10 | /// Container of geometry info that are used to make the progress-view. 11 | struct ProgressGeometry { 12 | /// Angles of the big-gray-arc-stroke. 13 | let angles: (start: Angle, end: Angle) 14 | /// The angle relative to the amount of the progress we had. 15 | let progressedAngle: Angle 16 | /// The angle at which the little circle is drawn. (the green circle) 17 | let circleAngle: Angle 18 | /// The angles of the progress arc. (the blue arc stroke) 19 | let progressAngles: (start: Angle, end: Angle) 20 | /// Radius of the progress indicator. 21 | let indicatorRadius: CGFloat 22 | /// Starting value to be used for a SwiftUI View. 23 | static let zero: Self = .init( 24 | progress: 0, radius: 0, angle1: .zero, angle2: .zero, 25 | lineWidth: 0, rightToLeft: false, offsetAngle: .zero) 26 | 27 | init( 28 | progress: CGFloat, 29 | radius: CGFloat, 30 | angle1: Angle, 31 | angle2: Angle, 32 | lineWidth: CGFloat, 33 | rightToLeft: Bool, 34 | offsetAngle: Angle 35 | ) { 36 | let angles: (start: Angle, end: Angle) = { 37 | if angle2 > angle1 { 38 | return (angle1 - offsetAngle, angle2 - offsetAngle) 39 | } else { 40 | return (angle2 - offsetAngle, angle1 - offsetAngle) 41 | } 42 | }() 43 | /// The arc which is visible and progress-able. (the gray arc) 44 | let wholeArc: Angle = angles.end - angles.start 45 | let progressedAngle: Angle = .radians(wholeArc.radians * progress) 46 | let circleAngle: Angle = { 47 | if rightToLeft { 48 | return (progressedAngle + angles.start) 49 | } else { 50 | return (angles.end - progressedAngle) 51 | } 52 | }() 53 | let progressAngles: (start: Angle, end: Angle) = { 54 | if rightToLeft { 55 | return (start: angles.start, end: circleAngle) 56 | } else { 57 | return (start: circleAngle, end: angles.end) 58 | } 59 | }() 60 | let indicatorRadius = lineWidth * 2 61 | 62 | self.angles = angles 63 | self.progressedAngle = progressedAngle 64 | self.circleAngle = circleAngle 65 | self.progressAngles = progressAngles 66 | self.indicatorRadius = indicatorRadius 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 MahdiBM 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | A Circular progress view. 2 | 3 | There are some controllers to let you customize the progress-view and see which one works better for you. 4 | 5 | This whole project is licensed under the MIT license attached to the project. 6 | 7 | 8 | [CircularProgressView Movie](https://user-images.githubusercontent.com/54685446/122641048-ffbd9680-d117-11eb-8032-a68a799089fb.MOV) 9 | 10 | --------------------------------------------------------------------------------