├── Cartfile ├── Gemfile ├── Cartfile.resolved ├── ZVProgressHUDExample ├── smile.png ├── Assets.xcassets │ ├── Contents.json │ ├── smile.imageset │ │ ├── Smile.png │ │ └── Contents.json │ ├── close.imageset │ │ ├── close@2x.png │ │ ├── close@3x.png │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ ├── Icon-20.png │ │ ├── Icon-29.png │ │ ├── Icon-40.png │ │ ├── Icon-76.png │ │ ├── Icon-20@2x.png │ │ ├── Icon-20@3x.png │ │ ├── Icon-29@2x.png │ │ ├── Icon-29@3x.png │ │ ├── Icon-40@2x.png │ │ ├── Icon-40@3x.png │ │ ├── Icon-60@2x.png │ │ ├── Icon-60@3x.png │ │ ├── Icon-76@2x.png │ │ ├── Icon-83_5@2x.png │ │ ├── ios-marketing.png │ │ └── Contents.json │ ├── logo_crown.imageset │ │ ├── logo_crown@2x.png │ │ ├── logo_crown@3x.png │ │ └── Contents.json │ ├── loading_01.imageset │ │ ├── dropdown_loading_01@2x.png │ │ └── Contents.json │ ├── loading_02.imageset │ │ ├── dropdown_loading_02@2x.png │ │ └── Contents.json │ └── loading_03.imageset │ │ ├── dropdown_loading_03@2x.png │ │ └── Contents.json ├── Info.plist ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── AppDelegate.swift ├── ZVDownloadingView.swift └── ViewController.swift ├── ZVProgressHUD ├── Resource.bundle │ ├── error.png │ ├── success.png │ └── warning.png ├── ZVProgressHUD.h ├── Info.plist ├── ZVProgressView.swift ├── ZVIndicatorView.swift ├── ZVProgressHUDExtensions.swift └── ZVProgressHUD.swift ├── .swiftpm └── xcode │ └── package.xcworkspace │ └── contents.xcworkspacedata ├── ZVProgressHUD.xcodeproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── swiftpm │ │ └── Package.resolved ├── xcshareddata │ └── xcschemes │ │ └── ZVProgressHUD.xcscheme └── project.pbxproj ├── fastlane ├── Appfile ├── Fastfile └── README.md ├── Package.resolved ├── Package.swift ├── LICENSE ├── ZVProgressHUD.podspec ├── .gitignore ├── .swiftlint.yml ├── README_CN.md ├── README.md └── Gemfile.lock /Cartfile: -------------------------------------------------------------------------------- 1 | github "zevwings/ZVActivityIndicatorView" -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gem "fastlane" 4 | -------------------------------------------------------------------------------- /Cartfile.resolved: -------------------------------------------------------------------------------- 1 | github "zevwings/ZVActivityIndicatorView" "1.0.0" 2 | -------------------------------------------------------------------------------- /ZVProgressHUDExample/smile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zevwings/ZVProgressHUD/HEAD/ZVProgressHUDExample/smile.png -------------------------------------------------------------------------------- /ZVProgressHUD/Resource.bundle/error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zevwings/ZVProgressHUD/HEAD/ZVProgressHUD/Resource.bundle/error.png -------------------------------------------------------------------------------- /ZVProgressHUDExample/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ZVProgressHUD/Resource.bundle/success.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zevwings/ZVProgressHUD/HEAD/ZVProgressHUD/Resource.bundle/success.png -------------------------------------------------------------------------------- /ZVProgressHUD/Resource.bundle/warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zevwings/ZVProgressHUD/HEAD/ZVProgressHUD/Resource.bundle/warning.png -------------------------------------------------------------------------------- /ZVProgressHUDExample/Assets.xcassets/smile.imageset/Smile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zevwings/ZVProgressHUD/HEAD/ZVProgressHUDExample/Assets.xcassets/smile.imageset/Smile.png -------------------------------------------------------------------------------- /ZVProgressHUDExample/Assets.xcassets/close.imageset/close@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zevwings/ZVProgressHUD/HEAD/ZVProgressHUDExample/Assets.xcassets/close.imageset/close@2x.png -------------------------------------------------------------------------------- /ZVProgressHUDExample/Assets.xcassets/close.imageset/close@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zevwings/ZVProgressHUD/HEAD/ZVProgressHUDExample/Assets.xcassets/close.imageset/close@3x.png -------------------------------------------------------------------------------- /ZVProgressHUDExample/Assets.xcassets/AppIcon.appiconset/Icon-20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zevwings/ZVProgressHUD/HEAD/ZVProgressHUDExample/Assets.xcassets/AppIcon.appiconset/Icon-20.png -------------------------------------------------------------------------------- /ZVProgressHUDExample/Assets.xcassets/AppIcon.appiconset/Icon-29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zevwings/ZVProgressHUD/HEAD/ZVProgressHUDExample/Assets.xcassets/AppIcon.appiconset/Icon-29.png -------------------------------------------------------------------------------- /ZVProgressHUDExample/Assets.xcassets/AppIcon.appiconset/Icon-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zevwings/ZVProgressHUD/HEAD/ZVProgressHUDExample/Assets.xcassets/AppIcon.appiconset/Icon-40.png -------------------------------------------------------------------------------- /ZVProgressHUDExample/Assets.xcassets/AppIcon.appiconset/Icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zevwings/ZVProgressHUD/HEAD/ZVProgressHUDExample/Assets.xcassets/AppIcon.appiconset/Icon-76.png -------------------------------------------------------------------------------- /ZVProgressHUDExample/Assets.xcassets/AppIcon.appiconset/Icon-20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zevwings/ZVProgressHUD/HEAD/ZVProgressHUDExample/Assets.xcassets/AppIcon.appiconset/Icon-20@2x.png -------------------------------------------------------------------------------- /ZVProgressHUDExample/Assets.xcassets/AppIcon.appiconset/Icon-20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zevwings/ZVProgressHUD/HEAD/ZVProgressHUDExample/Assets.xcassets/AppIcon.appiconset/Icon-20@3x.png -------------------------------------------------------------------------------- /ZVProgressHUDExample/Assets.xcassets/AppIcon.appiconset/Icon-29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zevwings/ZVProgressHUD/HEAD/ZVProgressHUDExample/Assets.xcassets/AppIcon.appiconset/Icon-29@2x.png -------------------------------------------------------------------------------- /ZVProgressHUDExample/Assets.xcassets/AppIcon.appiconset/Icon-29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zevwings/ZVProgressHUD/HEAD/ZVProgressHUDExample/Assets.xcassets/AppIcon.appiconset/Icon-29@3x.png -------------------------------------------------------------------------------- /ZVProgressHUDExample/Assets.xcassets/AppIcon.appiconset/Icon-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zevwings/ZVProgressHUD/HEAD/ZVProgressHUDExample/Assets.xcassets/AppIcon.appiconset/Icon-40@2x.png -------------------------------------------------------------------------------- /ZVProgressHUDExample/Assets.xcassets/AppIcon.appiconset/Icon-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zevwings/ZVProgressHUD/HEAD/ZVProgressHUDExample/Assets.xcassets/AppIcon.appiconset/Icon-40@3x.png -------------------------------------------------------------------------------- /ZVProgressHUDExample/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zevwings/ZVProgressHUD/HEAD/ZVProgressHUDExample/Assets.xcassets/AppIcon.appiconset/Icon-60@2x.png -------------------------------------------------------------------------------- /ZVProgressHUDExample/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zevwings/ZVProgressHUD/HEAD/ZVProgressHUDExample/Assets.xcassets/AppIcon.appiconset/Icon-60@3x.png -------------------------------------------------------------------------------- /ZVProgressHUDExample/Assets.xcassets/AppIcon.appiconset/Icon-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zevwings/ZVProgressHUD/HEAD/ZVProgressHUDExample/Assets.xcassets/AppIcon.appiconset/Icon-76@2x.png -------------------------------------------------------------------------------- /ZVProgressHUDExample/Assets.xcassets/AppIcon.appiconset/Icon-83_5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zevwings/ZVProgressHUD/HEAD/ZVProgressHUDExample/Assets.xcassets/AppIcon.appiconset/Icon-83_5@2x.png -------------------------------------------------------------------------------- /ZVProgressHUDExample/Assets.xcassets/AppIcon.appiconset/ios-marketing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zevwings/ZVProgressHUD/HEAD/ZVProgressHUDExample/Assets.xcassets/AppIcon.appiconset/ios-marketing.png -------------------------------------------------------------------------------- /ZVProgressHUDExample/Assets.xcassets/logo_crown.imageset/logo_crown@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zevwings/ZVProgressHUD/HEAD/ZVProgressHUDExample/Assets.xcassets/logo_crown.imageset/logo_crown@2x.png -------------------------------------------------------------------------------- /ZVProgressHUDExample/Assets.xcassets/logo_crown.imageset/logo_crown@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zevwings/ZVProgressHUD/HEAD/ZVProgressHUDExample/Assets.xcassets/logo_crown.imageset/logo_crown@3x.png -------------------------------------------------------------------------------- /.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ZVProgressHUDExample/Assets.xcassets/loading_01.imageset/dropdown_loading_01@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zevwings/ZVProgressHUD/HEAD/ZVProgressHUDExample/Assets.xcassets/loading_01.imageset/dropdown_loading_01@2x.png -------------------------------------------------------------------------------- /ZVProgressHUDExample/Assets.xcassets/loading_02.imageset/dropdown_loading_02@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zevwings/ZVProgressHUD/HEAD/ZVProgressHUDExample/Assets.xcassets/loading_02.imageset/dropdown_loading_02@2x.png -------------------------------------------------------------------------------- /ZVProgressHUDExample/Assets.xcassets/loading_03.imageset/dropdown_loading_03@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zevwings/ZVProgressHUD/HEAD/ZVProgressHUDExample/Assets.xcassets/loading_03.imageset/dropdown_loading_03@2x.png -------------------------------------------------------------------------------- /ZVProgressHUD.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /fastlane/Appfile: -------------------------------------------------------------------------------- 1 | # app_identifier("[[APP_IDENTIFIER]]") # The bundle identifier of your app 2 | # apple_id("[[APPLE_ID]]") # Your Apple email address 3 | 4 | 5 | # For more information about the Appfile, see: 6 | # https://docs.fastlane.tools/advanced/#appfile 7 | -------------------------------------------------------------------------------- /ZVProgressHUD.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "object": { 3 | "pins": [ 4 | { 5 | "package": "ZVActivityIndicatorView", 6 | "repositoryURL": "https://github.com/zevwings/ZVActivityIndicatorView.git", 7 | "state": { 8 | "branch": null, 9 | "revision": "cad655bc187df933f9e21017873d11f72c08c038", 10 | "version": "0.2.4" 11 | } 12 | } 13 | ] 14 | }, 15 | "version": 1 16 | } 17 | -------------------------------------------------------------------------------- /ZVProgressHUDExample/Assets.xcassets/smile.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Smile.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /ZVProgressHUDExample/Assets.xcassets/loading_01.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "dropdown_loading_01@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /ZVProgressHUDExample/Assets.xcassets/loading_02.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "dropdown_loading_02@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /ZVProgressHUDExample/Assets.xcassets/loading_03.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "dropdown_loading_03@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /ZVProgressHUD.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "object": { 3 | "pins": [ 4 | { 5 | "package": "ZVActivityIndicatorView", 6 | "repositoryURL": "https://github.com/zevwings/ZVActivityIndicatorView.git", 7 | "state": { 8 | "branch": null, 9 | "revision": "cad655bc187df933f9e21017873d11f72c08c038", 10 | "version": "0.2.4" 11 | } 12 | } 13 | ] 14 | }, 15 | "version": 1 16 | } 17 | -------------------------------------------------------------------------------- /ZVProgressHUDExample/Assets.xcassets/close.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "close@2x.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "filename" : "close@3x.png", 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ZVProgressHUDExample/Assets.xcassets/logo_crown.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "logo_crown@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "logo_crown@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /ZVProgressHUD/ZVProgressHUD.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZVProgressHUD.h 3 | // ZVProgressHUD 4 | // 5 | // Created by zevwings on 2017/7/11. 6 | // Copyright © 2017-2019 zevwings. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for ZVProgressHUD. 12 | FOUNDATION_EXPORT double ZVProgressHUDVersionNumber; 13 | 14 | //! Project version string for ZVProgressHUD. 15 | FOUNDATION_EXPORT const unsigned char ZVProgressHUDVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /fastlane/Fastfile: -------------------------------------------------------------------------------- 1 | # This file contains the fastlane.tools configuration 2 | # You can find the documentation at https://docs.fastlane.tools 3 | # 4 | # For a list of all available actions, check out 5 | # 6 | # https://docs.fastlane.tools/actions 7 | # 8 | # For a list of all available plugins, check out 9 | # 10 | # https://docs.fastlane.tools/plugins/available-plugins 11 | # 12 | 13 | # Uncomment the line if you want fastlane to automatically update itself 14 | # update_fastlane 15 | 16 | default_platform(:ios) 17 | 18 | platform :ios do 19 | 20 | desc "Build and upload to appetize" 21 | lane :upload_appetize do |options| 22 | git_pull 23 | build_and_upload_to_appetize(scheme: "ZVProgressHUDExample", api_token: "tok_8hajudt52c6921vcq5pzht6u4c", public_key: "39txw9h5d7mrkckm6f9vp9mn2r") 24 | end 25 | 26 | end 27 | -------------------------------------------------------------------------------- /fastlane/README.md: -------------------------------------------------------------------------------- 1 | fastlane documentation 2 | ================ 3 | # Installation 4 | 5 | Make sure you have the latest version of the Xcode command line tools installed: 6 | 7 | ``` 8 | xcode-select --install 9 | ``` 10 | 11 | Install _fastlane_ using 12 | ``` 13 | [sudo] gem install fastlane -NV 14 | ``` 15 | or alternatively using `brew install fastlane` 16 | 17 | # Available Actions 18 | ## iOS 19 | ### ios upload_appetize 20 | ``` 21 | fastlane ios upload_appetize 22 | ``` 23 | Build and upload to appetize 24 | 25 | ---- 26 | 27 | This README.md is auto-generated and will be re-generated every time [_fastlane_](https://fastlane.tools) is run. 28 | More information about fastlane can be found on [fastlane.tools](https://fastlane.tools). 29 | The documentation of fastlane can be found on [docs.fastlane.tools](https://docs.fastlane.tools). 30 | -------------------------------------------------------------------------------- /ZVProgressHUD/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 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.3 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | 4 | import PackageDescription 5 | 6 | let package = Package( 7 | name: "ZVProgressHUD", 8 | platforms: [.iOS(.v9)], 9 | products: [ 10 | .library( 11 | name: "ZVProgressHUD", 12 | targets: ["ZVProgressHUD"]), 13 | ], 14 | dependencies: [ 15 | .package(url: "https://github.com/zevwings/ZVActivityIndicatorView.git", from: "0.2.1"), 16 | ], 17 | targets: [ 18 | .target( 19 | name: "ZVProgressHUD", 20 | dependencies: ["ZVActivityIndicatorView"], 21 | path: "./ZVProgressHUD", 22 | exclude: ["Info.plist"], 23 | resources: [ 24 | .process("Resource.bundle") 25 | ], 26 | swiftSettings: [ 27 | .define("ZVProgressHUD_SPM") 28 | ] 29 | ) 30 | ], 31 | swiftLanguageVersions: [.v5] 32 | ) 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 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 | -------------------------------------------------------------------------------- /ZVProgressHUD.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod spec lint ZVProgressHUD.podspec' to ensure this is a 3 | # valid spec and to remove all comments including this before submitting the spec. 4 | # 5 | # To learn more about Podspec attributes see http://docs.cocoapods.org/specification.html 6 | # To see working Podspecs in the CocoaPods repo see https://github.com/CocoaPods/Specs/ 7 | # 8 | 9 | Pod::Spec.new do |s| 10 | 11 | s.name = "ZVProgressHUD" 12 | s.version = "3.0.6" 13 | s.summary = "A pure-swift and wieldy HUD" 14 | s.swift_version = '5.1' 15 | 16 | s.description = <<-DESC 17 | ZVProgressHUD a pure-swift and wieldy HUD 18 | DESC 19 | 20 | s.homepage = "https://github.com/zevwings/ZVProgressHUD" 21 | s.license = "MIT" 22 | s.author = { "zevwings" => "zevwings@gmail.com" } 23 | s.platform = :ios, "9.0" 24 | s.source = { :git => "https://github.com/zevwings/ZVProgressHUD.git", :tag => "#{s.version}" } 25 | s.source_files = "ZVProgressHUD/**/*.swift", "ZVProgressHUD/ZVProgressHUD.h" 26 | s.resources = "ZVProgressHUD/Resource.bundle" 27 | s.requires_arc = true 28 | 29 | s.dependency 'ZVActivityIndicatorView' 30 | 31 | end 32 | -------------------------------------------------------------------------------- /ZVProgressHUDExample/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xccheckout 23 | *.xcscmblueprint 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | *.ipa 28 | *.dSYM.zip 29 | *.dSYM 30 | 31 | ## Playgrounds 32 | timeline.xctimeline 33 | playground.xcworkspace 34 | 35 | # Swift Package Manager 36 | # 37 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 38 | # Packages/ 39 | # Package.pins 40 | .build/ 41 | 42 | # CocoaPods 43 | # 44 | # We recommend against adding the Pods directory to your .gitignore. However 45 | # you should judge for yourself, the pros and cons are mentioned at: 46 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 47 | # 48 | # Pods/ 49 | 50 | # Carthage 51 | # 52 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 53 | Carthage/ 54 | 55 | # fastlane 56 | # 57 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 58 | # screenshots whenever they are needed. 59 | # For more information about the recommended setup visit: 60 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 61 | 62 | fastlane/report.xml 63 | fastlane/Preview.html 64 | fastlane/screenshots 65 | fastlane/test_output 66 | -------------------------------------------------------------------------------- /.swiftlint.yml: -------------------------------------------------------------------------------- 1 | disabled_rules: # rule identifiers to exclude from running 2 | - colon 3 | # - comma 4 | - control_statement 5 | - trailing_whitespace 6 | - file_length 7 | opt_in_rules: # some rules are only opt-in 8 | - empty_count 9 | # Find all the available rules by running: 10 | # swiftlint rules 11 | included: # paths to include during linting. `--path` is ignored if present. 12 | - ZVProgressHUD 13 | excluded: # paths to ignore during linting. Takes precedence over `included`. 14 | - Carthage 15 | - Pods 16 | - Source/ExcludedFolder 17 | - Source/ExcludedFile.swift 18 | - Source/*/ExcludedFile.swift # Exclude files with a wildcard 19 | analyzer_rules: # Rules run by `swiftlint analyze` (experimental) 20 | - explicit_self 21 | 22 | # configurable rules can be customized from this configuration file 23 | # binary rules can set their severity level 24 | force_cast: warning # implicitly 25 | force_try: 26 | severity: warning # explicitly 27 | # rules that have both warning and error levels, can set just the warning level 28 | # implicitly 29 | line_length: 120 30 | # they can set both implicitly with an array 31 | type_body_length: 32 | - 300 # warning 33 | - 400 # error 34 | # or they can set both explicitly 35 | #file_length: 36 | # warning: 800 37 | # error: 1200 38 | function_body_length: 39 | warning: 60 40 | error: 80 41 | 42 | # naming rules can set warnings/errors for min_length and max_length 43 | # additionally they can set excluded names 44 | type_name: 45 | min_length: 3 # only warning 46 | max_length: # warning and error 47 | warning: 40 48 | error: 50 49 | excluded: iPhone # excluded via string 50 | identifier_name: 51 | min_length: # only min_length 52 | error: 3 # only error 53 | excluded: # excluded via string array 54 | - id 55 | - URL 56 | - GlobalAPIKey 57 | reporter: "xcode" # reporter type (xcode, json, csv, checkstyle, junit, html, emoji, sonarqube, markdown) 58 | 59 | -------------------------------------------------------------------------------- /ZVProgressHUDExample/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 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /ZVProgressHUDExample/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // ZVProgressHUDExample 4 | // 5 | // Created by zevwings on 12/02/2018. 6 | // Copyright © 2017-2019 zevwings. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(_ application: UIApplication) { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(_ application: UIApplication) { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(_ application: UIApplication) { 33 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(_ application: UIApplication) { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | func applicationWillTerminate(_ application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /ZVProgressHUDExample/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "filename" : "Icon-20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "idiom" : "iphone", 11 | "size" : "20x20", 12 | "filename" : "Icon-20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-29@2x.png", 19 | "scale" : "2x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-29@3x.png", 25 | "scale" : "3x" 26 | }, 27 | { 28 | "size" : "40x40", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-40@2x.png", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-40@3x.png", 37 | "scale" : "3x" 38 | }, 39 | { 40 | "size" : "60x60", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-60@2x.png", 43 | "scale" : "2x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-60@3x.png", 49 | "scale" : "3x" 50 | }, 51 | { 52 | "idiom" : "ipad", 53 | "size" : "20x20", 54 | "filename" : "Icon-20.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "idiom" : "ipad", 59 | "size" : "20x20", 60 | "filename" : "Icon-20@2x.png", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "size" : "29x29", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-29.png", 67 | "scale" : "1x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-29@2x.png", 73 | "scale" : "2x" 74 | }, 75 | { 76 | "size" : "40x40", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-40.png", 79 | "scale" : "1x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-40@2x.png", 85 | "scale" : "2x" 86 | }, 87 | { 88 | "size" : "76x76", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-76.png", 91 | "scale" : "1x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-76@2x.png", 97 | "scale" : "2x" 98 | }, 99 | { 100 | "size" : "83.5x83.5", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-83_5@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "idiom" : "ios-marketing", 107 | "size" : "1024x1024", 108 | "filename" : "ios-marketing.png", 109 | "scale" : "1x" 110 | } 111 | ], 112 | "info" : { 113 | "version" : 1, 114 | "author" : "xcode" 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /ZVProgressHUD.xcodeproj/xcshareddata/xcschemes/ZVProgressHUD.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 42 | 48 | 49 | 50 | 51 | 52 | 62 | 63 | 69 | 70 | 71 | 72 | 78 | 79 | 85 | 86 | 87 | 88 | 90 | 91 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /ZVProgressHUD/ZVProgressView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ZVProgressView.swift 3 | // ZVProgressHUD 4 | // 5 | // Created by zevwings on 2017/7/13. 6 | // Copyright © 2017-2019 zevwings. All rights reserved. 7 | // 8 | 9 | #if !os(macOS) 10 | 11 | import UIKit 12 | 13 | class ZVProgressView: UIView { 14 | 15 | var strokeWidth: CGFloat = 3.0 { 16 | didSet { 17 | foregroundLayer.lineWidth = strokeWidth 18 | backgroundLayer.lineWidth = strokeWidth 19 | } 20 | } 21 | 22 | var progressBackgroundColor: UIColor = UIColor.black.withAlphaComponent(0.5) { 23 | didSet { 24 | backgroundLayer.strokeColor = progressBackgroundColor.cgColor 25 | } 26 | } 27 | 28 | var progressForegroundColor: UIColor = .black { 29 | didSet { 30 | foregroundLayer.strokeColor = progressForegroundColor.cgColor 31 | } 32 | } 33 | 34 | var progressLabelColor: UIColor = .black { 35 | didSet { 36 | progressLabel.textColor = progressLabelColor 37 | } 38 | } 39 | 40 | var font: UIFont = .systemFont(ofSize: 12) { 41 | didSet { 42 | progressLabel.font = font 43 | } 44 | } 45 | 46 | var isProgressLabelHidden: Bool = false { 47 | didSet { 48 | progressLabel.isHidden = isProgressLabelHidden 49 | } 50 | } 51 | 52 | var progress: Float = 0.0 { 53 | didSet { 54 | foregroundLayer.strokeEnd = CGFloat(progress) 55 | setNeedsDisplay() 56 | } 57 | } 58 | 59 | private lazy var progressLabel : UILabel = { 60 | let label = UILabel() 61 | label.textColor = progressLabelColor 62 | label.font = font 63 | label.textAlignment = .center 64 | label.frame = bounds 65 | return label 66 | }() 67 | 68 | private lazy var foregroundLayer: CAShapeLayer = { 69 | 70 | let foregroundLayer = CAShapeLayer() 71 | foregroundLayer.lineCap = .round 72 | foregroundLayer.lineWidth = strokeWidth 73 | foregroundLayer.frame = bounds 74 | foregroundLayer.fillColor = UIColor.clear.cgColor 75 | foregroundLayer.strokeStart = 0.0 76 | foregroundLayer.strokeEnd = 0.0 77 | 78 | return foregroundLayer 79 | }() 80 | 81 | private lazy var backgroundLayer: CAShapeLayer = { 82 | 83 | let backgroundLayer = CAShapeLayer() 84 | backgroundLayer.lineCap = .round 85 | backgroundLayer.lineWidth = strokeWidth 86 | backgroundLayer.frame = bounds 87 | backgroundLayer.fillColor = UIColor.clear.cgColor 88 | backgroundLayer.strokeStart = 0.0 89 | backgroundLayer.strokeEnd = 1.0 90 | 91 | return backgroundLayer 92 | }() 93 | 94 | override init(frame: CGRect) { 95 | super.init(frame: frame) 96 | 97 | addSubview(progressLabel) 98 | layer.addSublayer(backgroundLayer) 99 | layer.addSublayer(foregroundLayer) 100 | layer.masksToBounds = true 101 | } 102 | 103 | required init?(coder aDecoder: NSCoder) { 104 | fatalError("init(coder:) has not been implemented") 105 | } 106 | 107 | override func layoutSubviews() { 108 | super.layoutSubviews() 109 | 110 | backgroundColor = .clear 111 | 112 | let rect = CGRect(x: 0, y: 0, width: frame.width, height: frame.height) 113 | foregroundLayer.frame = rect 114 | backgroundLayer.frame = rect 115 | progressLabel.frame = rect 116 | prepare() 117 | } 118 | 119 | private func prepare() { 120 | 121 | let arcCenter = CGPoint(x: self.frame.width / 2.0, y: self.frame.height / 2.0) 122 | let radius = (min(self.bounds.height, self.bounds.width) - self.strokeWidth) / 2.0 123 | let startAngle = -CGFloat.pi / 2 124 | let endAngle = CGFloat.pi * 3 / 2 125 | 126 | let bezierPath = UIBezierPath( 127 | arcCenter: arcCenter, 128 | radius: radius, 129 | startAngle: startAngle, 130 | endAngle: endAngle, 131 | clockwise: true 132 | ) 133 | 134 | foregroundLayer.path = bezierPath.cgPath 135 | backgroundLayer.path = bezierPath.cgPath 136 | 137 | } 138 | 139 | func updateProgress(_ progress: Float) { 140 | 141 | CATransaction.begin() 142 | CATransaction.setAnimationTimingFunction(CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)) 143 | CATransaction.setAnimationDuration(0.15) 144 | foregroundLayer.strokeEnd = CGFloat(progress) 145 | progressLabel.text = "\(Int(progress * 100))%" 146 | CATransaction.commit() 147 | } 148 | } 149 | 150 | #endif 151 | -------------------------------------------------------------------------------- /README_CN.md: -------------------------------------------------------------------------------- 1 | # ZVProgressHUD 2 | ![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)[](https://github.com/Carthage/Carthage) 3 | ![CocoaPods Compatible](https://img.shields.io/badge/pod-1.0.0-4BC51D.svg?style=flat)[](https://cocoapods.org) 4 | ![Platform](https://img.shields.io/badge/platform-ios-9F9F9F.svg)[](http://cocoadocs.org/docsets/Alamofire) 5 | 6 | 7 | `ZVProgressHUD` 是用纯`swift`开发,简单易用的提示工具。 8 | 9 | ## 版本支持 10 | 11 | - iOS 8.0+ 12 | - Swift 4.0 13 | 14 | ## 安装 15 | ### Cocoapod 16 | [CocoaPods](https://cocoapods.org) is a dependency manager for Swift and Objective-C Cocoa projects. 17 | 18 | You can install Cocoapod with the following command 19 | 20 | ``` 21 | $ sudo gem install cocoapods 22 | ``` 23 | To integrate `ZVProgressHUD` into your project using CocoaPods, specify it into your `Podfile` 24 | 25 | ``` 26 | source 'https://github.com/CocoaPods/Specs.git' 27 | platform :ios, '8.0' 28 | 29 | target 'TargetName' do 30 | use_frameworks! 31 |    pod 'ZVProgressHUD', :git => 'https://github.com/zevwings/ZVProgressHUD.git' 32 | end 33 | ``` 34 | 35 | Then,install your dependencies with [CocoaPods](https://cocoapods.org). 36 | 37 | ``` 38 | $ pod install 39 | ``` 40 | ### Carthage 41 | 42 | [Carthage](https://github.com/Carthage/Carthage) is intended to be the simplest way to add frameworks to your application. 43 | 44 | You can install Carthage with [Homebrew](https://brew.sh) using following command: 45 | 46 | ``` 47 | $ brew update 48 | $ brew install carthage 49 | ``` 50 | 51 | To integrate `ZVProgressHUD` into your project using Carthage, specify it into your `Cartfile` 52 | 53 | ``` 54 | github "zevwings/ZVProgressHUD" ~> 0.0.1 55 | ``` 56 | 57 | Then,build the framework with Carthage 58 | using `carthage update` and drag `ZVProgressHUD.framework` into your project. 59 | 60 | #### Note: 61 | The framework is under the Carthage/Build, and you should drag it into `Target` -> `Genral` -> `Embedded Binaries` 62 | 63 | ## 使用方法 64 | 当你在需要使用`ZVProgressHUD `使用`import ZVProgressHUD`导入即可。 65 | 66 | ### 任务提示 67 | 当你需要任务提示时,使用如下代码即可 68 | 69 | ``` 70 | ZVProgressHUD.show() 71 | ``` 72 | 73 | 通过如下代码自定义动画类型 74 | 75 | ``` 76 | /// 动画类型,默认为 .flat 77 | public enum AnimationType { 78 | //使用自定义`ZVActivityIndicator` 79 | case flat 80 | //使用系统自带`UIActivityIndicator` 81 | case native 82 | } 83 | 84 | /// 你可以通过类属性修改动画类型 85 | ZVProgressHUD.animationType = .flat 86 | ``` 87 | 88 | 当你需要改变`ZVProgressHUD`的显示父视图时,只需要在调用`show`方法时,指定父视图即可 89 | 90 | ``` 91 | // 你也可以延迟视图显示,通过`delay`参数 92 | ZVProgressHUD.show(with: "正在加载", in: superview, delay: 0.0) 93 | ``` 94 | 95 | ### 关闭提示 96 | 当你需要关闭任务提示时,使用如下代码即可 97 | 98 | ``` 99 | ZVProgressHUD.dismiss() 100 | ``` 101 | 102 | ### 展示一个确认信息 103 | 当需要展示任务确认信息时,调用如下方法 104 | 105 | ``` 106 | ZVProgressHUD.showError(with: "保存失败") 107 | ZVProgressHUD.showSuccess(with: "保存成功") 108 | ZVProgressHUD.showWarning(with: "存储信息有误") 109 | ``` 110 | 111 | ### 展示自定义图片 112 | 当你需要展示自定义图片时,可以使用如下方法 113 | 114 | ``` 115 | let image = UIImage(named: "smile") 116 | ZVProgressHUD.showImage(image!) 117 | // 或者 118 | ZVProgressHUD.showImage(image!, title: "微笑每一天") 119 | ``` 120 | 121 | ### 展示自定义动画 122 | 当你需要展示自定义动画时,可以使用如下方法 123 | 124 | ``` 125 | var images = [UIImage]() 126 | for index in 1 ... 3 { 127 | let image = UIImage(named: "loading_0\(index)") 128 | images.append(image!) 129 | } 130 | 131 | ZVProgressHUD.showAnimation(images) 132 | ``` 133 | 134 | ### 展示任务进度 135 | 136 | ``` 137 | ZVProgressHUD.showProgress(0.0, title: "任务进度") 138 | ``` 139 | 140 | ### 自定义属性 141 | 142 | ``` 143 | // 设置显示前景色、背景色 144 | class var displayStyle: DisplayStyle 145 | 146 | // 设置遮罩类型 147 | class var maskType: MaskType 148 | 149 | // 基础视图圆角 150 | class var cornerRadius: CGFloat 151 | 152 | // 基础视图的偏移量 153 | class var offset: UIOffset 154 | 155 | // 字体 156 | class var font: UIFont 157 | 158 | // 当动画类型为`flat`时,改变圆环宽度 159 | class var strokeWith: CGFloat 160 | 161 | // 指示视图大小 162 | class var indicatorSize: CGSize 163 | 164 | // 设置动画类型,默认为`flat` 165 | class var animationType: IndicatorView.AnimationType 166 | 167 | ``` 168 | 169 | ### 自定义边距 170 | 171 | ``` 172 | // 设置整体内容边距 173 | class var contentInsets: UIEdgeInsets 174 | 175 | // 设置文本边距 176 | class var titleEdgeInsets: UIEdgeInsets 177 | 178 | // 设置指示器边距 179 | class var indicatorEdgeInsets: UIEdgeInsets 180 | ``` 181 | 182 | ### 通知 183 | 184 | 你可以使用对应类型的通知,自定义相关操作。 185 | 186 | ``` 187 | extension NSNotification.Name { 188 | 189 | // 接受到点击时间 190 | public static let ZVProgressHUDReceivedTouchUpInsideEvent: Notification.Name 191 | 192 | // 视图将要展示 193 | public static let ZVProgressHUDWillAppear: Notification.Name 194 | 195 | // 视图完成展示 196 | public static let ZVProgressHUDDidAppear: Notification.Name 197 | 198 | // 视图将要消失 199 | public static let ZVProgressHUDWillDisappear: Notification.Name 200 | 201 | // 视图完成消失 202 | public static let ZVProgressHUDDidDisappear: Notification.Name 203 | } 204 | ``` 205 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ZVProgressHUD 2 | ![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)[](https://github.com/Carthage/Carthage) 3 | ![CocoaPods Compatible](https://img.shields.io/badge/pod-1.0.0-4BC51D.svg?style=flat)[](https://cocoapods.org) 4 | ![Platform](https://img.shields.io/badge/platform-ios-9F9F9F.svg)[](http://cocoadocs.org/docsets/Alamofire) 5 | 6 | 7 | ZVProgressHUD is a pure-swift and wieldy HUD. 8 | 9 | [中文文档](https://github.com/zevwings/ZVProgressHUD/blob/master/README_CN.md) 10 | 11 | ## Requirements 12 | 13 | - iOS 8.0+ 14 | - Swift 5.0 15 | 16 | ## Appetize 17 | You can run this demo at [Appetize](https://appetize.io/embed/39txw9h5d7mrkckm6f9vp9mn2r?device=iphone5s&scale=100&autoplay=false&orientation=portrait&deviceColor=white) 18 | 19 | 20 | ## Installation 21 | ### Cocoapod 22 | [CocoaPods](https://cocoapods.org) is a dependency manager for Swift and Objective-C Cocoa projects. 23 | 24 | You can install Cocoapod with the following command 25 | 26 | ``` 27 | $ sudo gem install cocoapods 28 | ``` 29 | To integrate `ZVProgressHUD` into your project using CocoaPods, specify it into your `Podfile` 30 | 31 | ``` 32 | source 'https://github.com/CocoaPods/Specs.git' 33 | platform :ios, '8.0' 34 | 35 | target 'TargetName' do 36 | use_frameworks! 37 |    pod 'ZVProgressHUD', '~> 2.0.0' 38 | end 39 | ``` 40 | 41 | Then,install your dependencies with [CocoaPods](https://cocoapods.org). 42 | 43 | ``` 44 | $ pod install 45 | ``` 46 | ### Carthage 47 | 48 | [Carthage](https://github.com/Carthage/Carthage) is intended to be the simplest way to add frameworks to your application. 49 | 50 | You can install Carthage with [Homebrew](https://brew.sh) using following command: 51 | 52 | ``` 53 | $ brew update 54 | $ brew install carthage 55 | ``` 56 | 57 | To integrate `ZVProgressHUD` into your project using Carthage, specify it into your `Cartfile` 58 | 59 | ``` 60 | github "zevwings/ZVProgressHUD" ~> 0.0.1 61 | ``` 62 | 63 | Then,build the framework with Carthage 64 | using `carthage update` and drag `ZVProgressHUD.framework` into your project. 65 | 66 | #### Note: 67 | The framework is under the Carthage/Build, and you should drag it into `Target` -> `Genral` -> `Embedded Binaries` 68 | 69 | ## Usage 70 | You can use `import ProgressHUD` when you needed to use `ZVProgressHUD`. 71 | 72 | ### Showing a HUD 73 | When you start a task, You can using following code: 74 | 75 | ``` 76 | // class method 77 | ProgressHUD.shared.show() 78 | // or you can use instance method 79 | let hud = ProgressHUD() 80 | hud.show() 81 | ``` 82 | 83 | you can custom animation type, use following code: 84 | 85 | ``` 86 | /// the animation type, default is flat 87 | public enum AnimationType { 88 | case flat 89 | case native 90 | } 91 | 92 | /// this code will modify global animation type. 93 | ProgressHUD.shared.animationType = .flat 94 | ``` 95 | 96 | when you want modify the superview of `ZVProgressHUD`, use the following code: 97 | 98 | ``` 99 | // the HUD will show delay 0.0 100 | ZVProgressHUD.show(with: "Loading", in: superview, delay: 0.0) 101 | ``` 102 | 103 | ### Dismiss a HUD 104 | you can use a simple code to close HUD. 105 | 106 | ``` 107 | // class method 108 | ProgressHUD.shared.dismiss() 109 | // or you can use instance method 110 | hud.dismiss() 111 | ``` 112 | 113 | ### Showing a confirm 114 | when you want show a comfirm infomation, use the following code: 115 | 116 | ``` 117 | ProgressHUD.shared.showError(with: "error") 118 | ProgressHUD.shared.showSuccess(with: "success") 119 | ProgressHUD.shared.showWarning(with: "warning") 120 | ``` 121 | 122 | ### Showing a custom image 123 | you also can show a custom image, use the following code: 124 | 125 | ``` 126 | let image = UIImage(named: "smile") 127 | ProgressHUD.shared.showImage(image!) 128 | // or 129 | ProgressHUD.shared.showImage(image!, title: "smile everyday!") 130 | ``` 131 | 132 | ### Showing a custom animation 133 | you can use the following code to custom a animation indicator. 134 | 135 | ``` 136 | var images = [UIImage]() 137 | for index in 1 ... 3 { 138 | let image = UIImage(named: "loading_0\(index)") 139 | images.append(image!) 140 | } 141 | 142 | ProgressHUD.shared.showAnimation(images) 143 | ``` 144 | 145 | ### Showing a progress 146 | 147 | ``` 148 | ProgressHUD.shared.showProgress(0.0, title: "Progress") 149 | ``` 150 | 151 | ### Custom logo 152 | 153 | ``` 154 | // set logoSize of HUD, CGSize(30, 30) 155 | class var logoSize: CGSize 156 | // set logo image of HUD, default is nil 157 | class var logo: UIImage 158 | ``` 159 | 160 | ### Custom properties 161 | 162 | ``` 163 | // set displayStyle type of HUD, default is dark. 164 | class var displayStyle: DisplayStyle 165 | 166 | // set mask type of HUD 167 | class var maskType: MaskType 168 | 169 | // the cornerRadius of basic view 170 | class var cornerRadius: CGFloat 171 | 172 | // the offset of basic view 173 | class var offset: UIOffset 174 | 175 | // the font of title label 176 | class var font: UIFont 177 | 178 | // you can change the line width of indicator when animation type is `flat` 179 | class var strokeWith: CGFloat 180 | 181 | // the size of indicator 182 | class var indicatorSize: CGSize 183 | 184 | // the animation type, default is `flat` 185 | class var animationType: IndicatorView.AnimationType 186 | 187 | ``` 188 | 189 | ### Custom Insets of content 190 | 191 | ``` 192 | class var contentInsets: UIEdgeInsets 193 | 194 | class var titleEdgeInsets: UIEdgeInsets 195 | 196 | class var indicatorEdgeInsets: UIEdgeInsets 197 | ``` 198 | 199 | ### Notifications 200 | 201 | you can add an observer to do something from hud's notifications. 202 | 203 | ``` 204 | extension NSNotification.Name { 205 | 206 | // this hud did disappear 207 | public static let ProgressHUDReceivedTouchUpInsideEvent: Notification.Name 208 | 209 | // this hud will appear 210 | public static let ProgressHUDWillAppear: Notification.Name 211 | 212 | // this hud did appear 213 | public static let ProgressHUDDidAppear: Notification.Name 214 | 215 | // this hud will disappear 216 | public static let ProgressHUDWillDisappear: Notification.Name 217 | 218 | // this hud did disappear 219 | public static let ProgressHUDDidDisappear: Notification.Name 220 | } 221 | ``` 222 | 223 | ## License 224 | `ZVProgressHUD` distributed under the terms and conditions of the [MIT License](https://github.com/zevwings/ZVProgressHUD/blob/master/LICENSE) 225 | 226 | 227 | 228 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | CFPropertyList (3.0.4) 5 | rexml 6 | addressable (2.8.0) 7 | public_suffix (>= 2.0.2, < 5.0) 8 | artifactory (3.0.15) 9 | atomos (0.1.3) 10 | aws-eventstream (1.2.0) 11 | aws-partitions (1.519.0) 12 | aws-sdk-core (3.121.3) 13 | aws-eventstream (~> 1, >= 1.0.2) 14 | aws-partitions (~> 1, >= 1.239.0) 15 | aws-sigv4 (~> 1.1) 16 | jmespath (~> 1.0) 17 | aws-sdk-kms (1.50.0) 18 | aws-sdk-core (~> 3, >= 3.121.2) 19 | aws-sigv4 (~> 1.1) 20 | aws-sdk-s3 (1.104.0) 21 | aws-sdk-core (~> 3, >= 3.121.2) 22 | aws-sdk-kms (~> 1) 23 | aws-sigv4 (~> 1.4) 24 | aws-sigv4 (1.4.0) 25 | aws-eventstream (~> 1, >= 1.0.2) 26 | babosa (1.0.4) 27 | claide (1.0.3) 28 | colored (1.2) 29 | colored2 (3.1.2) 30 | commander (4.6.0) 31 | highline (~> 2.0.0) 32 | declarative (0.0.20) 33 | digest-crc (0.6.4) 34 | rake (>= 12.0.0, < 14.0.0) 35 | domain_name (0.5.20190701) 36 | unf (>= 0.0.5, < 1.0.0) 37 | dotenv (2.7.6) 38 | emoji_regex (3.2.3) 39 | excon (0.87.0) 40 | faraday (1.8.0) 41 | faraday-em_http (~> 1.0) 42 | faraday-em_synchrony (~> 1.0) 43 | faraday-excon (~> 1.1) 44 | faraday-httpclient (~> 1.0.1) 45 | faraday-net_http (~> 1.0) 46 | faraday-net_http_persistent (~> 1.1) 47 | faraday-patron (~> 1.0) 48 | faraday-rack (~> 1.0) 49 | multipart-post (>= 1.2, < 3) 50 | ruby2_keywords (>= 0.0.4) 51 | faraday-cookie_jar (0.0.7) 52 | faraday (>= 0.8.0) 53 | http-cookie (~> 1.0.0) 54 | faraday-em_http (1.0.0) 55 | faraday-em_synchrony (1.0.0) 56 | faraday-excon (1.1.0) 57 | faraday-httpclient (1.0.1) 58 | faraday-net_http (1.0.1) 59 | faraday-net_http_persistent (1.2.0) 60 | faraday-patron (1.0.0) 61 | faraday-rack (1.0.0) 62 | faraday_middleware (1.2.0) 63 | faraday (~> 1.0) 64 | fastimage (2.2.5) 65 | fastlane (2.197.0) 66 | CFPropertyList (>= 2.3, < 4.0.0) 67 | addressable (>= 2.8, < 3.0.0) 68 | artifactory (~> 3.0) 69 | aws-sdk-s3 (~> 1.0) 70 | babosa (>= 1.0.3, < 2.0.0) 71 | bundler (>= 1.12.0, < 3.0.0) 72 | colored 73 | commander (~> 4.6) 74 | dotenv (>= 2.1.1, < 3.0.0) 75 | emoji_regex (>= 0.1, < 4.0) 76 | excon (>= 0.71.0, < 1.0.0) 77 | faraday (~> 1.0) 78 | faraday-cookie_jar (~> 0.0.6) 79 | faraday_middleware (~> 1.0) 80 | fastimage (>= 2.1.0, < 3.0.0) 81 | gh_inspector (>= 1.1.2, < 2.0.0) 82 | google-apis-androidpublisher_v3 (~> 0.3) 83 | google-apis-playcustomapp_v1 (~> 0.1) 84 | google-cloud-storage (~> 1.31) 85 | highline (~> 2.0) 86 | json (< 3.0.0) 87 | jwt (>= 2.1.0, < 3) 88 | mini_magick (>= 4.9.4, < 5.0.0) 89 | multipart-post (~> 2.0.0) 90 | naturally (~> 2.2) 91 | optparse (~> 0.1.1) 92 | plist (>= 3.1.0, < 4.0.0) 93 | rubyzip (>= 2.0.0, < 3.0.0) 94 | security (= 0.1.3) 95 | simctl (~> 1.6.3) 96 | terminal-notifier (>= 2.0.0, < 3.0.0) 97 | terminal-table (>= 1.4.5, < 2.0.0) 98 | tty-screen (>= 0.6.3, < 1.0.0) 99 | tty-spinner (>= 0.8.0, < 1.0.0) 100 | word_wrap (~> 1.0.0) 101 | xcodeproj (>= 1.13.0, < 2.0.0) 102 | xcpretty (~> 0.3.0) 103 | xcpretty-travis-formatter (>= 0.0.3) 104 | gh_inspector (1.1.3) 105 | google-apis-androidpublisher_v3 (0.12.0) 106 | google-apis-core (>= 0.4, < 2.a) 107 | google-apis-core (0.4.1) 108 | addressable (~> 2.5, >= 2.5.1) 109 | googleauth (>= 0.16.2, < 2.a) 110 | httpclient (>= 2.8.1, < 3.a) 111 | mini_mime (~> 1.0) 112 | representable (~> 3.0) 113 | retriable (>= 2.0, < 4.a) 114 | rexml 115 | webrick 116 | google-apis-iamcredentials_v1 (0.7.0) 117 | google-apis-core (>= 0.4, < 2.a) 118 | google-apis-playcustomapp_v1 (0.5.0) 119 | google-apis-core (>= 0.4, < 2.a) 120 | google-apis-storage_v1 (0.8.0) 121 | google-apis-core (>= 0.4, < 2.a) 122 | google-cloud-core (1.6.0) 123 | google-cloud-env (~> 1.0) 124 | google-cloud-errors (~> 1.0) 125 | google-cloud-env (1.5.0) 126 | faraday (>= 0.17.3, < 2.0) 127 | google-cloud-errors (1.2.0) 128 | google-cloud-storage (1.34.1) 129 | addressable (~> 2.5) 130 | digest-crc (~> 0.4) 131 | google-apis-iamcredentials_v1 (~> 0.1) 132 | google-apis-storage_v1 (~> 0.1) 133 | google-cloud-core (~> 1.6) 134 | googleauth (>= 0.16.2, < 2.a) 135 | mini_mime (~> 1.0) 136 | googleauth (1.1.0) 137 | faraday (>= 0.17.3, < 2.0) 138 | jwt (>= 1.4, < 3.0) 139 | memoist (~> 0.16) 140 | multi_json (~> 1.11) 141 | os (>= 0.9, < 2.0) 142 | signet (>= 0.16, < 2.a) 143 | highline (2.0.3) 144 | http-cookie (1.0.4) 145 | domain_name (~> 0.5) 146 | httpclient (2.8.3) 147 | jmespath (1.4.0) 148 | json (2.6.1) 149 | jwt (2.3.0) 150 | memoist (0.16.2) 151 | mini_magick (4.11.0) 152 | mini_mime (1.1.2) 153 | multi_json (1.15.0) 154 | multipart-post (2.0.0) 155 | nanaimo (0.3.0) 156 | naturally (2.2.1) 157 | optparse (0.1.1) 158 | os (1.1.1) 159 | plist (3.6.0) 160 | public_suffix (4.0.6) 161 | rake (13.0.6) 162 | representable (3.1.1) 163 | declarative (< 0.1.0) 164 | trailblazer-option (>= 0.1.1, < 0.2.0) 165 | uber (< 0.2.0) 166 | retriable (3.1.2) 167 | rexml (3.2.5) 168 | rouge (2.0.7) 169 | ruby2_keywords (0.0.5) 170 | rubyzip (2.3.2) 171 | security (0.1.3) 172 | signet (0.16.0) 173 | addressable (~> 2.8) 174 | faraday (>= 0.17.3, < 2.0) 175 | jwt (>= 1.5, < 3.0) 176 | multi_json (~> 1.10) 177 | simctl (1.6.8) 178 | CFPropertyList 179 | naturally 180 | terminal-notifier (2.0.0) 181 | terminal-table (1.8.0) 182 | unicode-display_width (~> 1.1, >= 1.1.1) 183 | trailblazer-option (0.1.1) 184 | tty-cursor (0.7.1) 185 | tty-screen (0.8.1) 186 | tty-spinner (0.9.3) 187 | tty-cursor (~> 0.7) 188 | uber (0.1.0) 189 | unf (0.1.4) 190 | unf_ext 191 | unf_ext (0.0.8) 192 | unicode-display_width (1.8.0) 193 | webrick (1.7.0) 194 | word_wrap (1.0.0) 195 | xcodeproj (1.21.0) 196 | CFPropertyList (>= 2.3.3, < 4.0) 197 | atomos (~> 0.1.3) 198 | claide (>= 1.0.2, < 2.0) 199 | colored2 (~> 3.1) 200 | nanaimo (~> 0.3.0) 201 | rexml (~> 3.2.4) 202 | xcpretty (0.3.0) 203 | rouge (~> 2.0.7) 204 | xcpretty-travis-formatter (1.0.1) 205 | xcpretty (~> 0.2, >= 0.0.7) 206 | 207 | PLATFORMS 208 | ruby 209 | 210 | DEPENDENCIES 211 | fastlane 212 | 213 | BUNDLED WITH 214 | 2.2.15 215 | -------------------------------------------------------------------------------- /ZVProgressHUDExample/ZVDownloadingView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ZVDownloadingView.swift 3 | // ZVProgressHUDExample 4 | // 5 | // Created by zevwings on 2020/12/22. 6 | // Copyright © 2020 zevwings. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import ZVProgressHUD 11 | 12 | class ZVDownloadingView: UIView { 13 | 14 | private lazy var containerView: UIView = { 15 | let view = UIView(frame: CGRect(x: 0, y: 28, width: 210, height: 104)) 16 | view.backgroundColor = .white 17 | view.layer.cornerRadius = 10 18 | return view 19 | }() 20 | 21 | private lazy var closeButton: UIButton = { 22 | let button = UIButton() 23 | button.setImage(UIImage(named: "close"), for: .normal) 24 | button.contentMode = .topRight 25 | button.addTarget(self, action: #selector(closeButonClicked(_:)), for: .touchUpInside) 26 | button.imageEdgeInsets = UIEdgeInsets(top: 12, left: 0, bottom: 0, right: 12) 27 | return button 28 | }() 29 | 30 | private lazy var progressView: ZVProgressView = { 31 | let view = ZVProgressView(frame: CGRect(x: 76, y: 42, width: 58, height: 58)) 32 | view.strokeColor = UIColor(red: 0.90, green: 0, blue: 0.27, alpha: 1) 33 | view.progressLabelColor = UIColor(red: 0.20, green: 0.20, blue: 0.20, alpha: 1) 34 | view.font = .systemFont(ofSize: 14.0, weight: .semibold) 35 | return view 36 | }() 37 | 38 | private lazy var describeLabel: UILabel = { 39 | let label = UILabel(frame: CGRect(x: 20, y: 44, width: 170, height: 20)) 40 | label.textColor = UIColor(red: 0.20, green: 0.20, blue: 0.20, alpha: 1) 41 | label.font = .systemFont(ofSize: 14.0, weight: .regular) 42 | label.textAlignment = .center 43 | return label 44 | }() 45 | 46 | init() { 47 | super.init(frame: CGRect(x: 0, y: 0, width: 210, height: 160)) 48 | 49 | addSubview(containerView) 50 | 51 | containerView.frame = CGRect(x: 0, y: 28, width: 210, height: 104) 52 | containerView.addSubview(closeButton) 53 | closeButton.frame = CGRect(x: 166, y: 0, width: 44, height: 44) 54 | containerView.addSubview(describeLabel) 55 | describeLabel.frame = CGRect(x: 42, y: 44, width: 126.0, height: 20) 56 | } 57 | 58 | required init?(coder: NSCoder) { 59 | fatalError("init(coder:) has not been implemented") 60 | } 61 | 62 | func start() { 63 | containerView.frame = CGRect(x: 0, y: 0, width: 210, height: 160) 64 | containerView.addSubview(progressView) 65 | progressView.frame = CGRect(x: 76, y: 42, width: 58, height: 58) 66 | describeLabel.frame = CGRect(x: 63, y: 111, width: 84, height: 20) 67 | } 68 | 69 | func update(_ progress: Float) { 70 | describeLabel.text = "Progress \("\(Int(progress * 100))%")" 71 | progressView.updateProgress(progress) 72 | } 73 | 74 | func show(with title: String) { 75 | describeLabel.text = title 76 | } 77 | 78 | func dismiss() { 79 | progressView.removeFromSuperview() 80 | containerView.frame = CGRect(x: 0, y: 28, width: 210, height: 104) 81 | describeLabel.frame = CGRect(x: 42, y: 44, width: 126.0, height: 20) 82 | } 83 | 84 | @objc private func closeButonClicked(_ sender: Any) { 85 | dismiss() 86 | ZVProgressHUD.dismiss() 87 | 88 | } 89 | } 90 | 91 | private class ZVProgressView: UIView { 92 | 93 | var strokeWidth: CGFloat = 3.0 { 94 | didSet { 95 | foregroundLayer.lineWidth = strokeWidth 96 | backgroundLayer.lineWidth = strokeWidth 97 | } 98 | } 99 | 100 | var strokeColor: UIColor = .black { 101 | didSet { 102 | foregroundLayer.strokeColor = strokeColor.cgColor 103 | backgroundLayer.strokeColor = strokeColor.withAlphaComponent(0.5).cgColor 104 | } 105 | } 106 | 107 | var progressLabelColor: UIColor = .black { 108 | didSet { 109 | progressLabel.textColor = progressLabelColor 110 | } 111 | } 112 | 113 | var font: UIFont = .systemFont(ofSize: 12) { 114 | didSet { 115 | progressLabel.font = font 116 | } 117 | } 118 | 119 | var isProgressLabelHidden: Bool = false { 120 | didSet { 121 | progressLabel.isHidden = isProgressLabelHidden 122 | } 123 | } 124 | 125 | var progress: Float = 0.0 { 126 | didSet { 127 | foregroundLayer.strokeEnd = CGFloat(progress) 128 | setNeedsDisplay() 129 | } 130 | } 131 | 132 | private lazy var progressLabel : UILabel = { 133 | let label = UILabel() 134 | label.textColor = strokeColor 135 | label.font = font 136 | label.textAlignment = .center 137 | label.frame = bounds 138 | return label 139 | }() 140 | 141 | private lazy var foregroundLayer: CAShapeLayer = { 142 | 143 | let foregroundLayer = CAShapeLayer() 144 | foregroundLayer.lineCap = .round 145 | foregroundLayer.lineWidth = strokeWidth 146 | foregroundLayer.frame = bounds 147 | foregroundLayer.fillColor = UIColor.clear.cgColor 148 | foregroundLayer.strokeStart = 0.0 149 | foregroundLayer.strokeEnd = 0.0 150 | 151 | return foregroundLayer 152 | }() 153 | 154 | private lazy var backgroundLayer: CAShapeLayer = { 155 | 156 | let backgroundLayer = CAShapeLayer() 157 | backgroundLayer.lineCap = .round 158 | backgroundLayer.lineWidth = strokeWidth 159 | backgroundLayer.frame = bounds 160 | backgroundLayer.fillColor = UIColor.clear.cgColor 161 | backgroundLayer.strokeStart = 0.0 162 | backgroundLayer.strokeEnd = 1.0 163 | 164 | return backgroundLayer 165 | }() 166 | 167 | override init(frame: CGRect) { 168 | super.init(frame: frame) 169 | 170 | addSubview(progressLabel) 171 | layer.addSublayer(backgroundLayer) 172 | layer.addSublayer(foregroundLayer) 173 | layer.masksToBounds = true 174 | } 175 | 176 | required init?(coder aDecoder: NSCoder) { 177 | fatalError("init(coder:) has not been implemented") 178 | } 179 | 180 | override func layoutSubviews() { 181 | super.layoutSubviews() 182 | 183 | backgroundColor = .clear 184 | 185 | let rect = CGRect(x: 0, y: 0, width: frame.width, height: frame.height) 186 | foregroundLayer.frame = rect 187 | backgroundLayer.frame = rect 188 | progressLabel.frame = rect 189 | prepare() 190 | } 191 | 192 | private func prepare() { 193 | 194 | let arcCenter = CGPoint(x: self.frame.width / 2.0, y: self.frame.height / 2.0) 195 | let radius = (min(self.bounds.height, self.bounds.width) - self.strokeWidth * 2) / 2.0 196 | let startAngle = -CGFloat.pi / 2 197 | let endAngle = CGFloat.pi * 3 / 2 198 | 199 | let bezierPath = UIBezierPath( 200 | arcCenter: arcCenter, 201 | radius: radius, 202 | startAngle: startAngle, 203 | endAngle: endAngle, 204 | clockwise: true 205 | ) 206 | 207 | foregroundLayer.path = bezierPath.cgPath 208 | backgroundLayer.path = bezierPath.cgPath 209 | 210 | } 211 | 212 | func updateProgress(_ progress: Float) { 213 | 214 | CATransaction.begin() 215 | CATransaction.setAnimationTimingFunction(CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)) 216 | CATransaction.setAnimationDuration(0.15) 217 | foregroundLayer.strokeEnd = CGFloat(progress) 218 | progressLabel.text = "\(Int(progress * 100))%" 219 | CATransaction.commit() 220 | } 221 | } 222 | 223 | -------------------------------------------------------------------------------- /ZVProgressHUD/ZVIndicatorView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ZVStateView.swift 3 | // ZVProgressHUD 4 | // 5 | // Created by zevwings on 2017/7/13. 6 | // Copyright © 2017-2019 zevwings. All rights reserved. 7 | // 8 | 9 | #if !os(macOS) 10 | 11 | import UIKit 12 | import ZVActivityIndicatorView 13 | 14 | public class ZVIndicatorView: UIView { 15 | 16 | public enum AnimationType { 17 | case flat 18 | case native 19 | } 20 | 21 | public enum IndicatorType { 22 | case none 23 | case error, success, warning 24 | case indicator(style: AnimationType) 25 | case progress(value: Float) 26 | case image(value: UIImage, dismissAtomically: Bool) 27 | case animation(value: [UIImage], duration: TimeInterval) 28 | } 29 | 30 | var strokeWidth: CGFloat = 3.0 { 31 | didSet { 32 | flatActivityIndicatorView?.strokeWidth = strokeWidth 33 | progressIndicatorView?.strokeWidth = strokeWidth 34 | } 35 | } 36 | 37 | var progressForegroundColor: UIColor = .black { 38 | didSet { 39 | progressIndicatorView?.progressForegroundColor = progressForegroundColor 40 | } 41 | } 42 | 43 | var progressBackgroundColor: UIColor = .black { 44 | didSet { 45 | progressIndicatorView?.progressBackgroundColor = progressBackgroundColor 46 | } 47 | } 48 | 49 | var progressLabelFont : UIFont = .systemFont(ofSize: 12) { 50 | didSet { 51 | progressIndicatorView?.font = progressLabelFont 52 | } 53 | } 54 | 55 | var progressLabelColor: UIColor = .black { 56 | didSet { 57 | progressIndicatorView?.progressLabelColor = progressLabelColor 58 | } 59 | } 60 | 61 | var isProgressLabelHidden: Bool = false { 62 | didSet { 63 | progressIndicatorView?.isProgressLabelHidden = isProgressLabelHidden 64 | } 65 | } 66 | 67 | var indcatorType: IndicatorType = .none { 68 | didSet { 69 | switch indcatorType { 70 | case .indicator(let style): 71 | switch (style) { 72 | case .native: 73 | configNativeActivityIndicatorView() 74 | case .flat: 75 | configFlatActivityIndicatorView() 76 | } 77 | case .progress(let value): 78 | configProgressIndicatorView(with: value) 79 | case .error, .success, .warning: 80 | configImageIndicatorView(indcatorType.resource) 81 | case .image(let value, _): 82 | configImageIndicatorView(value) 83 | case .animation(let value, let duration): 84 | configImageIndicatorView(value, animationDuration: duration) 85 | default: 86 | break 87 | } 88 | isHidden = indcatorType.shouldHidden 89 | } 90 | } 91 | 92 | private var imageIndicaotorView: UIImageView? 93 | private var nativeActivityIndicatorView: UIActivityIndicatorView? 94 | private var flatActivityIndicatorView: ZVActivityIndicatorView? 95 | private var progressIndicatorView: ZVProgressView? 96 | 97 | convenience init() { 98 | self.init(frame: .zero) 99 | } 100 | 101 | override init(frame: CGRect) { 102 | super.init(frame: frame) 103 | backgroundColor = .clear 104 | isUserInteractionEnabled = false 105 | } 106 | 107 | required public init?(coder aDecoder: NSCoder) { 108 | fatalError("init(coder:) has not been implemented") 109 | } 110 | } 111 | 112 | // MARK: - Override 113 | 114 | extension ZVIndicatorView { 115 | 116 | override public var tintColor: UIColor! { 117 | didSet { 118 | imageIndicaotorView?.tintColor = tintColor 119 | nativeActivityIndicatorView?.color = tintColor 120 | flatActivityIndicatorView?.tintColor = tintColor 121 | } 122 | } 123 | 124 | public override func layoutSubviews() { 125 | super.layoutSubviews() 126 | 127 | let subViewFrame = CGRect(origin: .zero, size: frame.size) 128 | 129 | imageIndicaotorView?.frame = subViewFrame 130 | flatActivityIndicatorView?.frame = subViewFrame 131 | nativeActivityIndicatorView?.frame = subViewFrame 132 | progressIndicatorView?.frame = subViewFrame 133 | } 134 | } 135 | 136 | // MARK: - Private Method 137 | 138 | private extension ZVIndicatorView { 139 | 140 | func configImageIndicatorView(_ value: Any, animationDuration: TimeInterval = 0.0) { 141 | 142 | flatActivityIndicatorView?.stopAnimating() 143 | flatActivityIndicatorView?.removeFromSuperview() 144 | 145 | nativeActivityIndicatorView?.stopAnimating() 146 | nativeActivityIndicatorView?.removeFromSuperview() 147 | 148 | imageIndicaotorView?.stopAnimating() 149 | imageIndicaotorView?.animationImages = nil 150 | imageIndicaotorView?.image = nil 151 | 152 | progressIndicatorView?.removeFromSuperview() 153 | 154 | if imageIndicaotorView == nil { 155 | imageIndicaotorView = UIImageView(frame: .zero) 156 | imageIndicaotorView?.isUserInteractionEnabled = false 157 | } 158 | 159 | if imageIndicaotorView?.superview == nil { 160 | addSubview(imageIndicaotorView!) 161 | } 162 | 163 | if let resource = value as? String { 164 | #if ZVProgressHUD_SPM 165 | let bundlePath = Bundle.module.path(forResource: "Resource", ofType: "bundle") 166 | #else 167 | let bundlePath = Bundle(for: ZVProgressHUD.self).path(forResource: "Resource", ofType: "bundle") 168 | #endif 169 | guard let path = bundlePath, 170 | let bundle = Bundle(path: path), 171 | let fileName = bundle.path(forResource: resource, ofType: "png") 172 | else { return } 173 | 174 | let image = UIImage(contentsOfFile: fileName)?.withRenderingMode(.alwaysTemplate) 175 | imageIndicaotorView?.tintColor = tintColor 176 | imageIndicaotorView?.image = image 177 | } else if let image = value as? UIImage { 178 | 179 | imageIndicaotorView?.image = image 180 | } else if let animationImages = value as? [UIImage] { 181 | 182 | if animationImages.isEmpty { 183 | imageIndicaotorView?.image = nil 184 | } else if animationImages.count == 1 { 185 | imageIndicaotorView?.image = animationImages[0] 186 | } else { 187 | imageIndicaotorView?.animationImages = animationImages 188 | imageIndicaotorView?.animationDuration = animationDuration 189 | imageIndicaotorView?.startAnimating() 190 | } 191 | 192 | imageIndicaotorView?.animationImages = animationImages 193 | imageIndicaotorView?.startAnimating() 194 | } 195 | } 196 | 197 | func configProgressIndicatorView(with value: Float) { 198 | 199 | flatActivityIndicatorView?.stopAnimating() 200 | flatActivityIndicatorView?.removeFromSuperview() 201 | 202 | imageIndicaotorView?.animationImages = nil 203 | imageIndicaotorView?.image = nil 204 | imageIndicaotorView?.stopAnimating() 205 | imageIndicaotorView?.removeFromSuperview() 206 | 207 | nativeActivityIndicatorView?.stopAnimating() 208 | nativeActivityIndicatorView?.removeFromSuperview() 209 | 210 | if progressIndicatorView == nil { 211 | progressIndicatorView = ZVProgressView(frame: .zero) 212 | progressIndicatorView?.progressBackgroundColor = progressBackgroundColor 213 | progressIndicatorView?.progressForegroundColor = progressForegroundColor 214 | progressIndicatorView?.progressLabelColor = progressLabelColor 215 | progressIndicatorView?.font = progressLabelFont 216 | } 217 | 218 | if progressIndicatorView?.superview == nil { 219 | addSubview(progressIndicatorView!) 220 | } 221 | 222 | progressIndicatorView?.updateProgress(value) 223 | } 224 | 225 | private func configNativeActivityIndicatorView() { 226 | 227 | flatActivityIndicatorView?.stopAnimating() 228 | flatActivityIndicatorView?.removeFromSuperview() 229 | 230 | imageIndicaotorView?.animationImages = nil 231 | imageIndicaotorView?.image = nil 232 | imageIndicaotorView?.stopAnimating() 233 | imageIndicaotorView?.removeFromSuperview() 234 | 235 | progressIndicatorView?.removeFromSuperview() 236 | 237 | if nativeActivityIndicatorView == nil { 238 | nativeActivityIndicatorView = UIActivityIndicatorView(style: .whiteLarge) 239 | nativeActivityIndicatorView?.color = tintColor 240 | nativeActivityIndicatorView?.hidesWhenStopped = true 241 | } 242 | 243 | if nativeActivityIndicatorView?.superview == nil { 244 | addSubview(nativeActivityIndicatorView!) 245 | } 246 | 247 | nativeActivityIndicatorView?.startAnimating() 248 | } 249 | 250 | private func configFlatActivityIndicatorView() { 251 | 252 | nativeActivityIndicatorView?.stopAnimating() 253 | nativeActivityIndicatorView?.removeFromSuperview() 254 | 255 | imageIndicaotorView?.image = nil 256 | imageIndicaotorView?.animationImages = nil 257 | imageIndicaotorView?.stopAnimating() 258 | imageIndicaotorView?.removeFromSuperview() 259 | 260 | progressIndicatorView?.removeFromSuperview() 261 | 262 | if flatActivityIndicatorView == nil { 263 | flatActivityIndicatorView = ZVActivityIndicatorView() 264 | flatActivityIndicatorView?.tintColor = tintColor 265 | flatActivityIndicatorView?.hidesWhenStopped = true 266 | flatActivityIndicatorView?.strokeWidth = strokeWidth 267 | } 268 | 269 | if flatActivityIndicatorView?.superview == nil { 270 | addSubview(flatActivityIndicatorView!) 271 | } 272 | 273 | flatActivityIndicatorView?.startAnimating() 274 | } 275 | } 276 | 277 | #endif 278 | -------------------------------------------------------------------------------- /ZVProgressHUDExample/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // Example 4 | // 5 | // Created by zevwings on 2017/7/11. 6 | // Copyright © 2017-2019 zevwings. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import ZVProgressHUD 11 | 12 | class ViewController: UIViewController { 13 | 14 | var rows = [ 15 | ("show", #selector(showIndicator)), 16 | ("showWithLabel", #selector(showWithLabel)), 17 | ("showProgress", #selector(showProgress)), 18 | ("showProgressWithLabel", #selector(showProgressWithLabel)), 19 | ("showError", #selector(showError)), 20 | ("showSuccess", #selector(showSuccess)), 21 | ("showWarning", #selector(showWarning)), 22 | ("showCustomImage", #selector(showCustomImage)), 23 | ("showCustomImageWithLabel", #selector(showCustomImageWithLabel)), 24 | ("showAnimation", #selector(showAnimation)), 25 | ("showCustomView", #selector(showCustomView)), 26 | ("showLabel", #selector(showLabel)), 27 | ("dismiss", #selector(dismissHUD)) 28 | ] 29 | 30 | @IBOutlet weak var tableView: UITableView! 31 | 32 | @IBOutlet weak var delayShowTimeLabel: UIView! 33 | @IBOutlet weak var delayDismissTimeLabel: UIView! 34 | 35 | var showDelay: TimeInterval = 0 36 | var dismissDelay: TimeInterval = 0 37 | 38 | var progress: Float = 0.0 39 | var timer: Timer? 40 | 41 | var countDown: Int = 0 42 | private lazy var loadingView: ZVDownloadingView = { 43 | let loadingView = ZVDownloadingView() 44 | return loadingView 45 | }() 46 | 47 | @IBOutlet weak var indicatorSizeLabel: UILabel! 48 | @IBOutlet weak var logoSizeLabel: UILabel! 49 | 50 | override func viewDidLoad() { 51 | super.viewDidLoad() 52 | 53 | ZVProgressHUD.setMaskType(.black) 54 | ZVProgressHUD.setDisplayStyle(.dark) 55 | ZVProgressHUD.setLogoSize(CGSize(width: 30.0, height: 30.0)) 56 | 57 | // ZVProgressHUD.setProgressLabelColor(.green) 58 | // ZVProgressHUD.setTitleLabelColor(.cyan) 59 | 60 | let logo = UIImage(named: "logo_crown")?.withRenderingMode(.alwaysTemplate) 61 | ZVProgressHUD.setLogo(logo) 62 | 63 | NotificationCenter.default.addObserver(self, 64 | selector: #selector(ZVProgressHUDTouchEvent(_:)), 65 | name: .ZVProgressHUDReceivedTouchUpInsideEvent, 66 | object: nil) 67 | } 68 | 69 | override func didReceiveMemoryWarning() { 70 | super.didReceiveMemoryWarning() 71 | 72 | } 73 | } 74 | 75 | // MARK: - ZVProgressHUD Notification 76 | 77 | extension ViewController { 78 | 79 | @objc func ZVProgressHUDTouchEvent(_ notification: Notification) { 80 | timer?.invalidate() 81 | timer = nil 82 | self.dismissHUD() 83 | } 84 | } 85 | 86 | // MARK: - ZVProgressHUD 87 | 88 | extension ViewController { 89 | 90 | @objc func showIndicator() { 91 | 92 | ZVProgressHUD.show(delay: showDelay) 93 | } 94 | 95 | @objc func showWithLabel() { 96 | 97 | ZVProgressHUD.show(with: "loading", delay: showDelay) 98 | } 99 | 100 | @objc func showError() { 101 | 102 | ZVProgressHUD.showError(with: "error", delay: showDelay) 103 | } 104 | 105 | @objc func showSuccess() { 106 | 107 | ZVProgressHUD.showSuccess(with: "success", delay: showDelay) 108 | } 109 | 110 | @objc func showWarning() { 111 | 112 | ZVProgressHUD.showWarning(with: "warning", delay: showDelay) 113 | } 114 | 115 | @objc func showCustomImage() { 116 | 117 | let image = UIImage(named: "smile") 118 | ZVProgressHUD.showImage(image!, delay: showDelay) 119 | } 120 | 121 | @objc func showCustomImageWithLabel() { 122 | 123 | let image = UIImage(named: "smile") 124 | ZVProgressHUD.showImage(image!, title: "smile everyday", delay: showDelay) 125 | } 126 | 127 | @objc func showProgress() { 128 | 129 | self.progress = 0 130 | if self.timer != nil { 131 | timer?.invalidate() 132 | timer = nil 133 | } 134 | 135 | ZVProgressHUD.showProgress(0.0) 136 | 137 | self.timer = Timer.scheduledTimer( 138 | timeInterval: 0.25, 139 | target: self, 140 | selector: #selector(ViewController.progressTimerAction(_:)), 141 | userInfo: nil, 142 | repeats: true 143 | ) 144 | } 145 | 146 | @objc func showProgressWithLabel() { 147 | 148 | self.progress = 0 149 | if self.timer != nil { 150 | timer?.invalidate() 151 | timer = nil 152 | } 153 | 154 | ZVProgressHUD.showProgress(0.0, title: "Progress", delay: showDelay) 155 | 156 | self.timer = Timer.scheduledTimer( 157 | timeInterval: 0.25, 158 | target: self, 159 | selector: #selector(ViewController.progressTimerAction(_:)), 160 | userInfo: ["title": "Progress"], 161 | repeats: true 162 | ) 163 | } 164 | 165 | @objc func showAnimation() { 166 | 167 | var images = [UIImage]() 168 | for index in 1 ... 3 { 169 | let image = UIImage(named: "loading_0\(index)") 170 | images.append(image!) 171 | } 172 | 173 | ZVProgressHUD.showAnimation(images, delay: showDelay) 174 | 175 | } 176 | 177 | @objc func showCustomView() { 178 | 179 | var configuration = ZVProgressHUD.Configuration() 180 | configuration.animationType = .native 181 | configuration.displayStyle = .custom((.clear, .clear)) 182 | configuration.maskType = .black 183 | 184 | loadingView.show(with: "Request Data ....") 185 | ZVProgressHUD.showCustomView(loadingView, with: configuration) 186 | 187 | countDown = 0 188 | progress = 0 189 | 190 | self.timer = Timer.scheduledTimer( 191 | timeInterval: 0.25, 192 | target: self, 193 | selector: #selector(ViewController.customProgressTimerAction(_:)), 194 | userInfo: ["title": "Progress"], 195 | repeats: true 196 | ) 197 | 198 | } 199 | 200 | @objc func showLabel() { 201 | 202 | ZVProgressHUD.showText("pure text", in: self.view, delay: showDelay) 203 | 204 | } 205 | 206 | @objc func dismissHUD() { 207 | 208 | ZVProgressHUD.dismiss(delay: dismissDelay) { 209 | print("dimiss") 210 | } 211 | } 212 | 213 | 214 | @IBAction func setDisplayStyle(_ sender: UISegmentedControl) { 215 | 216 | switch sender.selectedSegmentIndex { 217 | case 0: 218 | ZVProgressHUD.setDisplayStyle(.dark) 219 | case 1: 220 | ZVProgressHUD.setDisplayStyle(.light) 221 | case 2: 222 | let backgroundColor = UIColor(red: 86.0 / 255.0, green: 75.0 / 255.0, blue: 151.0 / 255.0, alpha: 1.0) 223 | let foregroundColor = UIColor(red: 239.0 / 255.0, green: 83.0 / 255.0, blue: 64.0 / 255.0, alpha: 1.0) 224 | ZVProgressHUD.setDisplayStyle(.custom((backgroundColor, foregroundColor))) 225 | default: 226 | break 227 | } 228 | } 229 | 230 | @IBAction func setMaskType(_ sender: UISegmentedControl) { 231 | 232 | switch sender.selectedSegmentIndex { 233 | case 0: 234 | ZVProgressHUD.setMaskType(.clear) 235 | case 1: 236 | ZVProgressHUD.setMaskType(.none) 237 | case 2: 238 | ZVProgressHUD.setMaskType(.black) 239 | case 3: 240 | let color = UIColor(red: 215.0 / 255.0, green: 22.0 / 255.0, blue: 59.0 / 255.0, alpha: 0.35) 241 | ZVProgressHUD.setMaskType(.custom(color: color)) 242 | default: 243 | break 244 | } 245 | } 246 | 247 | @IBAction func setAnimationType(_ sender: UISegmentedControl) { 248 | switch sender.selectedSegmentIndex { 249 | case 0: 250 | ZVProgressHUD.setAnimationType(.flat) 251 | case 1: 252 | ZVProgressHUD.setAnimationType(.native) 253 | default: 254 | break 255 | } 256 | } 257 | 258 | @IBAction func setIndicatorViewSize(_ sender: UISlider) { 259 | let size = CGFloat(sender.value) 260 | ZVProgressHUD.setIndicatorSize(CGSize(width: size, height: size)) 261 | indicatorSizeLabel.text = "Indicator Size (\(String(format: "%.2f", size)))" 262 | 263 | } 264 | 265 | @IBAction func setLogoViewSize(_ sender: UISlider) { 266 | let size = CGFloat(sender.value) 267 | 268 | ZVProgressHUD.setLogoSize(CGSize(width: size, height: size)) 269 | logoSizeLabel.text = "Logo Size (\(String(format: "%.2f", size)))" 270 | } 271 | 272 | @IBAction func setDelayShow(_ sender: UISlider) { 273 | self.showDelay = TimeInterval(sender.value) 274 | } 275 | 276 | @IBAction func setDelayDismiss(_ sender: UISlider) { 277 | self.dismissDelay = TimeInterval(sender.value) 278 | } 279 | 280 | @objc func progressTimerAction(_ sender: Timer?) { 281 | 282 | let userInfo = sender?.userInfo as? [String: String] 283 | let title = userInfo?["title"] ?? "" 284 | progress += 0.05 285 | ZVProgressHUD.showProgress(progress, title: title) 286 | 287 | print("timer action : \(progress)") 288 | 289 | if progress > 1.0 { 290 | timer?.invalidate() 291 | timer = nil 292 | } 293 | } 294 | 295 | @objc func customProgressTimerAction(_ sender: Timer?) { 296 | 297 | let userInfo = sender?.userInfo as? [String: String] 298 | let title = userInfo?["title"] ?? "" 299 | // progress += 0.05 300 | 301 | countDown += 1 302 | 303 | guard countDown >= 10 else { return } 304 | 305 | if countDown == 10 { 306 | loadingView.start() 307 | } 308 | 309 | progress += 0.05 310 | 311 | loadingView.update(progress) 312 | 313 | print("timer action : \(progress)") 314 | 315 | if progress > 1.0 { 316 | timer?.invalidate() 317 | timer = nil 318 | 319 | loadingView.dismiss() 320 | ZVProgressHUD.dismiss() 321 | } 322 | } 323 | } 324 | 325 | extension ViewController: UITableViewDataSource { 326 | 327 | public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 328 | return self.rows.count 329 | } 330 | 331 | public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 332 | 333 | let cell = tableView.dequeueReusableCell(withIdentifier: "ReuseIdentifier") 334 | cell?.textLabel?.text = self.rows[indexPath.row].0 335 | cell?.textLabel?.font = UIFont.systemFont(ofSize: 14.0) 336 | cell?.textLabel?.textColor = UIColor(white: 0.2, alpha: 1.0) 337 | return cell! 338 | } 339 | } 340 | 341 | extension ViewController: UITableViewDelegate { 342 | 343 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 344 | let selector = self.rows[indexPath.row].1 345 | self.perform(selector) 346 | } 347 | } 348 | 349 | extension ViewController: UITextFieldDelegate { 350 | 351 | func textFieldShouldReturn(_ textField: UITextField) -> Bool { 352 | 353 | textField.resignFirstResponder() 354 | 355 | return true 356 | } 357 | } 358 | 359 | extension ViewController { 360 | 361 | override var preferredStatusBarStyle: UIStatusBarStyle { 362 | return .lightContent 363 | } 364 | } 365 | 366 | extension UINavigationController { 367 | 368 | open override var childForStatusBarStyle: UIViewController? { 369 | return self.topViewController 370 | } 371 | } 372 | 373 | -------------------------------------------------------------------------------- /ZVProgressHUD/ZVProgressHUDExtensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ProgressHUD+Operations.swift 3 | // ZVProgressHUD 4 | // 5 | // Created by zevwings on 2019/9/29. 6 | // Copyright © 2019 zevwings. All rights reserved. 7 | // 8 | 9 | #if !os(macOS) 10 | 11 | import UIKit 12 | 13 | // MARK: - Configuration 14 | 15 | public extension ZVProgressHUD { 16 | 17 | class func setDisplayStyle(_ displayStyle: DisplayStyle) { 18 | shared.configuration.displayStyle = displayStyle 19 | } 20 | 21 | class func setMaskType(_ maskType: MaskType) { 22 | shared.configuration.maskType = maskType 23 | } 24 | 25 | class func setCornerRadius(_ cornerRadius: CGFloat) { 26 | shared.configuration.cornerRadius = cornerRadius 27 | } 28 | 29 | class func setOffset(_ offset: UIOffset) { 30 | shared.configuration.offset = offset 31 | } 32 | 33 | class func setTitleLabelFont(_ font: UIFont) { 34 | shared.configuration.titleLabelFont = font 35 | } 36 | 37 | class func setTitleLabelColor(_ color: UIColor?) { 38 | shared.configuration.titleLabelColor = color 39 | } 40 | 41 | class func setProgressLabelFont(_ font: UIFont) { 42 | shared.configuration.progressLabelFont = font 43 | } 44 | 45 | class func setProgressLabelColor(_ color: UIColor?) { 46 | shared.configuration.progressLabelColor = color 47 | } 48 | 49 | class func setProgressLabelHidden(_ isProgressLabelHidden: Bool) { 50 | shared.configuration.isProgressLabelHidden = isProgressLabelHidden 51 | } 52 | 53 | class func setStrokeWidth(_ strokeWidth: CGFloat) { 54 | shared.configuration.strokeWidth = strokeWidth 55 | } 56 | 57 | class func setIndicatorSize(_ size: CGSize) { 58 | shared.configuration.indicatorSize = size 59 | } 60 | 61 | class func setAnimationType(_ animationType: ZVIndicatorView.AnimationType) { 62 | shared.configuration.animationType = animationType 63 | } 64 | 65 | class func setContentInsets(_ indets: UIEdgeInsets) { 66 | shared.configuration.contentInsets = indets 67 | } 68 | 69 | class func setTitleEdgeInsets(_ indets: UIEdgeInsets) { 70 | shared.configuration.titleEdgeInsets = indets 71 | } 72 | 73 | class func setIndicatorEdgeInsets(_ indets: UIEdgeInsets) { 74 | shared.configuration.indicatorEdgeInsets = indets 75 | } 76 | 77 | class func setLogo(_ logo: UIImage?) { 78 | shared.configuration.logo = logo 79 | } 80 | 81 | class func setLogoSize(_ size: CGSize) { 82 | shared.configuration.logoSize = size 83 | } 84 | } 85 | 86 | // MARK: - Props 87 | 88 | public extension ZVProgressHUD { 89 | 90 | class func setMaxSupportedWindowLevel(_ windowLevel: UIWindow.Level) { 91 | shared.maxSupportedWindowLevel = windowLevel 92 | } 93 | 94 | class func setFadeInAnimationTimeInterval(_ timeInterval: TimeInterval) { 95 | shared.fadeInAnimationTimeInterval = timeInterval 96 | } 97 | 98 | class func setFadeOutAnimationTImeInterval(_ timeInterval: TimeInterval) { 99 | shared.fadeOutAnimationTImeInterval = timeInterval 100 | } 101 | 102 | class func setMinimumDismissTimeInterval(_ timeInterval: TimeInterval) { 103 | shared.minimumDismissTimeInterval = timeInterval 104 | } 105 | 106 | class func setMaximumDismissTimeInterval(_ timeInterval: TimeInterval) { 107 | shared.maximumDismissTimeInterval = timeInterval 108 | } 109 | 110 | class func setMaximumContentSize(_ size: CGSize) { 111 | shared.maximumContentSize = size 112 | } 113 | 114 | } 115 | 116 | // MARK: - Handle 117 | 118 | public extension ZVProgressHUD { 119 | 120 | /// show a toast 121 | /// 122 | /// - Parameters: 123 | /// - text: toast content 124 | /// - superview: super view, if superview is nil, show on main window 125 | /// - delayTimeInterval: the view will show delay the `delayTimeInterval` 126 | class func showText( 127 | _ text: String, 128 | in superview: UIView? = nil, 129 | delay delayTimeInterval: TimeInterval = 0.0, 130 | with configuration: Configuration? = nil 131 | ) { 132 | shared.internalShow( 133 | displayType: .text(value: text), 134 | in: superview, 135 | delay: delayTimeInterval, 136 | with: configuration 137 | ) 138 | } 139 | 140 | /// show a success message 141 | /// 142 | /// - Parameters: 143 | /// - title: the success message remind users what you want 144 | /// - superview: super view, if superview is nil, show on main window 145 | /// - delayTimeInterval: the view will show delay the `delayTimeInterval` 146 | class func showSuccess( 147 | with title: String = "", 148 | in superview: UIView? = nil, 149 | delay delayTimeInterval: TimeInterval = 0.0, 150 | with configuration: Configuration? = nil 151 | ) { 152 | shared.internalShow( 153 | displayType: .indicator(title: title, type: .success), 154 | in: superview, 155 | delay: delayTimeInterval, 156 | with: configuration 157 | ) 158 | } 159 | 160 | /// show a error message 161 | /// 162 | /// - Parameters: 163 | /// - title: the error message remind users what you want 164 | /// - superview: super view, if superview is nil, show on main window 165 | /// - delayTimeInterval: the view will show delay the `delayTimeInterval` 166 | class func showError( 167 | with title: String = "", 168 | in superview: UIView? = nil, 169 | delay delayTimeInterval: TimeInterval = 0.0, 170 | with configuration: Configuration? = nil 171 | ) { 172 | shared.internalShow( 173 | displayType: .indicator(title: title, type: .error), 174 | in: superview, 175 | delay: delayTimeInterval, 176 | with: configuration 177 | ) 178 | } 179 | 180 | /// show a warning message 181 | /// 182 | /// - Parameters: 183 | /// - title: the warning message remind users what you want 184 | /// - superview: super view, if superview is nil, show on main window 185 | /// - delayTimeInterval: the view will show delay the `delayTimeInterval` 186 | class func showWarning( 187 | with title: String = "", 188 | in superview: UIView? = nil, 189 | delay delayTimeInterval: TimeInterval = 0.0, 190 | with configuration: Configuration? = nil 191 | ) { 192 | shared.internalShow( 193 | displayType: .indicator(title: title, type: .warning), 194 | in: superview, 195 | delay: delayTimeInterval, 196 | with: configuration 197 | ) 198 | } 199 | 200 | /// show a waiting alert 201 | /// 202 | /// - Parameters: 203 | /// - title: the message remind users what you want 204 | /// - superview: super view, if superview is nil, show on main window 205 | /// - delayTimeInterval: the view will show delay the `delayTimeInterval` 206 | class func show( 207 | with title: String = "", 208 | in superview: UIView? = nil, 209 | delay delayTimeInterval: TimeInterval = 0.0, 210 | with configuration: Configuration? = nil 211 | ) { 212 | let animationType: ZVIndicatorView.AnimationType 213 | if let configuration = configuration { 214 | animationType = configuration.animationType 215 | } else { 216 | animationType = shared.configuration.animationType 217 | } 218 | shared.internalShow( 219 | displayType: .indicator(title: title, type: .indicator(style: animationType)), 220 | in: superview, 221 | delay: delayTimeInterval, 222 | with: configuration 223 | ) 224 | } 225 | 226 | /// show the progress of some task 227 | /// 228 | /// - Parameters: 229 | /// - progress: the progress of your task 230 | /// - title: the message remind users what you want 231 | /// - superview: super view, if superview is nil, show on main window 232 | /// - delayTimeInterval: the view will show delay the `delayTimeInterval` 233 | class func showProgress( 234 | _ progress: Float, 235 | title: String = "", 236 | in superview: UIView? = nil, 237 | delay delayTimeInterval: TimeInterval = 0.0, 238 | with configuration: Configuration? = nil 239 | ) { 240 | shared.internalShow( 241 | displayType: .indicator(title: title, type: .progress(value: progress)), 242 | in: superview, 243 | delay: delayTimeInterval, 244 | with: configuration 245 | ) 246 | } 247 | 248 | /// show a custom image 249 | /// 250 | /// - Parameters: 251 | /// - image: your image 252 | /// - title: the message remind users what you want 253 | /// - superview: super view, if superview is nil, show on main window 254 | /// - dismissAtomically: if `true` the `HUD` will dissmiss atomically 255 | /// - delayTimeInterval: the view will show delay the `delayTimeInterval` 256 | class func showImage( 257 | _ image: UIImage, 258 | title: String = "", 259 | in superview: UIView? = nil, 260 | dismissAtomically: Bool = true, 261 | delay delayTimeInterval: TimeInterval = 0.0, 262 | with configuration: Configuration? = nil 263 | ) { 264 | shared.internalShow( 265 | displayType: .indicator(title: title, type: .image(value: image, dismissAtomically: dismissAtomically)), 266 | in: superview, 267 | delay: delayTimeInterval, 268 | with: configuration 269 | ) 270 | } 271 | 272 | /// show the animation waiting alert 273 | /// 274 | /// - Parameters: 275 | /// - images: animation image array 276 | /// - duration: animation duration @see UIImage 277 | /// - title: the message remind users what you want 278 | /// - superview: super view, if superview is nil, show on main window 279 | /// - delayTimeInterval: the view will show delay the `delayTimeInterval` 280 | class func showAnimation( 281 | _ images: [UIImage], 282 | duration: TimeInterval = 0.0, 283 | title: String = "", 284 | in superview: UIView? = nil, 285 | delay delayTimeInterval: TimeInterval = 0.0, 286 | with configuration: Configuration? = nil 287 | ) { 288 | if images.isEmpty { return } 289 | 290 | let animationDuration: TimeInterval 291 | if duration == 0 { 292 | animationDuration = Double(images.count) * 0.1 293 | } else { 294 | animationDuration = duration 295 | } 296 | 297 | shared.internalShow( 298 | displayType: .indicator(title: title, type: .animation(value: images, duration: animationDuration)), 299 | in: superview, 300 | delay: delayTimeInterval, 301 | with: configuration 302 | ) 303 | } 304 | 305 | /// show the animation waiting alert 306 | /// 307 | /// - Parameters: 308 | /// - images: animation image array 309 | /// - duration: animation duration @see UIImage 310 | /// - title: the message remind users what you want 311 | /// - superview: super view, if superview is nil, show on main window 312 | /// - delayTimeInterval: the view will show delay the `delayTimeInterval` 313 | class func showCustomView( 314 | _ view: UIView, 315 | in superview: UIView? = nil, 316 | delay delayTimeInterval: TimeInterval = 0.0, 317 | with configuration: Configuration? = nil 318 | ) { 319 | shared.internalShow( 320 | displayType: .customeView(view: view), 321 | in: superview, 322 | delay: delayTimeInterval, 323 | with: configuration 324 | ) 325 | } 326 | 327 | /// show custom display type @see ZVProgressHUD.DisplayType 328 | /// 329 | /// - Parameters: 330 | /// - displayType: ZVProgressHUD.DisplayType 331 | /// - superview: super view, if superview is nil, show on main window 332 | /// - delayTimeInterval: the view will show delay the `delayTimeInterval` 333 | class func show( 334 | with displayType: DisplayType, 335 | in superview: UIView? = nil, 336 | delay delayTimeInterval: TimeInterval = 0.0, 337 | with configuration: Configuration? = nil 338 | ) { 339 | shared.internalShow( 340 | displayType: displayType, 341 | in: superview, 342 | delay: delayTimeInterval, 343 | with: configuration 344 | ) 345 | } 346 | 347 | /// dismiss the hud 348 | /// 349 | /// - Parameters: 350 | /// - delay: the view will dissmiss delay the `delayTimeInterval` 351 | /// - completion: dismiss completion handler 352 | class func dismiss( 353 | delay: TimeInterval = 0.0, 354 | completion: CompletionHandler? = nil 355 | ) { 356 | shared.internalDismiss(with: delay, completion: completion) 357 | } 358 | } 359 | 360 | #endif 361 | -------------------------------------------------------------------------------- /ZVProgressHUDExample/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 99 | 108 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 149 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | -------------------------------------------------------------------------------- /ZVProgressHUD.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 52; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 4D4445FC20A17185006FCEEC /* ZVProgressHUD.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D5BDA8D1F146CAC00E68CB6 /* ZVProgressHUD.framework */; }; 11 | 4D4445FD20A17185006FCEEC /* ZVProgressHUD.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 4D5BDA8D1F146CAC00E68CB6 /* ZVProgressHUD.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 12 | 4D5797D724CEACF900C0E6E8 /* ZVProgressHUDExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D5797D424CEACF900C0E6E8 /* ZVProgressHUDExtensions.swift */; }; 13 | 4D5797D924CEACF900C0E6E8 /* ZVProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D5797D624CEACF900C0E6E8 /* ZVProgressView.swift */; }; 14 | 4D5BDA9E1F146CAC00E68CB6 /* ZVProgressHUD.h in Headers */ = {isa = PBXBuildFile; fileRef = 4D5BDA901F146CAC00E68CB6 /* ZVProgressHUD.h */; settings = {ATTRIBUTES = (Public, ); }; }; 15 | 4D5F00102591AEC400E68D49 /* ZVProgressHUD.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D5F000E2591AEC400E68D49 /* ZVProgressHUD.swift */; }; 16 | 4D5F00152591AF6500E68D49 /* ZVDownloadingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D5F00142591AF6500E68D49 /* ZVDownloadingView.swift */; }; 17 | 4D60771620327D4F00474944 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D60771520327D4F00474944 /* ViewController.swift */; }; 18 | 4D8046F91F14CBFD0069F9F2 /* Resource.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 4D8046F81F14CBFD0069F9F2 /* Resource.bundle */; }; 19 | 4DB03ACA2531B329003F8300 /* ZVActivityIndicatorView in Frameworks */ = {isa = PBXBuildFile; productRef = 4DB03AC92531B329003F8300 /* ZVActivityIndicatorView */; }; 20 | 4DC8B6982306A61900170426 /* ZVIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DC8B6962306A61900170426 /* ZVIndicatorView.swift */; }; 21 | 4DFF5B4C20318D7A0098BA7D /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DFF5B4B20318D7A0098BA7D /* AppDelegate.swift */; }; 22 | 4DFF5B5120318D7A0098BA7D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4DFF5B4F20318D7A0098BA7D /* Main.storyboard */; }; 23 | 4DFF5B5320318D7A0098BA7D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4DFF5B5220318D7A0098BA7D /* Assets.xcassets */; }; 24 | 4DFF5B5620318D7A0098BA7D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4DFF5B5420318D7A0098BA7D /* LaunchScreen.storyboard */; }; 25 | /* End PBXBuildFile section */ 26 | 27 | /* Begin PBXContainerItemProxy section */ 28 | 4D4445FE20A17185006FCEEC /* PBXContainerItemProxy */ = { 29 | isa = PBXContainerItemProxy; 30 | containerPortal = 4D5BDA841F146CAC00E68CB6 /* Project object */; 31 | proxyType = 1; 32 | remoteGlobalIDString = 4D5BDA8C1F146CAC00E68CB6; 33 | remoteInfo = ZVProgressHUD; 34 | }; 35 | /* End PBXContainerItemProxy section */ 36 | 37 | /* Begin PBXCopyFilesBuildPhase section */ 38 | 4D44460020A17185006FCEEC /* Embed Frameworks */ = { 39 | isa = PBXCopyFilesBuildPhase; 40 | buildActionMask = 2147483647; 41 | dstPath = ""; 42 | dstSubfolderSpec = 10; 43 | files = ( 44 | 4D4445FD20A17185006FCEEC /* ZVProgressHUD.framework in Embed Frameworks */, 45 | ); 46 | name = "Embed Frameworks"; 47 | runOnlyForDeploymentPostprocessing = 0; 48 | }; 49 | /* End PBXCopyFilesBuildPhase section */ 50 | 51 | /* Begin PBXFileReference section */ 52 | 4D5797D424CEACF900C0E6E8 /* ZVProgressHUDExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ZVProgressHUDExtensions.swift; sourceTree = ""; }; 53 | 4D5797D624CEACF900C0E6E8 /* ZVProgressView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ZVProgressView.swift; sourceTree = ""; }; 54 | 4D5BDA8D1F146CAC00E68CB6 /* ZVProgressHUD.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ZVProgressHUD.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 55 | 4D5BDA901F146CAC00E68CB6 /* ZVProgressHUD.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ZVProgressHUD.h; sourceTree = ""; }; 56 | 4D5BDA911F146CAC00E68CB6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 57 | 4D5F000E2591AEC400E68D49 /* ZVProgressHUD.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ZVProgressHUD.swift; sourceTree = ""; }; 58 | 4D5F00142591AF6500E68D49 /* ZVDownloadingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZVDownloadingView.swift; sourceTree = ""; }; 59 | 4D60771520327D4F00474944 /* ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 60 | 4D8046F81F14CBFD0069F9F2 /* Resource.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Resource.bundle; sourceTree = ""; }; 61 | 4DC8B6962306A61900170426 /* ZVIndicatorView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ZVIndicatorView.swift; sourceTree = ""; }; 62 | 4DCDC08C207F4E0100CB78B8 /* ZVActivityIndicatorView.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ZVActivityIndicatorView.framework; path = Carthage/Build/iOS/ZVActivityIndicatorView.framework; sourceTree = ""; }; 63 | 4DDCB2D7272792560089BB96 /* Package.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = ""; }; 64 | 4DDCB2D8272792560089BB96 /* Cartfile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Cartfile; sourceTree = ""; }; 65 | 4DDCB2D9272792560089BB96 /* ZVProgressHUD.podspec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ZVProgressHUD.podspec; sourceTree = ""; }; 66 | 4DFF5B4920318D7A0098BA7D /* ZVProgressHUDExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ZVProgressHUDExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 67 | 4DFF5B4B20318D7A0098BA7D /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 68 | 4DFF5B5020318D7A0098BA7D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 69 | 4DFF5B5220318D7A0098BA7D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 70 | 4DFF5B5520318D7A0098BA7D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 71 | 4DFF5B5720318D7A0098BA7D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 72 | /* End PBXFileReference section */ 73 | 74 | /* Begin PBXFrameworksBuildPhase section */ 75 | 4D5BDA891F146CAC00E68CB6 /* Frameworks */ = { 76 | isa = PBXFrameworksBuildPhase; 77 | buildActionMask = 2147483647; 78 | files = ( 79 | 4DB03ACA2531B329003F8300 /* ZVActivityIndicatorView in Frameworks */, 80 | ); 81 | runOnlyForDeploymentPostprocessing = 0; 82 | }; 83 | 4DFF5B4620318D7A0098BA7D /* Frameworks */ = { 84 | isa = PBXFrameworksBuildPhase; 85 | buildActionMask = 2147483647; 86 | files = ( 87 | 4D4445FC20A17185006FCEEC /* ZVProgressHUD.framework in Frameworks */, 88 | ); 89 | runOnlyForDeploymentPostprocessing = 0; 90 | }; 91 | /* End PBXFrameworksBuildPhase section */ 92 | 93 | /* Begin PBXGroup section */ 94 | 4D5BDA831F146CAC00E68CB6 = { 95 | isa = PBXGroup; 96 | children = ( 97 | 4DDCB2DE2727926D0089BB96 /* Deployment */, 98 | 4DDCB2DD272792600089BB96 /* Dependencies */, 99 | 4D5BDA8F1F146CAC00E68CB6 /* ZVProgressHUD */, 100 | 4DFF5B4A20318D7A0098BA7D /* ZVProgressHUDExample */, 101 | 4D5BDA8E1F146CAC00E68CB6 /* Products */, 102 | 4DFF5B6620318F0B0098BA7D /* Frameworks */, 103 | ); 104 | sourceTree = ""; 105 | }; 106 | 4D5BDA8E1F146CAC00E68CB6 /* Products */ = { 107 | isa = PBXGroup; 108 | children = ( 109 | 4D5BDA8D1F146CAC00E68CB6 /* ZVProgressHUD.framework */, 110 | 4DFF5B4920318D7A0098BA7D /* ZVProgressHUDExample.app */, 111 | ); 112 | name = Products; 113 | sourceTree = ""; 114 | }; 115 | 4D5BDA8F1F146CAC00E68CB6 /* ZVProgressHUD */ = { 116 | isa = PBXGroup; 117 | children = ( 118 | 4D5BDA901F146CAC00E68CB6 /* ZVProgressHUD.h */, 119 | 4D5797D624CEACF900C0E6E8 /* ZVProgressView.swift */, 120 | 4DC8B6962306A61900170426 /* ZVIndicatorView.swift */, 121 | 4D5F000E2591AEC400E68D49 /* ZVProgressHUD.swift */, 122 | 4D5797D424CEACF900C0E6E8 /* ZVProgressHUDExtensions.swift */, 123 | 4D5BDA911F146CAC00E68CB6 /* Info.plist */, 124 | 4D8046F81F14CBFD0069F9F2 /* Resource.bundle */, 125 | ); 126 | path = ZVProgressHUD; 127 | sourceTree = ""; 128 | }; 129 | 4DDCB2DD272792600089BB96 /* Dependencies */ = { 130 | isa = PBXGroup; 131 | children = ( 132 | 4DDCB2D8272792560089BB96 /* Cartfile */, 133 | ); 134 | name = Dependencies; 135 | sourceTree = ""; 136 | }; 137 | 4DDCB2DE2727926D0089BB96 /* Deployment */ = { 138 | isa = PBXGroup; 139 | children = ( 140 | 4DDCB2D7272792560089BB96 /* Package.swift */, 141 | 4DDCB2D9272792560089BB96 /* ZVProgressHUD.podspec */, 142 | ); 143 | name = Deployment; 144 | sourceTree = ""; 145 | }; 146 | 4DFF5B4A20318D7A0098BA7D /* ZVProgressHUDExample */ = { 147 | isa = PBXGroup; 148 | children = ( 149 | 4DFF5B4B20318D7A0098BA7D /* AppDelegate.swift */, 150 | 4D60771520327D4F00474944 /* ViewController.swift */, 151 | 4DFF5B4F20318D7A0098BA7D /* Main.storyboard */, 152 | 4DFF5B5220318D7A0098BA7D /* Assets.xcassets */, 153 | 4DFF5B5420318D7A0098BA7D /* LaunchScreen.storyboard */, 154 | 4DFF5B5720318D7A0098BA7D /* Info.plist */, 155 | 4D5F00142591AF6500E68D49 /* ZVDownloadingView.swift */, 156 | ); 157 | path = ZVProgressHUDExample; 158 | sourceTree = ""; 159 | }; 160 | 4DFF5B6620318F0B0098BA7D /* Frameworks */ = { 161 | isa = PBXGroup; 162 | children = ( 163 | 4DCDC08C207F4E0100CB78B8 /* ZVActivityIndicatorView.framework */, 164 | ); 165 | name = Frameworks; 166 | sourceTree = ""; 167 | }; 168 | /* End PBXGroup section */ 169 | 170 | /* Begin PBXHeadersBuildPhase section */ 171 | 4D5BDA8A1F146CAC00E68CB6 /* Headers */ = { 172 | isa = PBXHeadersBuildPhase; 173 | buildActionMask = 2147483647; 174 | files = ( 175 | 4D5BDA9E1F146CAC00E68CB6 /* ZVProgressHUD.h in Headers */, 176 | ); 177 | runOnlyForDeploymentPostprocessing = 0; 178 | }; 179 | /* End PBXHeadersBuildPhase section */ 180 | 181 | /* Begin PBXNativeTarget section */ 182 | 4D5BDA8C1F146CAC00E68CB6 /* ZVProgressHUD */ = { 183 | isa = PBXNativeTarget; 184 | buildConfigurationList = 4D5BDAA11F146CAC00E68CB6 /* Build configuration list for PBXNativeTarget "ZVProgressHUD" */; 185 | buildPhases = ( 186 | 4D5BDA881F146CAC00E68CB6 /* Sources */, 187 | 4D5BDA891F146CAC00E68CB6 /* Frameworks */, 188 | 4D5BDA8A1F146CAC00E68CB6 /* Headers */, 189 | 4D5BDA8B1F146CAC00E68CB6 /* Resources */, 190 | 4DAE474B2340B1B3008773D2 /* SwiftLint */, 191 | ); 192 | buildRules = ( 193 | ); 194 | dependencies = ( 195 | ); 196 | name = ZVProgressHUD; 197 | packageProductDependencies = ( 198 | 4DB03AC92531B329003F8300 /* ZVActivityIndicatorView */, 199 | ); 200 | productName = ZVProgressHUD; 201 | productReference = 4D5BDA8D1F146CAC00E68CB6 /* ZVProgressHUD.framework */; 202 | productType = "com.apple.product-type.framework"; 203 | }; 204 | 4DFF5B4820318D7A0098BA7D /* ZVProgressHUDExample */ = { 205 | isa = PBXNativeTarget; 206 | buildConfigurationList = 4DFF5B5820318D7A0098BA7D /* Build configuration list for PBXNativeTarget "ZVProgressHUDExample" */; 207 | buildPhases = ( 208 | 4DFF5B4520318D7A0098BA7D /* Sources */, 209 | 4DFF5B4620318D7A0098BA7D /* Frameworks */, 210 | 4DFF5B4720318D7A0098BA7D /* Resources */, 211 | 4D44460020A17185006FCEEC /* Embed Frameworks */, 212 | ); 213 | buildRules = ( 214 | ); 215 | dependencies = ( 216 | 4D4445FF20A17185006FCEEC /* PBXTargetDependency */, 217 | ); 218 | name = ZVProgressHUDExample; 219 | packageProductDependencies = ( 220 | ); 221 | productName = ZVProgressHUDExample; 222 | productReference = 4DFF5B4920318D7A0098BA7D /* ZVProgressHUDExample.app */; 223 | productType = "com.apple.product-type.application"; 224 | }; 225 | /* End PBXNativeTarget section */ 226 | 227 | /* Begin PBXProject section */ 228 | 4D5BDA841F146CAC00E68CB6 /* Project object */ = { 229 | isa = PBXProject; 230 | attributes = { 231 | LastSwiftUpdateCheck = 0920; 232 | LastUpgradeCheck = 1300; 233 | ORGANIZATIONNAME = zevwings; 234 | TargetAttributes = { 235 | 4D5BDA8C1F146CAC00E68CB6 = { 236 | CreatedOnToolsVersion = 8.3.3; 237 | LastSwiftMigration = 1020; 238 | ProvisioningStyle = Automatic; 239 | }; 240 | 4DFF5B4820318D7A0098BA7D = { 241 | CreatedOnToolsVersion = 9.2; 242 | LastSwiftMigration = 1030; 243 | ProvisioningStyle = Automatic; 244 | }; 245 | }; 246 | }; 247 | buildConfigurationList = 4D5BDA871F146CAC00E68CB6 /* Build configuration list for PBXProject "ZVProgressHUD" */; 248 | compatibilityVersion = "Xcode 8.0"; 249 | developmentRegion = en; 250 | hasScannedForEncodings = 0; 251 | knownRegions = ( 252 | en, 253 | Base, 254 | ); 255 | mainGroup = 4D5BDA831F146CAC00E68CB6; 256 | packageReferences = ( 257 | 4DB03AC82531B329003F8300 /* XCRemoteSwiftPackageReference "ZVActivityIndicatorView" */, 258 | ); 259 | productRefGroup = 4D5BDA8E1F146CAC00E68CB6 /* Products */; 260 | projectDirPath = ""; 261 | projectRoot = ""; 262 | targets = ( 263 | 4D5BDA8C1F146CAC00E68CB6 /* ZVProgressHUD */, 264 | 4DFF5B4820318D7A0098BA7D /* ZVProgressHUDExample */, 265 | ); 266 | }; 267 | /* End PBXProject section */ 268 | 269 | /* Begin PBXResourcesBuildPhase section */ 270 | 4D5BDA8B1F146CAC00E68CB6 /* Resources */ = { 271 | isa = PBXResourcesBuildPhase; 272 | buildActionMask = 2147483647; 273 | files = ( 274 | 4D8046F91F14CBFD0069F9F2 /* Resource.bundle in Resources */, 275 | ); 276 | runOnlyForDeploymentPostprocessing = 0; 277 | }; 278 | 4DFF5B4720318D7A0098BA7D /* Resources */ = { 279 | isa = PBXResourcesBuildPhase; 280 | buildActionMask = 2147483647; 281 | files = ( 282 | 4DFF5B5620318D7A0098BA7D /* LaunchScreen.storyboard in Resources */, 283 | 4DFF5B5320318D7A0098BA7D /* Assets.xcassets in Resources */, 284 | 4DFF5B5120318D7A0098BA7D /* Main.storyboard in Resources */, 285 | ); 286 | runOnlyForDeploymentPostprocessing = 0; 287 | }; 288 | /* End PBXResourcesBuildPhase section */ 289 | 290 | /* Begin PBXShellScriptBuildPhase section */ 291 | 4DAE474B2340B1B3008773D2 /* SwiftLint */ = { 292 | isa = PBXShellScriptBuildPhase; 293 | buildActionMask = 2147483647; 294 | files = ( 295 | ); 296 | inputFileListPaths = ( 297 | ); 298 | inputPaths = ( 299 | ); 300 | name = SwiftLint; 301 | outputFileListPaths = ( 302 | ); 303 | outputPaths = ( 304 | ); 305 | runOnlyForDeploymentPostprocessing = 0; 306 | shellPath = /bin/sh; 307 | shellScript = "if [ \"${CONFIGURATION}\" = \"Debug\" ]; then\n if which swiftlint > /dev/null; then\n swiftlint\n else\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint to lint!\"\n fi\nfi\n"; 308 | }; 309 | /* End PBXShellScriptBuildPhase section */ 310 | 311 | /* Begin PBXSourcesBuildPhase section */ 312 | 4D5BDA881F146CAC00E68CB6 /* Sources */ = { 313 | isa = PBXSourcesBuildPhase; 314 | buildActionMask = 2147483647; 315 | files = ( 316 | 4DC8B6982306A61900170426 /* ZVIndicatorView.swift in Sources */, 317 | 4D5797D724CEACF900C0E6E8 /* ZVProgressHUDExtensions.swift in Sources */, 318 | 4D5797D924CEACF900C0E6E8 /* ZVProgressView.swift in Sources */, 319 | 4D5F00102591AEC400E68D49 /* ZVProgressHUD.swift in Sources */, 320 | ); 321 | runOnlyForDeploymentPostprocessing = 0; 322 | }; 323 | 4DFF5B4520318D7A0098BA7D /* Sources */ = { 324 | isa = PBXSourcesBuildPhase; 325 | buildActionMask = 2147483647; 326 | files = ( 327 | 4D60771620327D4F00474944 /* ViewController.swift in Sources */, 328 | 4D5F00152591AF6500E68D49 /* ZVDownloadingView.swift in Sources */, 329 | 4DFF5B4C20318D7A0098BA7D /* AppDelegate.swift in Sources */, 330 | ); 331 | runOnlyForDeploymentPostprocessing = 0; 332 | }; 333 | /* End PBXSourcesBuildPhase section */ 334 | 335 | /* Begin PBXTargetDependency section */ 336 | 4D4445FF20A17185006FCEEC /* PBXTargetDependency */ = { 337 | isa = PBXTargetDependency; 338 | target = 4D5BDA8C1F146CAC00E68CB6 /* ZVProgressHUD */; 339 | targetProxy = 4D4445FE20A17185006FCEEC /* PBXContainerItemProxy */; 340 | }; 341 | /* End PBXTargetDependency section */ 342 | 343 | /* Begin PBXVariantGroup section */ 344 | 4DFF5B4F20318D7A0098BA7D /* Main.storyboard */ = { 345 | isa = PBXVariantGroup; 346 | children = ( 347 | 4DFF5B5020318D7A0098BA7D /* Base */, 348 | ); 349 | name = Main.storyboard; 350 | sourceTree = ""; 351 | }; 352 | 4DFF5B5420318D7A0098BA7D /* LaunchScreen.storyboard */ = { 353 | isa = PBXVariantGroup; 354 | children = ( 355 | 4DFF5B5520318D7A0098BA7D /* Base */, 356 | ); 357 | name = LaunchScreen.storyboard; 358 | sourceTree = ""; 359 | }; 360 | /* End PBXVariantGroup section */ 361 | 362 | /* Begin XCBuildConfiguration section */ 363 | 4D5BDA9F1F146CAC00E68CB6 /* Debug */ = { 364 | isa = XCBuildConfiguration; 365 | buildSettings = { 366 | ALWAYS_SEARCH_USER_PATHS = NO; 367 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 368 | CLANG_ANALYZER_NONNULL = YES; 369 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 370 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 371 | CLANG_CXX_LIBRARY = "libc++"; 372 | CLANG_ENABLE_MODULES = YES; 373 | CLANG_ENABLE_OBJC_ARC = YES; 374 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 375 | CLANG_WARN_BOOL_CONVERSION = YES; 376 | CLANG_WARN_COMMA = YES; 377 | CLANG_WARN_CONSTANT_CONVERSION = YES; 378 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 379 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 380 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 381 | CLANG_WARN_EMPTY_BODY = YES; 382 | CLANG_WARN_ENUM_CONVERSION = YES; 383 | CLANG_WARN_INFINITE_RECURSION = YES; 384 | CLANG_WARN_INT_CONVERSION = YES; 385 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 386 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 387 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 388 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 389 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 390 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 391 | CLANG_WARN_STRICT_PROTOTYPES = YES; 392 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 393 | CLANG_WARN_UNREACHABLE_CODE = YES; 394 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 395 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 396 | COPY_PHASE_STRIP = NO; 397 | CURRENT_PROJECT_VERSION = 1; 398 | DEBUG_INFORMATION_FORMAT = dwarf; 399 | ENABLE_STRICT_OBJC_MSGSEND = YES; 400 | ENABLE_TESTABILITY = YES; 401 | GCC_C_LANGUAGE_STANDARD = gnu99; 402 | GCC_DYNAMIC_NO_PIC = NO; 403 | GCC_NO_COMMON_BLOCKS = YES; 404 | GCC_OPTIMIZATION_LEVEL = 0; 405 | GCC_PREPROCESSOR_DEFINITIONS = ( 406 | "DEBUG=1", 407 | "$(inherited)", 408 | ); 409 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 410 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 411 | GCC_WARN_UNDECLARED_SELECTOR = YES; 412 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 413 | GCC_WARN_UNUSED_FUNCTION = YES; 414 | GCC_WARN_UNUSED_VARIABLE = YES; 415 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 416 | MTL_ENABLE_DEBUG_INFO = YES; 417 | ONLY_ACTIVE_ARCH = YES; 418 | SDKROOT = iphoneos; 419 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 420 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 421 | TARGETED_DEVICE_FAMILY = "1,2"; 422 | VERSIONING_SYSTEM = "apple-generic"; 423 | VERSION_INFO_PREFIX = ""; 424 | }; 425 | name = Debug; 426 | }; 427 | 4D5BDAA01F146CAC00E68CB6 /* Release */ = { 428 | isa = XCBuildConfiguration; 429 | buildSettings = { 430 | ALWAYS_SEARCH_USER_PATHS = NO; 431 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 432 | CLANG_ANALYZER_NONNULL = YES; 433 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 434 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 435 | CLANG_CXX_LIBRARY = "libc++"; 436 | CLANG_ENABLE_MODULES = YES; 437 | CLANG_ENABLE_OBJC_ARC = YES; 438 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 439 | CLANG_WARN_BOOL_CONVERSION = YES; 440 | CLANG_WARN_COMMA = YES; 441 | CLANG_WARN_CONSTANT_CONVERSION = YES; 442 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 443 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 444 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 445 | CLANG_WARN_EMPTY_BODY = YES; 446 | CLANG_WARN_ENUM_CONVERSION = YES; 447 | CLANG_WARN_INFINITE_RECURSION = YES; 448 | CLANG_WARN_INT_CONVERSION = YES; 449 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 450 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 451 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 452 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 453 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 454 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 455 | CLANG_WARN_STRICT_PROTOTYPES = YES; 456 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 457 | CLANG_WARN_UNREACHABLE_CODE = YES; 458 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 459 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 460 | COPY_PHASE_STRIP = NO; 461 | CURRENT_PROJECT_VERSION = 1; 462 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 463 | ENABLE_NS_ASSERTIONS = NO; 464 | ENABLE_STRICT_OBJC_MSGSEND = YES; 465 | GCC_C_LANGUAGE_STANDARD = gnu99; 466 | GCC_NO_COMMON_BLOCKS = YES; 467 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 468 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 469 | GCC_WARN_UNDECLARED_SELECTOR = YES; 470 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 471 | GCC_WARN_UNUSED_FUNCTION = YES; 472 | GCC_WARN_UNUSED_VARIABLE = YES; 473 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 474 | MTL_ENABLE_DEBUG_INFO = NO; 475 | SDKROOT = iphoneos; 476 | SWIFT_COMPILATION_MODE = wholemodule; 477 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 478 | TARGETED_DEVICE_FAMILY = "1,2"; 479 | VALIDATE_PRODUCT = YES; 480 | VERSIONING_SYSTEM = "apple-generic"; 481 | VERSION_INFO_PREFIX = ""; 482 | }; 483 | name = Release; 484 | }; 485 | 4D5BDAA21F146CAC00E68CB6 /* Debug */ = { 486 | isa = XCBuildConfiguration; 487 | buildSettings = { 488 | CLANG_ENABLE_MODULES = YES; 489 | CODE_SIGN_IDENTITY = ""; 490 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 491 | DEFINES_MODULE = YES; 492 | DEVELOPMENT_TEAM = DDWF823A49; 493 | DYLIB_COMPATIBILITY_VERSION = 1; 494 | DYLIB_CURRENT_VERSION = 1; 495 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 496 | FRAMEWORK_SEARCH_PATHS = ""; 497 | INFOPLIST_FILE = ZVProgressHUD/Info.plist; 498 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 499 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 500 | LD_RUNPATH_SEARCH_PATHS = ( 501 | "$(inherited)", 502 | "@executable_path/Frameworks", 503 | "@loader_path/Frameworks", 504 | ); 505 | PRODUCT_BUNDLE_IDENTIFIER = com.zevwings.ZVProgressHUD; 506 | PRODUCT_NAME = "$(TARGET_NAME)"; 507 | SKIP_INSTALL = YES; 508 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 509 | SWIFT_VERSION = 5.0; 510 | }; 511 | name = Debug; 512 | }; 513 | 4D5BDAA31F146CAC00E68CB6 /* Release */ = { 514 | isa = XCBuildConfiguration; 515 | buildSettings = { 516 | CLANG_ENABLE_MODULES = YES; 517 | CODE_SIGN_IDENTITY = ""; 518 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 519 | DEFINES_MODULE = YES; 520 | DEVELOPMENT_TEAM = DDWF823A49; 521 | DYLIB_COMPATIBILITY_VERSION = 1; 522 | DYLIB_CURRENT_VERSION = 1; 523 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 524 | FRAMEWORK_SEARCH_PATHS = ""; 525 | INFOPLIST_FILE = ZVProgressHUD/Info.plist; 526 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 527 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 528 | LD_RUNPATH_SEARCH_PATHS = ( 529 | "$(inherited)", 530 | "@executable_path/Frameworks", 531 | "@loader_path/Frameworks", 532 | ); 533 | PRODUCT_BUNDLE_IDENTIFIER = com.zevwings.ZVProgressHUD; 534 | PRODUCT_NAME = "$(TARGET_NAME)"; 535 | SKIP_INSTALL = YES; 536 | SWIFT_VERSION = 5.0; 537 | }; 538 | name = Release; 539 | }; 540 | 4DFF5B5920318D7A0098BA7D /* Debug */ = { 541 | isa = XCBuildConfiguration; 542 | buildSettings = { 543 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 544 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 545 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 546 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 547 | CODE_SIGN_IDENTITY = "iPhone Developer"; 548 | CODE_SIGN_STYLE = Automatic; 549 | DEVELOPMENT_TEAM = DDWF823A49; 550 | FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/Carthage/Build/iOS"; 551 | GCC_C_LANGUAGE_STANDARD = gnu11; 552 | INFOPLIST_FILE = ZVProgressHUDExample/Info.plist; 553 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 554 | LD_RUNPATH_SEARCH_PATHS = ( 555 | "$(inherited)", 556 | "@executable_path/Frameworks", 557 | ); 558 | OTHER_LDFLAGS = ""; 559 | PRODUCT_BUNDLE_IDENTIFIER = com.zevwings.ZVProgressHUDExample; 560 | PRODUCT_NAME = "$(TARGET_NAME)"; 561 | SWIFT_VERSION = 5.0; 562 | TARGETED_DEVICE_FAMILY = "1,2"; 563 | }; 564 | name = Debug; 565 | }; 566 | 4DFF5B5A20318D7A0098BA7D /* Release */ = { 567 | isa = XCBuildConfiguration; 568 | buildSettings = { 569 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 570 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 571 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 572 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 573 | CODE_SIGN_IDENTITY = "iPhone Developer"; 574 | CODE_SIGN_STYLE = Automatic; 575 | DEVELOPMENT_TEAM = DDWF823A49; 576 | FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/Carthage/Build/iOS"; 577 | GCC_C_LANGUAGE_STANDARD = gnu11; 578 | INFOPLIST_FILE = ZVProgressHUDExample/Info.plist; 579 | IPHONEOS_DEPLOYMENT_TARGET = 12.0; 580 | LD_RUNPATH_SEARCH_PATHS = ( 581 | "$(inherited)", 582 | "@executable_path/Frameworks", 583 | ); 584 | OTHER_LDFLAGS = ""; 585 | PRODUCT_BUNDLE_IDENTIFIER = com.zevwings.ZVProgressHUDExample; 586 | PRODUCT_NAME = "$(TARGET_NAME)"; 587 | SWIFT_VERSION = 5.0; 588 | TARGETED_DEVICE_FAMILY = "1,2"; 589 | }; 590 | name = Release; 591 | }; 592 | /* End XCBuildConfiguration section */ 593 | 594 | /* Begin XCConfigurationList section */ 595 | 4D5BDA871F146CAC00E68CB6 /* Build configuration list for PBXProject "ZVProgressHUD" */ = { 596 | isa = XCConfigurationList; 597 | buildConfigurations = ( 598 | 4D5BDA9F1F146CAC00E68CB6 /* Debug */, 599 | 4D5BDAA01F146CAC00E68CB6 /* Release */, 600 | ); 601 | defaultConfigurationIsVisible = 0; 602 | defaultConfigurationName = Release; 603 | }; 604 | 4D5BDAA11F146CAC00E68CB6 /* Build configuration list for PBXNativeTarget "ZVProgressHUD" */ = { 605 | isa = XCConfigurationList; 606 | buildConfigurations = ( 607 | 4D5BDAA21F146CAC00E68CB6 /* Debug */, 608 | 4D5BDAA31F146CAC00E68CB6 /* Release */, 609 | ); 610 | defaultConfigurationIsVisible = 0; 611 | defaultConfigurationName = Release; 612 | }; 613 | 4DFF5B5820318D7A0098BA7D /* Build configuration list for PBXNativeTarget "ZVProgressHUDExample" */ = { 614 | isa = XCConfigurationList; 615 | buildConfigurations = ( 616 | 4DFF5B5920318D7A0098BA7D /* Debug */, 617 | 4DFF5B5A20318D7A0098BA7D /* Release */, 618 | ); 619 | defaultConfigurationIsVisible = 0; 620 | defaultConfigurationName = Release; 621 | }; 622 | /* End XCConfigurationList section */ 623 | 624 | /* Begin XCRemoteSwiftPackageReference section */ 625 | 4DB03AC82531B329003F8300 /* XCRemoteSwiftPackageReference "ZVActivityIndicatorView" */ = { 626 | isa = XCRemoteSwiftPackageReference; 627 | repositoryURL = "https://github.com/zevwings/ZVActivityIndicatorView.git"; 628 | requirement = { 629 | kind = upToNextMajorVersion; 630 | minimumVersion = 0.2.3; 631 | }; 632 | }; 633 | /* End XCRemoteSwiftPackageReference section */ 634 | 635 | /* Begin XCSwiftPackageProductDependency section */ 636 | 4DB03AC92531B329003F8300 /* ZVActivityIndicatorView */ = { 637 | isa = XCSwiftPackageProductDependency; 638 | package = 4DB03AC82531B329003F8300 /* XCRemoteSwiftPackageReference "ZVActivityIndicatorView" */; 639 | productName = ZVActivityIndicatorView; 640 | }; 641 | /* End XCSwiftPackageProductDependency section */ 642 | }; 643 | rootObject = 4D5BDA841F146CAC00E68CB6 /* Project object */; 644 | } 645 | -------------------------------------------------------------------------------- /ZVProgressHUD/ZVProgressHUD.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ZVProgressHUD.swift 3 | // ZVProgressHUD 4 | // 5 | // Created by zevwings on 2017/7/12. 6 | // Copyright © 2017-2019 zevwings. All rights reserved. 7 | // 8 | 9 | #if !os(macOS) 10 | 11 | import UIKit 12 | 13 | // MARK: - Notifications 14 | 15 | public extension Notification.Name { 16 | 17 | static let ZVProgressHUDReceivedTouchUpInsideEvent = Notification.Name("com.zevwings.progresshud.touchup.inside") 18 | 19 | static let ZVProgressHUDWillAppear = Notification.Name("com.zevwings.progresshud.willAppear") 20 | static let ZVProgressHUDDidAppear = Notification.Name("com.zevwings.progresshud.didAppear") 21 | 22 | static let ZVProgressHUDWillDisappear = Notification.Name("com.zevwings.progresshud.willDisappear") 23 | static let ZVProgressHUDDidDisappear = Notification.Name("com.zevwings.progresshud.didDisappear") 24 | } 25 | 26 | // MARK: - ZVProgressHUD 27 | 28 | open class ZVProgressHUD: UIControl { 29 | 30 | public typealias CompletionHandler = () -> Void 31 | 32 | public struct Configuration { 33 | 34 | public var displayStyle: DisplayStyle = .light 35 | public var maskType: MaskType = .none 36 | public var position: Position = .center 37 | 38 | public var cornerRadius: CGFloat = 8.0 39 | public var offset: UIOffset = .zero 40 | 41 | public var titleLabelFont: UIFont = .systemFont(ofSize: 16.0) 42 | public var titleLabelColor: UIColor? 43 | 44 | public var progressForegroundColor: UIColor? 45 | public var progressBackgroundColor: UIColor? 46 | public var progressLabelFont: UIFont = .systemFont(ofSize: 12.0) 47 | public var progressLabelColor: UIColor? 48 | public var isProgressLabelHidden: Bool = false 49 | 50 | public var strokeWidth: CGFloat = 3.0 51 | public var animationType: ZVIndicatorView.AnimationType = .flat 52 | 53 | public var contentInsets = UIEdgeInsets(top: 24.0, left: 24.0, bottom: 24.0, right: 24.0) 54 | public var titleEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0 ) 55 | public var indicatorEdgeInsets = UIEdgeInsets(top: 12.0, left: 12.0, bottom: 12.0, right: 12.0) 56 | 57 | public var indicatorSize = CGSize(width: 56.0, height: 56.0) 58 | 59 | public var logo: UIImage? 60 | public var logoSize = CGSize(width: 30.0, height: 30.0) 61 | 62 | public init() {} 63 | } 64 | 65 | public enum DisplayType { 66 | case indicator(title: String?, type: ZVIndicatorView.IndicatorType) 67 | case text(value: String) 68 | case customeView(view: UIView) 69 | } 70 | 71 | public enum DisplayStyle { 72 | case light 73 | case dark 74 | case custom((backgroundColor: UIColor, foregroundColor: UIColor)) 75 | } 76 | 77 | public enum MaskType { 78 | case none 79 | case clear 80 | case black 81 | case custom(color: UIColor) 82 | } 83 | 84 | public enum Position { 85 | case top 86 | case center 87 | case bottom 88 | } 89 | 90 | private struct AnimationDuration { 91 | static let fadeIn: TimeInterval = 0.15 92 | static let fadeOut: TimeInterval = 0.15 93 | static let keyboard: TimeInterval = 0.25 94 | } 95 | 96 | // MARK: Public 97 | 98 | internal static let shared = ZVProgressHUD(frame: .zero) 99 | 100 | var maxSupportedWindowLevel: UIWindow.Level = .normal 101 | 102 | var fadeInAnimationTimeInterval: TimeInterval = ZVProgressHUD.AnimationDuration.fadeIn 103 | var fadeOutAnimationTImeInterval: TimeInterval = ZVProgressHUD.AnimationDuration.fadeOut 104 | 105 | var minimumDismissTimeInterval: TimeInterval = 3.0 106 | var maximumDismissTimeInterval: TimeInterval = 10.0 107 | 108 | // swiftlint:disable:next line_length 109 | var maximumContentSize = CGSize(width: UIScreen.main.bounds.width * 0.618, height: UIScreen.main.bounds.width * 0.618) 110 | // swiftlint:disable:previous: line_length 111 | 112 | /// 全局配置属性 113 | internal var configuration = Configuration() 114 | 115 | // MARK: Private 116 | 117 | private var _fadeOutTimer: Timer? 118 | private var _fadeInDeleyTimer: Timer? 119 | private var _fadeOutDelayTimer: Timer? 120 | 121 | private var _displayType: DisplayType? 122 | public var displayType: DisplayType? { 123 | return _displayType 124 | } 125 | 126 | private var _containerView: UIView? 127 | 128 | /// 展示自定视图时,保存临时视图 129 | private weak var _tempCustomView: UIView? 130 | 131 | /// 临时配置属性,在`HUD`消失时,清空 132 | private var _tempConfiguration: Configuration? 133 | 134 | // MARK: UI 135 | 136 | private lazy var maskLayer: CALayer = { [unowned self] in 137 | let maskLayer = CALayer() 138 | return maskLayer 139 | }() 140 | 141 | private lazy var baseView: UIControl = { 142 | let baseView = UIControl() 143 | baseView.backgroundColor = .clear 144 | baseView.alpha = 0 145 | baseView.layer.masksToBounds = true 146 | return baseView 147 | }() 148 | 149 | private lazy var indicatorView: ZVIndicatorView = { 150 | let indicatorView = ZVIndicatorView() 151 | indicatorView.isUserInteractionEnabled = false 152 | indicatorView.alpha = 0 153 | return indicatorView 154 | }() 155 | 156 | private lazy var titleLabel: UILabel = { [unowned self] in 157 | 158 | let titleLabel = UILabel(frame: .zero) 159 | titleLabel.minimumScaleFactor = 0.5 160 | titleLabel.textAlignment = .center 161 | titleLabel.isUserInteractionEnabled = false 162 | titleLabel.backgroundColor = .clear 163 | titleLabel.lineBreakMode = .byTruncatingTail 164 | titleLabel.numberOfLines = 0 165 | titleLabel.alpha = 0 166 | return titleLabel 167 | }() 168 | 169 | private lazy var logoView: UIImageView = { [unowned self] in 170 | 171 | let logoView = UIImageView(frame: .zero) 172 | logoView.contentMode = .scaleAspectFit 173 | logoView.layer.masksToBounds = true 174 | return logoView 175 | }() 176 | 177 | // MARK: Init 178 | 179 | deinit { 180 | NotificationCenter.default.removeObserver(self) 181 | } 182 | 183 | private override init(frame: CGRect) { 184 | super.init(frame: frame) 185 | 186 | alpha = 0 187 | backgroundColor = .clear 188 | 189 | addTarget(self, action: #selector(overlayRecievedTouchUpInsideEvent(_:)), for: .touchUpInside) 190 | } 191 | 192 | public required init?(coder aDecoder: NSCoder) { 193 | fatalError("init(coder:) has not been implemented") 194 | } 195 | } 196 | 197 | // MARK: - Internal Operations 198 | 199 | extension ZVProgressHUD { 200 | 201 | func internalShow( 202 | displayType: DisplayType, 203 | in superview: UIView?, 204 | delay delayTimeInterval: TimeInterval, 205 | with configuration: Configuration? 206 | ) { 207 | OperationQueue.main.addOperation { [weak self] in 208 | 209 | guard let `self` = self else { return } 210 | 211 | self._tempConfiguration = configuration 212 | 213 | if self.superview != superview { 214 | self.indicatorView.removeFromSuperview() 215 | self.titleLabel.removeFromSuperview() 216 | self.baseView.removeFromSuperview() 217 | self.logoView.removeFromSuperview() 218 | self.removeFromSuperview() 219 | } 220 | 221 | /// 确保自定义视图不会重复添加 222 | if let customView = self._tempCustomView { 223 | customView.removeFromSuperview() 224 | } 225 | 226 | self.fadeOutTimer = nil 227 | self.fadeInDeleyTimer = nil 228 | self.fadeOutDelayTimer = nil 229 | 230 | if let superview = superview { 231 | self._containerView = superview 232 | } else { 233 | self._containerView = self.getKeyWindow() 234 | } 235 | 236 | // set property form displayType 237 | self._displayType = displayType 238 | 239 | self.updateViewHierarchy() 240 | 241 | // set property form maskType 242 | self.isUserInteractionEnabled = self.maskType.isUserInteractionEnabled 243 | self.maskLayer.backgroundColor = self.maskType.backgroundColor 244 | 245 | self.baseView.layer.cornerRadius = self.cornerRadius 246 | self.baseView.backgroundColor = self.displayStyle.backgroundColor 247 | 248 | self.titleLabel.text = displayType.title 249 | self.titleLabel.isHidden = displayType.title.isEmpty 250 | self.titleLabel.font = self.titleLabelFont 251 | self.titleLabel.textColor = self.titleLabelColor 252 | 253 | self.indicatorView.indcatorType = displayType.indicatorType 254 | self.indicatorView.strokeWidth = self.strokeWidth 255 | self.indicatorView.tintColor = self.displayStyle.foregroundColor 256 | self.indicatorView.progressForegroundColor = self.progressForegroundColor 257 | self.indicatorView.progressBackgroundColor = self.progressBackgroundColor 258 | self.indicatorView.progressLabelFont = self.progressLabelFont 259 | self.indicatorView.progressLabelColor = self.progressLabelColor 260 | self.indicatorView.isProgressLabelHidden = self.isProgressLabelHidden 261 | 262 | self.logoView.image = self.logo 263 | self.logoView.tintColor = self.displayStyle.foregroundColor 264 | 265 | // display 266 | if delayTimeInterval > 0 { 267 | self.fadeInDeleyTimer = Timer.scheduledTimer( 268 | timeInterval: delayTimeInterval, 269 | target: self, 270 | selector: #selector(self.fadeInTimerAction(_:)), 271 | userInfo: nil, 272 | repeats: false 273 | ) 274 | } else { 275 | self.fadeIn() 276 | } 277 | } 278 | } 279 | 280 | func internalDismiss( 281 | with delayTimeInterval: TimeInterval = 0, 282 | completion: CompletionHandler? = nil 283 | ) { 284 | 285 | if delayTimeInterval > 0 { 286 | fadeOutDelayTimer = Timer.scheduledTimer( 287 | timeInterval: delayTimeInterval, 288 | target: self, 289 | selector: #selector(fadeOutTimerAction(_:)), 290 | userInfo: completion, 291 | repeats: false 292 | ) 293 | } else { 294 | fadeOut(with: completion) 295 | } 296 | } 297 | 298 | @objc private func fadeInTimerAction(_ timer: Timer?) { 299 | fadeIn() 300 | } 301 | 302 | @objc private func fadeIn() { 303 | 304 | guard let displayType = _displayType else { return } 305 | 306 | // swiftlint:disable:next line_length 307 | let displayTimeInterval = displayType.getDisplayTimeInterval(minimumDismissTimeInterval, maximumDismissTimeInterval) 308 | // swiftlint:disable:previous: line_length 309 | 310 | updateSubviews() 311 | 312 | let keybordHeight = getVisibleKeyboardHeight() 313 | placeSubviews(keybordHeight) 314 | 315 | if self.alpha != 1.0 { 316 | 317 | // send the notification HUD will appear 318 | NotificationCenter.default.post(name: .ZVProgressHUDWillAppear, object: self, userInfo: nil) 319 | 320 | let animationBlock = { 321 | self.alpha = 1.0 322 | self.baseView.alpha = 1.0 323 | self.indicatorView.alpha = 1.0 324 | self.titleLabel.alpha = 1.0 325 | } 326 | 327 | let completionBlock = { 328 | 329 | guard self.alpha == 1.0 else { return } 330 | 331 | self.fadeInDeleyTimer = nil 332 | 333 | // register keyboard notification and orientation notification 334 | self.registerNotifications() 335 | 336 | // send the notification HUD did appear 337 | NotificationCenter.default.post(name: .ZVProgressHUDDidAppear, object: self, userInfo: nil) 338 | 339 | if displayTimeInterval > 0 { 340 | self.fadeOutTimer = Timer.scheduledTimer( 341 | timeInterval: displayTimeInterval, 342 | target: self, 343 | selector: #selector(self.fadeOutTimerAction(_:)), 344 | userInfo: nil, 345 | repeats: false 346 | ) 347 | RunLoop.main.add(self.fadeOutTimer!, forMode: RunLoop.Mode.common) 348 | } else { 349 | if displayType.indicatorType.progressValueChecker.0 && 350 | displayType.indicatorType.progressValueChecker.1 >= 1.0 { 351 | self.internalDismiss() 352 | } 353 | } 354 | } 355 | 356 | if fadeInAnimationTimeInterval > 0 { 357 | UIView.animate( 358 | withDuration: fadeInAnimationTimeInterval, 359 | delay: 0, 360 | options: [.allowUserInteraction, .curveEaseOut, .beginFromCurrentState], 361 | animations: { 362 | animationBlock() 363 | }, completion: { _ in 364 | completionBlock() 365 | } 366 | ) 367 | } else { 368 | animationBlock() 369 | completionBlock() 370 | } 371 | } else { 372 | 373 | if displayTimeInterval > 0 { 374 | fadeOutTimer = Timer.scheduledTimer( 375 | timeInterval: displayTimeInterval, 376 | target: self, 377 | selector: #selector(self.fadeOutTimerAction(_:)), 378 | userInfo: nil, 379 | repeats: false 380 | ) 381 | RunLoop.main.add(fadeOutTimer!, forMode: RunLoop.Mode.common) 382 | } else { 383 | if displayType.indicatorType.progressValueChecker.0 && 384 | displayType.indicatorType.progressValueChecker.1 >= 1.0 { 385 | fadeOut() 386 | } 387 | } 388 | } 389 | } 390 | 391 | @objc private func fadeOutTimerAction(_ timer: Timer?) { 392 | 393 | let completion = timer?.userInfo as? CompletionHandler 394 | fadeOut(with: completion) 395 | } 396 | 397 | @objc private func fadeOut(with completion: CompletionHandler? = nil) { 398 | 399 | OperationQueue.main.addOperation { [weak self] in 400 | 401 | guard let `self` = self else { return } 402 | 403 | // send the notification HUD will disAppear 404 | NotificationCenter.default.post(name: .ZVProgressHUDWillDisappear, object: self, userInfo: nil) 405 | 406 | let animationBlock = { 407 | self.alpha = 0 408 | self.baseView.alpha = 0 409 | self.baseView.backgroundColor = .clear 410 | self.indicatorView.alpha = 0 411 | self.titleLabel.alpha = 0 412 | } 413 | 414 | let completionBlock = { 415 | 416 | guard self.alpha == 0 else { return } 417 | 418 | self.fadeOutTimer = nil 419 | self.fadeOutDelayTimer = nil 420 | 421 | // update view hierarchy 422 | self.indicatorView.removeFromSuperview() 423 | self.titleLabel.removeFromSuperview() 424 | self.baseView.removeFromSuperview() 425 | self.logoView.removeFromSuperview() 426 | self.removeFromSuperview() 427 | 428 | self._containerView = nil 429 | 430 | // remove notifications from self 431 | NotificationCenter.default.removeObserver(self) 432 | 433 | // send the notification HUD did disAppear 434 | NotificationCenter.default.post(name: .ZVProgressHUDDidDisappear, object: self, userInfo: nil) 435 | 436 | // execute completion handler 437 | completion?() 438 | 439 | self._tempConfiguration = nil 440 | } 441 | 442 | if self.fadeOutAnimationTImeInterval > 0 { 443 | UIView.animate( 444 | withDuration: self.fadeOutAnimationTImeInterval, 445 | delay: 0, 446 | options: [.allowUserInteraction, .curveEaseOut, .beginFromCurrentState], 447 | animations: { 448 | animationBlock() 449 | }, completion: { _ in 450 | completionBlock() 451 | } 452 | ) 453 | } else { 454 | animationBlock() 455 | completionBlock() 456 | } 457 | 458 | self.setNeedsDisplay() 459 | } 460 | } 461 | } 462 | 463 | // MARK: - Update Subviews 464 | 465 | private extension ZVProgressHUD { 466 | 467 | func updateViewHierarchy() { 468 | 469 | guard let displayType = _displayType else { return } 470 | 471 | self.isUserInteractionEnabled = self.maskType.isUserInteractionEnabled 472 | 473 | if superview == nil { 474 | _containerView?.addSubview(self) 475 | } else { 476 | _containerView?.bringSubviewToFront(self) 477 | } 478 | 479 | if maskLayer.superlayer == nil { 480 | layer.addSublayer(maskLayer) 481 | } 482 | 483 | self.maskLayer.backgroundColor = self.maskType.backgroundColor 484 | 485 | if baseView.superview == nil { 486 | addSubview(baseView) 487 | } else { 488 | bringSubviewToFront(baseView) 489 | } 490 | 491 | baseView.layer.cornerRadius = cornerRadius 492 | baseView.backgroundColor = displayStyle.backgroundColor 493 | 494 | switch displayType { 495 | case let .indicator(title, indicatorType): 496 | updateIndicatorHierarchy(with: indicatorType) 497 | updateLabelHierarchy(with: title) 498 | case let .text(title): 499 | updateLabelHierarchy(with: title) 500 | case let .customeView(view): 501 | _tempCustomView = view 502 | baseView.addSubview(view) 503 | } 504 | } 505 | 506 | /// 更新 指示视图视图层级 507 | func updateIndicatorHierarchy(with indicatorType: ZVIndicatorView.IndicatorType) { 508 | 509 | if indicatorType.showLogo && logo != nil && logoView.superview == nil { 510 | baseView.addSubview(logoView) 511 | } else { 512 | baseView.bringSubviewToFront(logoView) 513 | } 514 | logoView.image = logo 515 | logoView.tintColor = displayStyle.foregroundColor 516 | 517 | /// 添加指示视图 518 | if indicatorView.superview == nil { 519 | baseView.addSubview(indicatorView) 520 | } else { 521 | baseView.bringSubviewToFront(indicatorView) 522 | } 523 | 524 | indicatorView.indcatorType = indicatorType 525 | } 526 | 527 | /// 更新描述标题视图层级 528 | func updateLabelHierarchy(with text: String?) { 529 | 530 | if titleLabel.superview == nil { 531 | baseView.addSubview(titleLabel) 532 | } else { 533 | baseView.bringSubviewToFront(titleLabel) 534 | } 535 | 536 | titleLabel.text = text 537 | titleLabel.isHidden = false 538 | titleLabel.font = titleLabelFont 539 | titleLabel.textColor = titleLabelColor 540 | } 541 | 542 | func updateSubviews() { 543 | 544 | guard let containerView = _containerView, let displayType = _displayType else { return } 545 | 546 | frame = CGRect(origin: .zero, size: containerView.frame.size) 547 | maskLayer.frame = CGRect(origin: .zero, size: containerView.frame.size) 548 | 549 | switch displayType { 550 | case .indicator, .text: 551 | 552 | if !indicatorView.isHidden { 553 | indicatorView.frame = CGRect(origin: .zero, size: indicatorSize) 554 | } 555 | 556 | if let displayType = _displayType, displayType.indicatorType.showLogo, logo != nil { 557 | logoView.frame = CGRect(origin: .zero, size: logoSize) 558 | } 559 | 560 | var labelSize: CGSize = .zero 561 | if !titleLabel.isHidden, let title = titleLabel.text as NSString?, title.length > 0 { 562 | let attributes: [NSAttributedString.Key: Any] = [.font: titleLabelFont] 563 | let options: NSStringDrawingOptions = [ 564 | .usesFontLeading, 565 | .truncatesLastVisibleLine, 566 | .usesLineFragmentOrigin 567 | ] 568 | labelSize = title.boundingRect( 569 | with: maximumContentSize, 570 | options: options, 571 | attributes: attributes, 572 | context: nil 573 | ).size 574 | titleLabel.frame = CGRect(origin: .zero, size: labelSize) 575 | } 576 | 577 | let labelHeight = titleLabel.isHidden ? 0 : labelSize.height + titleEdgeInsets.top + titleEdgeInsets.bottom 578 | let indicatorHeight = indicatorView.isHidden ? 579 | 0 : 580 | indicatorSize.height + indicatorEdgeInsets.top + indicatorEdgeInsets.bottom 581 | 582 | let contentHeight = labelHeight + indicatorHeight + contentInsets.top + contentInsets.bottom 583 | let maxWidth = max(labelSize.width + titleEdgeInsets.left + titleEdgeInsets.right, 584 | indicatorSize.width + indicatorEdgeInsets.left + indicatorEdgeInsets.right) 585 | let contetnWidth = maxWidth + contentInsets.left + contentInsets.right 586 | 587 | let contentSize = CGSize(width: contetnWidth, height: contentHeight) 588 | let origin = self.baseView.frame.origin 589 | baseView.frame = CGRect(origin: origin, size: contentSize) 590 | 591 | CATransaction.begin() 592 | CATransaction.setDisableActions(true) 593 | 594 | let centerX: CGFloat = contetnWidth / 2.0 595 | var centerY: CGFloat = contentHeight / 2.0 596 | 597 | // Indicator 598 | if labelHeight > 0 && !indicatorView.isHidden { 599 | centerY = contentInsets.top + indicatorEdgeInsets.top + indicatorSize.height / 2.0 600 | } 601 | indicatorView.center = CGPoint(x: centerX, y: centerY) 602 | logoView.center = CGPoint(x: centerX, y: centerY) 603 | 604 | // Label 605 | if indicatorHeight > 0 && !titleLabel.isHidden { 606 | centerY = contentInsets.top + indicatorHeight + titleEdgeInsets.top + labelSize.height / 2.0 607 | } 608 | titleLabel.center = CGPoint(x: centerX, y: centerY) 609 | 610 | CATransaction.commit() 611 | 612 | case let .customeView(view): 613 | let origin = self.baseView.frame.origin 614 | baseView.frame = CGRect(origin: origin, size: view.frame.size) 615 | } 616 | } 617 | 618 | @objc func placeSubviews(_ keybordHeight: CGFloat = 0, animationDuration: TimeInterval = 0) { 619 | 620 | guard let containerView = _containerView else { return } 621 | 622 | frame = CGRect(origin: .zero, size: containerView.frame.size) 623 | maskLayer.frame = CGRect(origin: .zero, size: containerView.frame.size) 624 | 625 | let keyWindow = getKeyWindow() 626 | let orenitationFrame = frame 627 | var statusBarFrame: CGRect = .zero 628 | if containerView == keyWindow { 629 | statusBarFrame = UIApplication.shared.statusBarFrame 630 | } 631 | 632 | // safe area bottom height 633 | let bottomInset: CGFloat 634 | if #available(iOS 11.0, *) { 635 | bottomInset = keyWindow?.safeAreaInsets.bottom ?? 0.0 636 | } else { 637 | bottomInset = 0 638 | } 639 | 640 | // if tabBar is hidden, bottom instantce is 24.0 + 12.0 641 | // otherwise, if keyboard is show, ignore tabBar height. 642 | let defaultBottomInset: CGFloat 643 | if keybordHeight > 0 { 644 | defaultBottomInset = 0 645 | } else { 646 | let tabBarHeight = keyWindow?.rootViewController?.tabBarController?.tabBar.frame.height ?? 24.0 647 | defaultBottomInset = tabBarHeight + bottomInset 648 | } 649 | 650 | // if navigationBar is hidden, top instantce is 24.0 651 | let defaultTopInset: CGFloat 652 | if let navigationController = keyWindow?.rootViewController?.navigationController { 653 | defaultTopInset = navigationController.navigationBar.frame.height 654 | } else { 655 | defaultTopInset = 24.0 656 | } 657 | 658 | var activeHeight = orenitationFrame.height 659 | 660 | if keybordHeight > 0 { 661 | activeHeight += statusBarFrame.height * 2 662 | } 663 | 664 | activeHeight -= keybordHeight 665 | 666 | let distanceOfNavigationBarOrTabBar: CGFloat = 12 667 | 668 | // swiftlint:disable line_length 669 | let posY: CGFloat 670 | switch position { 671 | case .top: 672 | posY = defaultTopInset + statusBarFrame.height + distanceOfNavigationBarOrTabBar + baseView.frame.height * 0.5 + offset.vertical 673 | case .center: 674 | posY = activeHeight * 0.45 + offset.vertical 675 | case .bottom: 676 | posY = activeHeight - defaultBottomInset - distanceOfNavigationBarOrTabBar - baseView.frame.height * 0.5 + offset.vertical 677 | } 678 | // swiftlint:enable line_length 679 | 680 | let posX = orenitationFrame.width / 2.0 + offset.horizontal 681 | 682 | let center = CGPoint(x: posX, y: posY) 683 | 684 | if animationDuration == 0 { 685 | baseView.center = center 686 | } else { 687 | UIView.animate( 688 | withDuration: animationDuration, 689 | delay: 0, 690 | options: [.allowUserInteraction, .beginFromCurrentState], 691 | animations: { 692 | self.baseView.center = center 693 | self.baseView.setNeedsDisplay() 694 | }) 695 | } 696 | } 697 | } 698 | 699 | // MARK: - Event Handler 700 | 701 | private extension ZVProgressHUD { 702 | 703 | @objc func overlayRecievedTouchUpInsideEvent(_ sender: UIControl) { 704 | NotificationCenter.default.post(name: .ZVProgressHUDReceivedTouchUpInsideEvent, object: self, userInfo: nil) 705 | } 706 | } 707 | 708 | // MARK: - Notifications 709 | 710 | private extension ZVProgressHUD { 711 | 712 | private func registerNotifications() { 713 | 714 | NotificationCenter.default.addObserver(self, 715 | selector: #selector(handleKeyboardNotification(_:)), 716 | name: UIApplication.didChangeStatusBarOrientationNotification, 717 | object: nil) 718 | 719 | NotificationCenter.default.addObserver(self, 720 | selector: #selector(handleKeyboardNotification(_:)), 721 | name: UIApplication.didBecomeActiveNotification, 722 | object: nil) 723 | 724 | NotificationCenter.default.addObserver(self, 725 | selector: #selector(handleKeyboardNotification(_:)), 726 | name: UIResponder.keyboardWillShowNotification, 727 | object: nil) 728 | 729 | NotificationCenter.default.addObserver(self, 730 | selector: #selector(handleKeyboardNotification(_:)), 731 | name: UIResponder.keyboardWillHideNotification, 732 | object: nil) 733 | 734 | NotificationCenter.default.addObserver(self, 735 | selector: #selector(handleKeyboardNotification(_:)), 736 | name: UIResponder.keyboardDidShowNotification, 737 | object: nil) 738 | 739 | NotificationCenter.default.addObserver(self, 740 | selector: #selector(handleKeyboardNotification(_:)), 741 | name: UIResponder.keyboardDidHideNotification, 742 | object: nil) 743 | } 744 | 745 | @objc func handleKeyboardNotification(_ notification: Notification?) { 746 | 747 | let orientation = UIApplication.shared.statusBarOrientation 748 | 749 | var keybordHeight: CGFloat = 0 750 | var animationDuration: TimeInterval = 0 751 | 752 | if let notification = notification, let keyboardInfo = notification.userInfo { 753 | let keyboardFrame = keyboardInfo[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect 754 | animationDuration = keyboardInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? TimeInterval ?? 0 755 | if notification.name == UIResponder.keyboardWillShowNotification || 756 | notification.name == UIResponder.keyboardDidShowNotification { 757 | if orientation == .portrait { 758 | keybordHeight = keyboardFrame?.height ?? 0 759 | } 760 | } 761 | } else { 762 | keybordHeight = getVisibleKeyboardHeight() 763 | } 764 | 765 | placeSubviews(keybordHeight, animationDuration: animationDuration) 766 | } 767 | } 768 | 769 | // MARK: - KeyWindow & Keyboard 770 | 771 | private extension ZVProgressHUD { 772 | 773 | func getKeyWindow() -> UIWindow? { 774 | 775 | var keyWindow: UIWindow? 776 | UIApplication.shared.windows.forEach { window in 777 | if window.screen == UIScreen.main, 778 | window.isHidden == false, 779 | window.alpha > 0, 780 | window.windowLevel >= UIWindow.Level.normal, 781 | window.windowLevel <= maxSupportedWindowLevel { 782 | keyWindow = window 783 | return 784 | } 785 | } 786 | return keyWindow 787 | } 788 | 789 | func getVisibleKeyboardHeight() -> CGFloat { 790 | 791 | var visibleKeyboardHeight: CGFloat = 0.0 792 | var keyboardWindow: UIWindow? 793 | UIApplication.shared.windows.reversed().forEach { window in 794 | let windowName = NSStringFromClass(window.classForCoder) 795 | if #available(iOS 9.0, *) { 796 | if windowName == "UIRemoteKeyboardWindow" { 797 | keyboardWindow = window 798 | return 799 | } 800 | } else { 801 | if windowName == "UITextEffectsWindow" { 802 | keyboardWindow = window 803 | return 804 | } 805 | } 806 | } 807 | 808 | var possibleKeyboard: UIView? 809 | keyboardWindow?.subviews.forEach({ subview in 810 | let viewClassName = NSStringFromClass(subview.classForCoder) 811 | if viewClassName.hasPrefix("UI") && viewClassName.hasSuffix("InputSetContainerView") { 812 | possibleKeyboard = subview 813 | return 814 | } 815 | }) 816 | 817 | possibleKeyboard?.subviews.forEach({ subview in 818 | let viewClassName = NSStringFromClass(subview.classForCoder) 819 | if viewClassName.hasPrefix("UI") && viewClassName.hasSuffix("InputSetHostView") { 820 | let convertedRect = possibleKeyboard?.convert(subview.frame, to: self) 821 | let intersectedRect = convertedRect?.intersection(self.bounds) 822 | visibleKeyboardHeight = intersectedRect?.height ?? 0.0 823 | return 824 | } 825 | }) 826 | 827 | return visibleKeyboardHeight 828 | } 829 | } 830 | 831 | // MARK: - Timers 832 | 833 | private extension ZVProgressHUD { 834 | 835 | var fadeOutTimer: Timer? { 836 | get { 837 | return _fadeOutTimer 838 | } 839 | set { 840 | if _fadeOutTimer != nil { 841 | _fadeOutTimer?.invalidate() 842 | _fadeOutTimer = nil 843 | } 844 | _fadeOutTimer = newValue 845 | } 846 | } 847 | 848 | var fadeInDeleyTimer: Timer? { 849 | get { 850 | return _fadeInDeleyTimer 851 | } 852 | set { 853 | if _fadeInDeleyTimer != nil { 854 | _fadeInDeleyTimer?.invalidate() 855 | _fadeInDeleyTimer = nil 856 | } 857 | _fadeInDeleyTimer = newValue 858 | } 859 | } 860 | 861 | var fadeOutDelayTimer: Timer? { 862 | get { 863 | return _fadeOutDelayTimer 864 | } 865 | set { 866 | if _fadeOutDelayTimer != nil { 867 | _fadeOutDelayTimer?.invalidate() 868 | _fadeOutDelayTimer = nil 869 | } 870 | _fadeOutDelayTimer = newValue 871 | } 872 | } 873 | } 874 | 875 | // MARK: - Props 876 | 877 | private extension ZVProgressHUD { 878 | 879 | var actualConfiguration: Configuration { 880 | if let configuration = _tempConfiguration { 881 | return configuration 882 | } 883 | return configuration 884 | } 885 | 886 | var displayStyle: DisplayStyle { 887 | return actualConfiguration.displayStyle 888 | } 889 | 890 | var maskType: MaskType { 891 | return actualConfiguration.maskType 892 | } 893 | 894 | var position: Position { 895 | return actualConfiguration.position 896 | } 897 | 898 | var cornerRadius: CGFloat { 899 | return actualConfiguration.cornerRadius 900 | } 901 | 902 | var offset: UIOffset { 903 | return actualConfiguration.offset 904 | } 905 | 906 | var titleLabelFont: UIFont { 907 | return actualConfiguration.titleLabelFont 908 | } 909 | 910 | var titleLabelColor: UIColor { 911 | if let color = _tempConfiguration?.titleLabelColor { 912 | return color 913 | } 914 | if let color = configuration.titleLabelColor { 915 | return color 916 | } 917 | return actualConfiguration.displayStyle.foregroundColor 918 | } 919 | 920 | var progressForegroundColor: UIColor { 921 | if let color = _tempConfiguration?.progressForegroundColor { 922 | return color 923 | } 924 | if let color = configuration.progressForegroundColor { 925 | return color 926 | } 927 | return actualConfiguration.displayStyle.foregroundColor 928 | } 929 | 930 | var progressBackgroundColor: UIColor { 931 | if let color = _tempConfiguration?.progressBackgroundColor { 932 | return color 933 | } 934 | if let color = configuration.progressBackgroundColor { 935 | return color 936 | } 937 | return actualConfiguration.displayStyle.foregroundColor.withAlphaComponent(0.5) 938 | } 939 | 940 | var progressLabelFont: UIFont { 941 | return actualConfiguration.progressLabelFont 942 | } 943 | 944 | var progressLabelColor: UIColor { 945 | if let color = _tempConfiguration?.progressLabelColor { 946 | return color 947 | } 948 | if let color = configuration.progressLabelColor { 949 | return color 950 | } 951 | return actualConfiguration.displayStyle.foregroundColor 952 | } 953 | 954 | var isProgressLabelHidden: Bool { 955 | return actualConfiguration.isProgressLabelHidden 956 | } 957 | 958 | var strokeWidth: CGFloat { 959 | return actualConfiguration.strokeWidth 960 | } 961 | 962 | var animationType: ZVIndicatorView.AnimationType { 963 | return actualConfiguration.animationType 964 | } 965 | 966 | var contentInsets: UIEdgeInsets { 967 | return actualConfiguration.contentInsets 968 | } 969 | var titleEdgeInsets: UIEdgeInsets { 970 | return actualConfiguration.titleEdgeInsets 971 | } 972 | 973 | var indicatorEdgeInsets: UIEdgeInsets { 974 | return actualConfiguration.indicatorEdgeInsets 975 | } 976 | 977 | var indicatorSize: CGSize { 978 | return actualConfiguration.indicatorSize 979 | } 980 | 981 | var logo: UIImage? { 982 | return actualConfiguration.logo 983 | } 984 | 985 | var logoSize: CGSize { 986 | return actualConfiguration.logoSize 987 | } 988 | 989 | } 990 | 991 | // MARK: - ZVProgressHUD.DisplayType 992 | 993 | extension ZVProgressHUD.DisplayType { 994 | 995 | var dismissAtomically: Bool { 996 | switch self { 997 | case .text: 998 | return true 999 | case .indicator(_, let type): 1000 | switch type { 1001 | case .success, .error, .warning: 1002 | return true 1003 | case .image(_, let dismissAtomically): 1004 | return dismissAtomically 1005 | default: 1006 | return false 1007 | } 1008 | case .customeView: 1009 | return false 1010 | } 1011 | } 1012 | 1013 | var title: String { 1014 | switch self { 1015 | case .text(let value): return value 1016 | case .indicator(let title, _): return title ?? "" 1017 | case .customeView: 1018 | return "" 1019 | } 1020 | } 1021 | 1022 | var indicatorType: ZVIndicatorView.IndicatorType { 1023 | switch self { 1024 | case .text: return .none 1025 | case .indicator(_, let type): return type 1026 | case .customeView: return .none 1027 | } 1028 | } 1029 | 1030 | func getDisplayTimeInterval( 1031 | _ minimumDismissTimeInterval: TimeInterval, 1032 | _ maximumDismissTimeInterval: TimeInterval 1033 | ) -> TimeInterval { 1034 | 1035 | var displayTimeInterval: TimeInterval = dismissAtomically ? 3.0 : 0 1036 | 1037 | guard displayTimeInterval > 0 else { return 0 } 1038 | 1039 | displayTimeInterval = max(Double(title.count) * 0.06 + 0.5, minimumDismissTimeInterval) 1040 | displayTimeInterval = min(displayTimeInterval, maximumDismissTimeInterval) 1041 | 1042 | return displayTimeInterval 1043 | } 1044 | 1045 | var customView: UIView? { 1046 | switch self { 1047 | case let .customeView(view): 1048 | return view 1049 | default: 1050 | return nil 1051 | } 1052 | } 1053 | } 1054 | 1055 | // MARK: - ZVProgressHUD.DisplayStyle 1056 | 1057 | extension ZVProgressHUD.DisplayStyle { 1058 | var foregroundColor: UIColor { 1059 | switch self { 1060 | case .dark: return .white 1061 | case .light: return UIColor(white: 0.2, alpha: 1) 1062 | case .custom(let (foregroundColor, _)): return foregroundColor 1063 | } 1064 | } 1065 | 1066 | var backgroundColor: UIColor { 1067 | switch self { 1068 | case .dark: return UIColor(white: 0, alpha: 0.75) 1069 | case .light: return .white 1070 | case .custom(let (_, backgroundColor)): return backgroundColor 1071 | } 1072 | } 1073 | } 1074 | 1075 | // MARK: - ZVProgressHUD.MaskType 1076 | 1077 | extension ZVProgressHUD.MaskType { 1078 | 1079 | var backgroundColor: CGColor { 1080 | switch self { 1081 | case .none, .clear: return UIColor.clear.cgColor 1082 | case .black: return UIColor.init(white: 0, alpha: 0.3).cgColor 1083 | case .custom(let color): return color.cgColor 1084 | } 1085 | } 1086 | 1087 | var isUserInteractionEnabled: Bool { 1088 | switch self { 1089 | case .none: return false 1090 | default: return true 1091 | } 1092 | } 1093 | } 1094 | 1095 | // MARK: - ZVIndicatorView.IndicatorType 1096 | 1097 | extension ZVIndicatorView.IndicatorType { 1098 | 1099 | var resource: String { 1100 | switch self { 1101 | case .error: 1102 | return "error" 1103 | case .success: 1104 | return "success" 1105 | case .warning: 1106 | return "warning" 1107 | default: 1108 | return "" 1109 | } 1110 | } 1111 | 1112 | var shouldHidden: Bool { 1113 | switch self { 1114 | case .none: 1115 | return true 1116 | default: 1117 | return false 1118 | } 1119 | } 1120 | 1121 | var progressValueChecker: (Bool, Float) { 1122 | switch self { 1123 | case .progress(let value): 1124 | return (true, value) 1125 | default: 1126 | return (false, 0.0) 1127 | } 1128 | } 1129 | 1130 | var showLogo: Bool { 1131 | switch self { 1132 | case .indicator(let animationType): 1133 | return animationType == .flat 1134 | default: 1135 | return false 1136 | } 1137 | } 1138 | } 1139 | 1140 | #endif 1141 | --------------------------------------------------------------------------------