├── Classes ├── UIViewController+XNProgressHUD.h ├── UIViewController+XNProgressHUD.m ├── XNAnimaionViewProtocol.h ├── XNHUDAnimationView │ ├── XNAnimationView.h │ ├── XNAnimationView.m │ ├── XNHUDErrorLayer.h │ ├── XNHUDErrorLayer.m │ ├── XNHUDInfoLayer.h │ ├── XNHUDInfoLayer.m │ ├── XNHUDLayerProtocol.h │ ├── XNHUDLoadingLayer.h │ ├── XNHUDLoadingLayer.m │ ├── XNHUDProgressLayer.h │ ├── XNHUDProgressLayer.m │ ├── XNHUDSuccessLayer.h │ └── XNHUDSuccessLayer.m ├── XNProgressHUD.h └── XNProgressHUD.m ├── LICENSE ├── README.md ├── XNProgressHUD.podspec ├── XNProgressHUD.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings │ └── xcuserdata │ │ ├── anker.xcuserdatad │ │ └── UserInterfaceState.xcuserstate │ │ ├── luohan.xcuserdatad │ │ ├── UserInterfaceState.xcuserstate │ │ └── WorkspaceSettings.xcsettings │ │ └── ocean.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ ├── anker.xcuserdatad │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ │ └── xcschememanagement.plist │ ├── luohan.xcuserdatad │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ │ └── xcschememanagement.plist │ └── ocean.xcuserdatad │ └── xcschemes │ └── xcschememanagement.plist ├── XNProgressHUD ├── 1.0.3 │ └── XNProgressHUD.podspec ├── 1.0.4 │ └── XNProgressHUD.podspec ├── 1.0.5 │ └── XNProgressHUD.podspec ├── 1.0.7 │ └── XNProgressHUD.podspec ├── 1.0.8 │ └── XNProgressHUD.podspec ├── 1.0.9 │ └── XNProgressHUD.podspec ├── 1.1.0 │ └── XNProgressHUD.podspec └── 1.1.1 │ └── XNProgressHUD.podspec └── demo ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets ├── AppIcon.appiconset │ └── Contents.json ├── Contents.json └── image │ ├── Contents.json │ ├── ico_xnprogresshud_error.imageset │ ├── Contents.json │ ├── ico_xnprogresshud_error@2x.png │ └── ico_xnprogresshud_error@3x.png │ ├── ico_xnprogresshud_info.imageset │ ├── Contents.json │ ├── ico_xnprogresshud_info@2x.png │ └── ico_xnprogresshud_info@3x.png │ └── ico_xnprogresshud_success.imageset │ ├── Contents.json │ ├── ico_xnprogresshud_success@2x.png │ └── ico_xnprogresshud_success@3x.png ├── Base.lproj ├── LaunchScreen.storyboard └── Main.storyboard ├── Info.plist ├── ViewController.h ├── ViewController.m ├── custom ├── CustomHUDLoadingLayer.h └── CustomHUDLoadingLayer.m └── main.m /Classes/UIViewController+XNProgressHUD.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+XNProgressHUD.h 3 | // Pods 4 | // 5 | // Created by 罗函 on 2018/3/23. 6 | // 7 | 8 | #import 9 | #import "XNProgressHUD.h" 10 | 11 | #pragma mark - show hud on viewcontroller 12 | @interface UIViewController (XNProgressHUD) 13 | - (XNProgressHUD *)hud; 14 | @end 15 | -------------------------------------------------------------------------------- /Classes/UIViewController+XNProgressHUD.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+XNProgressHUD.m 3 | // Pods 4 | // 5 | // Created by 罗函 on 2018/3/23. 6 | // 7 | 8 | #import "UIViewController+XNProgressHUD.h" 9 | #import 10 | 11 | #pragma mark - show hud on viewcontroller 12 | static char VCXNProgressHUD; 13 | @implementation UIViewController (XNProgressHUD) 14 | 15 | - (void)setHud:(XNProgressHUD *)hud { 16 | objc_setAssociatedObject(self, &VCXNProgressHUD, hud, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 17 | } 18 | 19 | - (XNProgressHUD *)hud { 20 | XNProgressHUD *hudView = objc_getAssociatedObject(self, &VCXNProgressHUD); 21 | if(!hudView) { 22 | hudView = [[XNProgressHUD alloc] init]; 23 | hudView.targetView = self.view; 24 | [self setHud:hudView]; 25 | } 26 | return hudView; 27 | } 28 | 29 | + (void)load { 30 | [self exchangeMethod:@"viewDidDisappear:" exchangeMethod:@selector(vcViewDidDisappear:)]; 31 | } 32 | 33 | + (void)exchangeMethod:(NSString *)originalMethodStr exchangeMethod:(SEL)exchangeMethodSel { 34 | Method originalMethod = class_getInstanceMethod([self class], NSSelectorFromString(originalMethodStr)); 35 | Method exchangeMethod = class_getInstanceMethod([self class], exchangeMethodSel); 36 | if (!class_addMethod([self class], exchangeMethodSel, method_getImplementation(exchangeMethod), method_getTypeEncoding(exchangeMethod))) { 37 | method_exchangeImplementations(exchangeMethod, originalMethod); 38 | } 39 | } 40 | 41 | - (void)vcViewDidDisappear:(BOOL)animated { 42 | [self vcViewDidDisappear:animated]; 43 | XNProgressHUD *hudView = objc_getAssociatedObject(self, &VCXNProgressHUD); 44 | if(hudView) { 45 | [hudView clearUp]; 46 | hudView = nil; 47 | } 48 | } 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /Classes/XNAnimaionViewProtocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // XNAnimaionViewProtocol.h 3 | // Pods 4 | // 5 | // Created by 罗函 on 2018/3/22. 6 | // 7 | 8 | #import 9 | #import "XNProgressHUD.h" 10 | 11 | @protocol XNAnimaionViewProtocol 12 | /* 13 | * 自定义加载视图时,需要实现以下协议方法 14 | */ 15 | - (NSNumber *)xn_isAnimating; 16 | - (NSNumber *)xn_getStyle; 17 | - (void)xn_setStyle:(NSNumber *)styleValue; 18 | - (void)xn_setProgress:(NSNumber *)progressValue; 19 | - (void)xn_startAnimation; 20 | - (void)xn_stopAnimation; 21 | @end 22 | 23 | -------------------------------------------------------------------------------- /Classes/XNHUDAnimationView/XNAnimationView.h: -------------------------------------------------------------------------------- 1 | // 2 | // XNAnimationView.h 3 | // XNProgressHUD 4 | // 5 | // Created by jarvis on 2019/7/20. 6 | // Copyright © 2019 罗函. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "XNAnimaionViewProtocol.h" 11 | #import "XNHUDLayerProtocol.h" 12 | 13 | NS_ASSUME_NONNULL_BEGIN 14 | 15 | //@class XNHUDLoadingLayer, XNHUDErrorLayer, XNHUDSuccessLayer, XNHUDProgressLayer, XNHUDInfoLayer; 16 | @interface XNAnimationView : UIView 17 | @property (nonatomic, assign) XNAnimationViewStyle style; 18 | @property (nonatomic, strong) CALayer *loadingLayer; 19 | @property (nonatomic, strong) CALayer *errorLayer; 20 | @property (nonatomic, strong) CALayer *successLayer; 21 | @property (nonatomic, strong) CALayer *progressLayer; 22 | @property (nonatomic, strong) CALayer *infoLayer; 23 | @property (nonatomic, assign) CGFloat progress; 24 | @property (nonatomic, readwrite) NSTimeInterval duration; 25 | @property (nullable, nonatomic, strong) CAMediaTimingFunction *timingFunction; 26 | @property (nonatomic, readwrite) CGFloat lineWidth; 27 | @property (nullable, nonatomic, readwrite) UIColor *tintColor; 28 | @property (nullable, nonatomic, readwrite) UIColor *tintBGColor; 29 | @property (nullable, nonatomic, strong) UIImage *infoImage; 30 | @property (nullable, nonatomic, strong) UIImage *errorImage; 31 | @property (nullable, nonatomic, strong) UIImage *successImage; 32 | @end 33 | 34 | NS_ASSUME_NONNULL_END 35 | -------------------------------------------------------------------------------- /Classes/XNHUDAnimationView/XNAnimationView.m: -------------------------------------------------------------------------------- 1 | // 2 | // XNAnimationView.m 3 | // XNProgressHUD 4 | // 5 | // Created by jarvis on 2019/7/20. 6 | // Copyright © 2019 罗函. All rights reserved. 7 | // 8 | 9 | #import "XNAnimationView.h" 10 | #import "XNHUDLoadingLayer.h" 11 | #import "XNHUDErrorLayer.h" 12 | #import "XNHUDSuccessLayer.h" 13 | #import "XNHUDProgressLayer.h" 14 | #import "XNHUDInfoLayer.h" 15 | 16 | @interface XNAnimationView() 17 | @property (nonatomic, assign) BOOL isFirst; 18 | @property (nonatomic, assign, getter=isAnimating) BOOL animating; 19 | @property (nonatomic, strong) UIImageView *imageView; 20 | @property (nonatomic, strong) NSMutableArray *pointLayers; 21 | @end 22 | 23 | @implementation XNAnimationView 24 | 25 | - (instancetype)init { 26 | if(!(self = [super init])) return nil; 27 | [self initialize]; 28 | return self; 29 | } 30 | 31 | - (instancetype)initWithFrame:(CGRect)frame { 32 | if(!(self = [super initWithFrame:frame])) return nil; 33 | [self initialize]; 34 | return self; 35 | } 36 | 37 | - (void)initialize { 38 | _duration = 2.0f; 39 | _lineWidth = 2.f; 40 | _tintColor = [UIColor colorWithRed:237/255.f green:36/255.f blue:95/255.f alpha:1.f]; 41 | _tintBGColor = [_tintColor colorWithAlphaComponent:0.2]; 42 | _timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 43 | 44 | _loadingLayer = [XNHUDLoadingLayer new]; 45 | _progressLayer = [XNHUDProgressLayer new]; 46 | _infoLayer = [XNHUDInfoLayer new]; 47 | _successLayer = [XNHUDSuccessLayer new]; 48 | _errorLayer = [XNHUDErrorLayer new]; 49 | 50 | _pointLayers = [[NSMutableArray alloc] initWithObjects:\ 51 | _loadingLayer, _progressLayer, _infoLayer, _errorLayer, _successLayer, nil]; 52 | [self setBackgroundColor:[UIColor clearColor]]; 53 | [self invalidateIntrinsicContentSize]; 54 | } 55 | 56 | @synthesize tintColor = _tintColor; 57 | - (UIColor *)tintColor { 58 | if(_tintColor) 59 | return _tintColor; 60 | else 61 | return [UIColor grayColor]; 62 | } 63 | 64 | - (UIImageView *)imageView { 65 | if(!_imageView) { 66 | _imageView = [UIImageView new]; 67 | _imageView.contentMode = UIViewContentModeCenter; 68 | _imageView.image = self.infoImage; 69 | } 70 | return _imageView; 71 | } 72 | 73 | 74 | @synthesize loadingLayer = _loadingLayer; 75 | - (void)setLoadingLayer:(CALayer *)loadingLayer { 76 | if (!loadingLayer) { 77 | loadingLayer = [XNHUDLoadingLayer new]; 78 | } 79 | if (_loadingLayer) { 80 | if ([_pointLayers containsObject:_loadingLayer]) { 81 | HUDWeakSelf; 82 | [_pointLayers enumerateObjectsUsingBlock:^(CALayer* obj, NSUInteger idx, BOOL * _Nonnull stop) { 83 | if (obj == weakSelf.loadingLayer) { 84 | [obj stop]; 85 | [weakSelf.pointLayers replaceObjectAtIndex:idx withObject:loadingLayer]; 86 | } 87 | }]; 88 | } 89 | } 90 | _loadingLayer = loadingLayer; 91 | [self invalidateIntrinsicContentSize]; 92 | } 93 | 94 | - (BOOL)isEmptyImages { 95 | return !_infoImage && !_errorImage && !_successImage; 96 | } 97 | 98 | - (void)setFrame:(CGRect)frame { 99 | [super setFrame:frame]; 100 | if (!_pointLayers) return; 101 | HUDWeakSelf; 102 | [_pointLayers enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 103 | CALayer *layer = (CALayer *)obj; 104 | layer.targetLayer = weakSelf.layer; 105 | layer.xn_strokeColor = weakSelf.tintColor.CGColor; 106 | layer.xn_lineWidth = weakSelf.lineWidth; 107 | layer.timingFunction = weakSelf.timingFunction; 108 | layer.frame = CGRectMake(0, 0, frame.size.width, frame.size.height); 109 | }]; 110 | self.imageView.frame = self.bounds; 111 | } 112 | 113 | - (void)setProgress:(CGFloat)progress { 114 | _progress = progress; 115 | self.progressLayer.progress = progress; 116 | } 117 | 118 | - (void)setStyle:(XNAnimationViewStyle)style { 119 | if (style > XNAnimationViewStyleNone) { 120 | [_pointLayers enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 121 | CALayer *layer = (CALayer *)obj; 122 | if (idx != style) { 123 | [layer stop]; 124 | } 125 | }]; 126 | } 127 | if(_style != style) { 128 | [self removeImageView]; 129 | } 130 | _style = style; 131 | } 132 | 133 | - (void)showImageView { 134 | if (!self.imageView.superview) { 135 | [self addSubview:_imageView]; 136 | } 137 | } 138 | 139 | - (void)removeImageView { 140 | if (self.imageView.superview) { 141 | [_imageView removeFromSuperview]; 142 | } 143 | } 144 | 145 | - (BOOL)showImageViewByStyle { 146 | UIImage *image = nil; 147 | if (_style > XNAnimationViewStyleProgress) { 148 | switch (_style) { 149 | case XNAnimationViewStyleInfoImage: 150 | image = _infoImage; 151 | break; 152 | case XNAnimationViewStyleError: 153 | image = _errorImage; 154 | break; 155 | case XNAnimationViewStyleSuccess: 156 | image = _successImage; 157 | break; 158 | default: 159 | break; 160 | } 161 | } 162 | if (image) { 163 | self.imageView.image = image; 164 | [self showImageView]; 165 | return true; 166 | } 167 | return false; 168 | } 169 | 170 | - (void)showImageViewByImage:(UIImage *)image { 171 | self.imageView.image = image; 172 | } 173 | 174 | #pragma mark - XNAnimaionViewProtocol 175 | - (NSNumber *)xn_getStyle { 176 | return [NSNumber numberWithUnsignedInteger:_style]; 177 | } 178 | 179 | - (void)xn_setStyle:(NSNumber *)styleValue { 180 | if (styleValue) { 181 | self.style = styleValue.unsignedIntegerValue; 182 | } 183 | } 184 | 185 | - (void)xn_setProgress:(NSNumber *)progressValue { 186 | if (progressValue) { 187 | self.progress = progressValue.floatValue; 188 | } 189 | } 190 | 191 | - (NSNumber *)xn_isAnimating { 192 | return [NSNumber numberWithUnsignedInteger:_animating];; 193 | } 194 | 195 | - (void)xn_startAnimation { 196 | if (_style == XNAnimationViewStyleNone) return; 197 | _animating = YES; 198 | if (![self showImageViewByStyle]) { 199 | CALayer *layer = _pointLayers[_style]; 200 | [layer prepare]; 201 | [layer play]; 202 | } 203 | } 204 | 205 | - (void)xn_stopAnimation { 206 | if (_style == XNAnimationViewStyleNone) return; 207 | _animating = NO; 208 | CALayer *layer = _pointLayers[_style]; 209 | [layer stop]; 210 | [self removeImageView]; 211 | } 212 | 213 | @end 214 | -------------------------------------------------------------------------------- /Classes/XNHUDAnimationView/XNHUDErrorLayer.h: -------------------------------------------------------------------------------- 1 | // 2 | // XNErrorLayer.h 3 | // XNProgressHUD 4 | // 5 | // Created by jarvis on 2019/7/20. 6 | // Copyright © 2019 罗函. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "XNHUDLayerProtocol.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface XNHUDErrorLayer : CALayer 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /Classes/XNHUDAnimationView/XNHUDErrorLayer.m: -------------------------------------------------------------------------------- 1 | // 2 | // XNHUDErrorLayer.m 3 | // XNProgressHUD 4 | // 5 | // Created by jarvis on 2019/7/20. 6 | // Copyright © 2019 罗函. All rights reserved. 7 | // 8 | 9 | #import "XNHUDErrorLayer.h" 10 | 11 | @interface XNHUDErrorLayer(); 12 | @property (nonatomic, strong) CAShapeLayer *error01; 13 | @property (nonatomic, strong) CAShapeLayer *error02; 14 | @property (nonatomic, strong) CAShapeLayer *circular; 15 | @end 16 | 17 | @implementation XNHUDErrorLayer 18 | @synthesize timingFunction; 19 | @synthesize targetLayer; 20 | @synthesize animationDuration; 21 | @synthesize xn_lineWidth; 22 | @synthesize xn_strokeColor; 23 | @synthesize lineCap; 24 | 25 | - (instancetype)init { 26 | if (!(self = [super init])) return nil; 27 | _error01 = [CAShapeLayer layer]; 28 | _error02 = [CAShapeLayer layer]; 29 | _circular = [CAShapeLayer layer]; 30 | [self addSublayer:_circular]; 31 | [self addSublayer:_error01]; 32 | [self addSublayer:_error02]; 33 | return self; 34 | } 35 | 36 | - (void)addAnimationAtTBLayer:(CAShapeLayer *)layer transform:(CATransform3D)transform{ 37 | NSTimeInterval transformDuration = self.animationDuration * 0.25; 38 | CABasicAnimation *transformAnimation = [CABasicAnimation animationWithKeyPath:@"transform"]; 39 | transformAnimation.duration = transformDuration; 40 | transformAnimation.beginTime = CACurrentMediaTime(); 41 | transformAnimation.timingFunction = [CAMediaTimingFunction functionWithControlPoints:0.5 :-1.55 :0.5 :1]; 42 | transformAnimation.toValue = [NSValue valueWithCATransform3D: transform]; 43 | transformAnimation.repeatCount = 1; 44 | transformAnimation.autoreverses = NO; 45 | transformAnimation.removedOnCompletion = NO; 46 | transformAnimation.fillMode = kCAFillModeForwards; 47 | [layer addAnimation:transformAnimation forKey:@"errorAnimation"]; 48 | } 49 | 50 | - (void)drawInContext:(CGContextRef)ctx { 51 | [super drawInContext:ctx]; 52 | UIGraphicsPushContext(ctx); 53 | 54 | CGPoint center = CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2); 55 | float radius = self.bounds.size.width/2.0, from = 0.f, to = M_PI * 2; 56 | UIBezierPath *path2 = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:from endAngle:to clockwise:true]; 57 | _circular.path = path2.CGPath; 58 | _circular.bounds = path2.bounds; 59 | _circular.position = center; 60 | _circular.fillColor = [UIColor clearColor].CGColor; 61 | 62 | CGFloat width = self.bounds.size.width * 0.55; 63 | UIBezierPath* path = [UIBezierPath bezierPath]; 64 | [path moveToPoint: CGPointMake(0, self.bounds.size.height/2)]; 65 | [path addLineToPoint: CGPointMake(width, self.bounds.size.height/2)]; 66 | _error01.path = _error02.path = path.CGPath; 67 | _error01.bounds = _error02.bounds = path.bounds; 68 | _error01.position = _error02.position = center; 69 | 70 | UIGraphicsPopContext(); 71 | } 72 | 73 | #pragma mark - XNHUDLayerProtocol 74 | - (void)prepare { 75 | if (self.animationDuration == 0) { 76 | self.animationDuration = 2.0; 77 | } 78 | if (!self.timingFunction) { 79 | self.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 80 | } 81 | if (xn_lineWidth == 0) { 82 | xn_lineWidth = 1.8f; 83 | } 84 | if (!xn_strokeColor ) { 85 | xn_strokeColor = [UIColor blackColor].CGColor; 86 | } 87 | _error01.lineWidth = _error02.lineWidth = _circular.lineWidth = xn_lineWidth; 88 | _error01.strokeColor = _error02.strokeColor = _circular.strokeColor = xn_strokeColor; 89 | 90 | // drawing 91 | [self setNeedsDisplay]; 92 | } 93 | 94 | - (void)play { 95 | [_error01 removeAllAnimations]; 96 | [_error02 removeAllAnimations]; 97 | if (!self.superlayer) { 98 | [self.targetLayer addSublayer:self]; 99 | } 100 | CATransform3D translation = CATransform3DMakeTranslation(0, 0, 0); 101 | CATransform3D topTransfrom = CATransform3DRotate(translation, -M_PI_4, 0, 0, 1); 102 | CATransform3D bottomTransfrom = CATransform3DRotate(translation, M_PI_4, 0, 0, 1); 103 | [self addAnimationAtTBLayer:_error01 transform:topTransfrom]; 104 | [self addAnimationAtTBLayer:_error02 transform:bottomTransfrom]; 105 | } 106 | 107 | - (void)stop { 108 | if(_error01.animationKeys) { 109 | [_error01 removeAllAnimations]; 110 | [_error02 removeAllAnimations]; 111 | } 112 | if(self.superlayer) { 113 | [self removeFromSuperlayer]; 114 | } 115 | } 116 | 117 | @end 118 | -------------------------------------------------------------------------------- /Classes/XNHUDAnimationView/XNHUDInfoLayer.h: -------------------------------------------------------------------------------- 1 | // 2 | // XNHUDInfoLayer.h 3 | // XNProgressHUD 4 | // 5 | // Created by jarvis on 2019/7/22. 6 | // Copyright © 2019 罗函. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "XNHUDLayerProtocol.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface XNHUDInfoLayer : CALayer 15 | 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /Classes/XNHUDAnimationView/XNHUDInfoLayer.m: -------------------------------------------------------------------------------- 1 | // 2 | // XNHUDInfoLayer.m 3 | // XNProgressHUD 4 | // 5 | // Created by jarvis on 2019/7/22. 6 | // Copyright © 2019 罗函. All rights reserved. 7 | // 8 | 9 | #import "XNHUDInfoLayer.h" 10 | 11 | @interface XNHUDInfoLayer(); 12 | @property (nonatomic, strong) CAShapeLayer *info01; 13 | @property (nonatomic, strong) CAShapeLayer *info02; 14 | @property (nonatomic, strong) CAShapeLayer *circular; 15 | @end 16 | 17 | 18 | @implementation XNHUDInfoLayer 19 | @synthesize timingFunction; 20 | @synthesize targetLayer; 21 | @synthesize animationDuration; 22 | @synthesize xn_lineWidth; 23 | @synthesize xn_strokeColor; 24 | @synthesize lineCap; 25 | 26 | - (instancetype)init { 27 | if (!(self = [super init])) return nil; 28 | _circular = [CAShapeLayer layer]; 29 | _info01 = [CAShapeLayer layer]; 30 | _info02 = [CAShapeLayer layer]; 31 | [self addSublayer:_circular]; 32 | [self addSublayer:_info01]; 33 | [self addSublayer:_info02]; 34 | return self; 35 | } 36 | 37 | - (void)drawInContext:(CGContextRef)ctx { 38 | [super drawInContext:ctx]; 39 | UIGraphicsPushContext(ctx); 40 | 41 | CGRect frame = self.bounds; 42 | CGPoint center = CGPointMake(frame.size.width/2, frame.size.height/2); 43 | float radius = frame.size.width/2.0, start = 0.f, end = M_PI * 2; 44 | UIBezierPath *circularPath = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:start endAngle:end clockwise:true]; 45 | _circular.path = circularPath.CGPath; 46 | _circular.bounds = circularPath.bounds; 47 | _circular.position = center; 48 | _circular.fillColor = [UIColor clearColor].CGColor; 49 | _circular.lineWidth = xn_lineWidth; 50 | _circular.strokeColor = xn_strokeColor; 51 | 52 | // Oval 椭圆形 2 Drawing 53 | float diameter = xn_lineWidth * 1.8; 54 | float top = frame.size.height * 0.23; 55 | float ovalX = (frame.size.width - diameter)/2; 56 | UIBezierPath* oval2Path = [UIBezierPath bezierPathWithOvalInRect: CGRectMake(ovalX, top, diameter, diameter)]; 57 | [[UIColor clearColor] setStroke]; 58 | [[UIColor clearColor] setFill]; 59 | [oval2Path stroke]; 60 | _info01.path = oval2Path.CGPath; 61 | _info01.bounds = oval2Path.bounds; 62 | _info01.position = CGPointMake(center.x, top); 63 | _info01.fillColor = xn_strokeColor; 64 | 65 | top += xn_lineWidth * 1.1; 66 | // Bezier 路径 2 Drawing 67 | UIBezierPath* bezier2Path = [UIBezierPath bezierPath]; 68 | [bezier2Path moveToPoint: CGPointMake(center.x, top)]; 69 | [bezier2Path addLineToPoint: CGPointMake(center.x, frame.size.height-top)]; 70 | bezier2Path.lineWidth = 1; 71 | bezier2Path.miterLimit = 1; 72 | [bezier2Path stroke]; 73 | _info02.path = bezier2Path.CGPath; 74 | _info02.bounds = bezier2Path.bounds; 75 | _info02.position = CGPointMake(center.x, top+(frame.size.height-top)/2); 76 | _info02.strokeColor = xn_strokeColor; 77 | _info02.lineWidth = xn_lineWidth; 78 | _info02.lineCap = kCALineCapRound; 79 | 80 | UIGraphicsPopContext(); 81 | } 82 | 83 | #pragma mark - XNHUDLayerProtocol 84 | - (void)prepare { 85 | if (self.animationDuration == 0) { 86 | self.animationDuration = 2.0; 87 | } 88 | if (!self.timingFunction) { 89 | self.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 90 | } 91 | if (xn_lineWidth == 0) { 92 | xn_lineWidth = 1.8f; 93 | } 94 | if (!xn_strokeColor ) { 95 | xn_strokeColor = [UIColor blackColor].CGColor; 96 | } 97 | 98 | // drawing 99 | [self setNeedsDisplay]; 100 | } 101 | 102 | - (void)play { 103 | [self removeAllAnimations]; 104 | if (!self.superlayer) { 105 | [self.targetLayer addSublayer:self]; 106 | } 107 | } 108 | 109 | - (void)stop { 110 | if(_circular.animationKeys) { 111 | [_circular removeAllAnimations]; 112 | } 113 | if(self.superlayer) { 114 | [self removeFromSuperlayer]; 115 | } 116 | } 117 | 118 | @end 119 | -------------------------------------------------------------------------------- /Classes/XNHUDAnimationView/XNHUDLayerProtocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // XNHUDLayerProtocol.h 3 | // XNProgressHUD 4 | // 5 | // Created by jarvis on 2019/7/20. 6 | // Copyright © 2019 罗函. All rights reserved. 7 | // 8 | 9 | #ifndef XNHUDLayerProtocol_h 10 | #define XNHUDLayerProtocol_h 11 | 12 | #import 13 | 14 | @protocol XNHUDLayerProtocol 15 | @property (nonatomic, weak, nullable) CALayer *targetLayer; 16 | @property (nonatomic, strong, nullable) CAMediaTimingFunction *timingFunction; 17 | @property (nonatomic, assign) NSTimeInterval animationDuration; 18 | 19 | @property (nullable) CGColorRef xn_strokeColor; 20 | @property (nonatomic, assign) CGFloat xn_lineWidth; 21 | @property (copy, nullable) CAShapeLayerLineCap lineCap;; 22 | 23 | - (void)prepare; 24 | - (void)play; 25 | - (void)stop; 26 | 27 | @optional 28 | - (void)setProgress:(CGFloat)progress; 29 | @end 30 | 31 | #endif /* XNHUDLayerProtocol_h */ 32 | -------------------------------------------------------------------------------- /Classes/XNHUDAnimationView/XNHUDLoadingLayer.h: -------------------------------------------------------------------------------- 1 | // 2 | // XNHUDLoadingLayer.h 3 | // XNProgressHUD 4 | // 5 | // Created by jarvis on 2019/7/20. 6 | // Copyright © 2019 罗函. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "XNHUDLayerProtocol.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface XNHUDLoadingLayer : CALayer 15 | 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /Classes/XNHUDAnimationView/XNHUDLoadingLayer.m: -------------------------------------------------------------------------------- 1 | // 2 | // XNHUDLoadingLayer.m 3 | // XNProgressHUD 4 | // 5 | // Created by jarvis on 2019/7/20. 6 | // Copyright © 2019 罗函. All rights reserved. 7 | // 8 | 9 | #import "XNHUDLoadingLayer.h" 10 | 11 | static NSString *kMMRingStrokeAnimationKey = @"materialdesignspinner.stroke"; 12 | static NSString *kMMRingRotationAnimationKey = @"materialdesignspinner.rotation"; 13 | 14 | @interface XNHUDLoadingLayer() 15 | @property (nonatomic, strong) CAShapeLayer *loading; 16 | @end 17 | 18 | @implementation XNHUDLoadingLayer 19 | @synthesize timingFunction; 20 | @synthesize targetLayer; 21 | @synthesize animationDuration; 22 | @synthesize lineCap; 23 | @synthesize xn_lineWidth; 24 | @synthesize xn_strokeColor; 25 | 26 | - (instancetype)init { 27 | if (!(self = [super init])) return nil; 28 | _loading = [CAShapeLayer layer]; 29 | [self addSublayer:_loading]; 30 | return self; 31 | } 32 | 33 | - (void)setCustomPath:(CAShapeLayer *)layer { 34 | CGPoint center = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds)); 35 | CGFloat radius = MIN(CGRectGetWidth(self.bounds) / 2, CGRectGetHeight(self.bounds) / 2) - layer.lineWidth / 2; 36 | CGFloat startAngle = 0.f; 37 | CGFloat endAngle = M_PI * 2.f; 38 | UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:startAngle endAngle:endAngle clockwise:YES]; 39 | layer.path = path.CGPath; 40 | layer.strokeStart = 0.f; 41 | layer.strokeEnd = 0.f; 42 | layer.frame = self.bounds; 43 | } 44 | 45 | - (void)drawInContext:(CGContextRef)ctx { 46 | [super drawInContext:ctx]; 47 | UIGraphicsPushContext(ctx); 48 | 49 | [self setCustomPath:_loading]; 50 | 51 | _loading.lineCap = kCALineCapRound; 52 | _loading.lineJoin = kCALineJoinBevel; 53 | _loading.strokeColor = xn_strokeColor; 54 | _loading.fillColor = [UIColor clearColor].CGColor; 55 | _loading.lineWidth = xn_lineWidth; 56 | _loading.position = CGPointMake(CGRectGetWidth(self.bounds)/2, CGRectGetHeight(self.bounds)/2); 57 | 58 | UIGraphicsPopContext(); 59 | } 60 | 61 | #pragma mark - XNHUDLayerProtocol 62 | - (void)prepare { 63 | if (self.animationDuration == 0) { 64 | self.animationDuration = 2.0; 65 | } 66 | if (!self.timingFunction) { 67 | self.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 68 | } 69 | 70 | // drawing 71 | [self setNeedsDisplay]; 72 | } 73 | 74 | - (void)play { 75 | [_loading removeAnimationForKey:kMMRingStrokeAnimationKey]; 76 | 77 | if (!self.superlayer) { 78 | [self.targetLayer addSublayer:self]; 79 | } 80 | float duration = self.animationDuration; 81 | 82 | CABasicAnimation *animation = [CABasicAnimation animation]; 83 | animation.keyPath = @"transform.rotation"; 84 | animation.duration = duration / 0.5; 85 | animation.fromValue = @(0.f); 86 | animation.toValue = @(2 * M_PI); 87 | animation.repeatCount = INFINITY; 88 | animation.removedOnCompletion = NO; 89 | [_loading addAnimation:animation forKey:kMMRingRotationAnimationKey]; 90 | 91 | CABasicAnimation *headAnimation = [CABasicAnimation animation]; 92 | headAnimation.keyPath = @"strokeStart"; 93 | headAnimation.duration = duration / 2; 94 | headAnimation.fromValue = @(0.f); 95 | headAnimation.toValue = @(0.3f); 96 | headAnimation.timingFunction = self.timingFunction; 97 | 98 | CABasicAnimation *tailAnimation = [CABasicAnimation animation]; 99 | tailAnimation.keyPath = @"strokeEnd"; 100 | tailAnimation.duration = duration / 2; 101 | tailAnimation.fromValue = @(0.f); 102 | tailAnimation.toValue = @(1.0f); 103 | tailAnimation.timingFunction = timingFunction; 104 | 105 | CABasicAnimation *endHeadAnimation = [CABasicAnimation animation]; 106 | endHeadAnimation.keyPath = @"strokeStart"; 107 | endHeadAnimation.beginTime = duration - headAnimation.duration; 108 | endHeadAnimation.duration = duration / 2; 109 | endHeadAnimation.fromValue = headAnimation.toValue; 110 | endHeadAnimation.toValue = @(1.0f); 111 | endHeadAnimation.timingFunction = self.timingFunction; 112 | 113 | CABasicAnimation *endTailAnimation = [CABasicAnimation animation]; 114 | endTailAnimation.keyPath = @"strokeEnd"; 115 | endTailAnimation.beginTime = duration - tailAnimation.duration; 116 | endTailAnimation.duration = duration / 2; 117 | endTailAnimation.fromValue = tailAnimation.toValue; 118 | endTailAnimation.toValue = @(1.0f); 119 | endTailAnimation.timingFunction = self.timingFunction; 120 | 121 | CAAnimationGroup *animations = [CAAnimationGroup animation]; 122 | [animations setDuration:duration]; 123 | [animations setAnimations:@[headAnimation, tailAnimation, endHeadAnimation, endTailAnimation]]; 124 | animations.repeatCount = INFINITY; 125 | animations.removedOnCompletion = NO; 126 | animations.fillMode = kCAFillModeForwards; 127 | [_loading addAnimation:animations forKey:kMMRingStrokeAnimationKey]; 128 | } 129 | 130 | - (void)stop { 131 | if(_loading.animationKeys) { 132 | [_loading removeAnimationForKey:kMMRingStrokeAnimationKey]; 133 | } 134 | if(self.superlayer) { 135 | [self removeFromSuperlayer]; 136 | } 137 | } 138 | 139 | 140 | 141 | 142 | @end 143 | -------------------------------------------------------------------------------- /Classes/XNHUDAnimationView/XNHUDProgressLayer.h: -------------------------------------------------------------------------------- 1 | // 2 | // XNHUDProgressLayer.h 3 | // XNProgressHUD 4 | // 5 | // Created by jarvis on 2019/7/20. 6 | // Copyright © 2019 罗函. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "XNHUDLayerProtocol.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface XNHUDProgressLayer : CALayer 15 | @property (nonatomic, assign) CGFloat progress; 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /Classes/XNHUDAnimationView/XNHUDProgressLayer.m: -------------------------------------------------------------------------------- 1 | // 2 | // XNHUDProgressLayer.m 3 | // XNProgressHUD 4 | // 5 | // Created by jarvis on 2019/7/20. 6 | // Copyright © 2019 罗函. All rights reserved. 7 | // 8 | 9 | #import "XNHUDProgressLayer.h" 10 | 11 | @interface XNHUDProgressLayer() 12 | @property (nonatomic, strong) CAShapeLayer *circular; 13 | @property (nonatomic, strong) CAShapeLayer *progressLayer; 14 | @property (nonatomic, strong) CATextLayer *textLayer; 15 | @end 16 | 17 | 18 | @implementation XNHUDProgressLayer 19 | @synthesize animationDuration; 20 | @synthesize lineCap; 21 | @synthesize targetLayer; 22 | @synthesize timingFunction; 23 | @synthesize xn_lineWidth; 24 | @synthesize xn_strokeColor; 25 | 26 | - (CATextLayer *)createTextLayer { 27 | CATextLayer *layer = [CATextLayer layer]; 28 | layer.alignmentMode = kCAAlignmentCenter; 29 | layer.font = (__bridge CFTypeRef _Nullable)(@"AvenirNextCondensed-Medium"); 30 | layer.fontSize = 11.f; 31 | layer.backgroundColor = [UIColor clearColor].CGColor; 32 | layer.contentsScale = 2; 33 | return layer; 34 | } 35 | 36 | - (instancetype)init { 37 | if (!(self = [super init])) return nil; 38 | _circular = [CAShapeLayer layer]; 39 | _progressLayer = [CAShapeLayer layer]; 40 | _textLayer = [self createTextLayer]; 41 | [self addSublayer:_circular]; 42 | [self addSublayer:_progressLayer]; 43 | [self addSublayer:_textLayer]; 44 | return self; 45 | } 46 | 47 | - (void)setFrame:(CGRect)frame { 48 | [super setFrame:frame]; 49 | [self setNeedsDisplay]; 50 | } 51 | 52 | - (void)setProgress:(CGFloat)progress { 53 | _progress = progress; 54 | _textLayer.string = [NSString stringWithFormat:@"%.f%%", progress * 100]; 55 | _progressLayer.strokeEnd = progress; 56 | } 57 | 58 | - (void)drawInContext:(CGContextRef)ctx { 59 | [super drawInContext:ctx]; 60 | UIGraphicsPushContext(ctx); 61 | 62 | CGPoint center = CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2); 63 | float fontHeight = self.bounds.size.height * 0.5; 64 | _textLayer.frame = CGRectMake(0, (self.bounds.size.height-fontHeight)/2, self.bounds.size.width, fontHeight); 65 | _textLayer.foregroundColor = xn_strokeColor; 66 | _textLayer.fontSize = self.bounds.size.width * 0.4f; 67 | 68 | float radius = self.bounds.size.width/2.0, from = -M_PI_2, to = -M_PI_2 + M_PI * 2.f; 69 | UIBezierPath *circularPath = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:from endAngle:to clockwise:true]; 70 | _circular.fillColor = _progressLayer.fillColor = [UIColor clearColor].CGColor; 71 | _circular.path = _progressLayer.path = circularPath.CGPath; 72 | _circular.bounds = _progressLayer.bounds = circularPath.bounds; 73 | _circular.position = _progressLayer.position = center; 74 | _circular.lineWidth = _progressLayer.lineWidth = xn_lineWidth; 75 | _circular.strokeColor = [[UIColor blackColor] colorWithAlphaComponent:0.3].CGColor; 76 | _progressLayer.strokeColor = xn_strokeColor; 77 | 78 | UIGraphicsPopContext(); 79 | } 80 | 81 | #pragma mark - XNHUDLayerProtocol 82 | - (void)prepare { 83 | if (self.animationDuration == 0) { 84 | self.animationDuration = 2.0; 85 | } 86 | if (!self.timingFunction) { 87 | self.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 88 | } 89 | if (xn_lineWidth == 0) { 90 | xn_lineWidth = 1.8f; 91 | } 92 | if (!xn_strokeColor ) { 93 | xn_strokeColor = [UIColor blackColor].CGColor; 94 | } 95 | } 96 | 97 | - (void)play { 98 | [self removeAllAnimations]; 99 | if (!self.superlayer) { 100 | [self.targetLayer addSublayer:self]; 101 | } 102 | } 103 | 104 | - (void)stop { 105 | if(_progressLayer.animationKeys) { 106 | [_progressLayer removeAllAnimations]; 107 | [_circular removeAllAnimations]; 108 | } 109 | if(self.superlayer) { 110 | [self removeFromSuperlayer]; 111 | } 112 | } 113 | 114 | @end 115 | -------------------------------------------------------------------------------- /Classes/XNHUDAnimationView/XNHUDSuccessLayer.h: -------------------------------------------------------------------------------- 1 | // 2 | // XNHUDSuccessLayer.h 3 | // XNProgressHUD 4 | // 5 | // Created by jarvis on 2019/7/20. 6 | // Copyright © 2019 罗函. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "XNHUDLayerProtocol.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface XNHUDSuccessLayer : CALayer 15 | 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /Classes/XNHUDAnimationView/XNHUDSuccessLayer.m: -------------------------------------------------------------------------------- 1 | // 2 | // XNHUDSuccessLayer.m 3 | // XNProgressHUD 4 | // 5 | // Created by jarvis on 2019/7/20. 6 | // Copyright © 2019 罗函. All rights reserved. 7 | // 8 | 9 | #import "XNHUDSuccessLayer.h" 10 | 11 | @interface XNHUDSuccessLayer () 12 | @property (nonatomic, strong) CAShapeLayer *success; 13 | @property (nonatomic, strong) CAShapeLayer *circular; 14 | @end 15 | 16 | @implementation XNHUDSuccessLayer 17 | @synthesize timingFunction; 18 | @synthesize targetLayer; 19 | @synthesize animationDuration; 20 | @synthesize lineCap; 21 | @synthesize xn_lineWidth; 22 | @synthesize xn_strokeColor; 23 | 24 | - (instancetype)init { 25 | if (!(self = [super init])) return nil; 26 | _success = [CAShapeLayer layer]; 27 | _circular = [CAShapeLayer layer]; 28 | [self addSublayer:_success]; 29 | [self addSublayer:_circular]; 30 | return self; 31 | } 32 | 33 | - (void)drawInContext:(CGContextRef)ctx { 34 | [super drawInContext:ctx]; 35 | UIGraphicsPushContext(ctx); 36 | 37 | CGPoint center = CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2); 38 | float radius = self.bounds.size.width/2.0, start = 0.f, end = M_PI * 2; 39 | UIBezierPath *path2 = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:start endAngle:end clockwise:true]; 40 | _circular.path = path2.CGPath; 41 | _circular.bounds = path2.bounds; 42 | _circular.position = center; 43 | _circular.fillColor = [UIColor clearColor].CGColor; 44 | 45 | CGFloat width = self.bounds.size.width; 46 | UIBezierPath* path = [UIBezierPath bezierPath]; 47 | [path moveToPoint: CGPointMake(width / 4.8, width / 1.9)]; 48 | [path addLineToPoint: CGPointMake(width / 2.39, width / 1.4)]; 49 | [path addLineToPoint: CGPointMake(width / 1.3, width / 3.55)]; 50 | _success.path = path.CGPath; 51 | _success.actions = @{@"strokeStart":[NSNull null], @"strokeEnd":[NSNull null], @"transform":[NSNull null]}; 52 | _success.strokeStart = 0.f; 53 | _success.strokeEnd = 0.9f; 54 | _success.position = center; 55 | _success.fillColor = [UIColor clearColor].CGColor; 56 | _success.lineWidth = _circular.lineWidth = xn_lineWidth; 57 | _success.strokeColor = _circular.strokeColor = xn_strokeColor; 58 | CGPathRef strokingPath = CGPathCreateCopyByStrokingPath(_success.path, nil, _success.lineWidth, kCGLineCapRound, kCGLineJoinMiter, 0); 59 | _success.bounds = CGPathGetPathBoundingBox(strokingPath); 60 | 61 | UIGraphicsPopContext(); 62 | } 63 | 64 | #pragma mark - XNHUDLayerProtocol 65 | - (void)prepare { 66 | if (self.animationDuration == 0) { 67 | self.animationDuration = 2.0; 68 | } 69 | if (!self.timingFunction) { 70 | self.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 71 | } 72 | if (xn_lineWidth == 0) { 73 | xn_lineWidth = 1.8f; 74 | } 75 | if (!xn_strokeColor ) { 76 | xn_strokeColor = [UIColor blackColor].CGColor; 77 | } 78 | 79 | // drawing 80 | [self setNeedsDisplay]; 81 | } 82 | 83 | - (void)play { 84 | [_success removeAllAnimations]; 85 | if (!self.superlayer) { 86 | [self.targetLayer addSublayer:self]; 87 | } 88 | //对勾动画 89 | CABasicAnimation *arc = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; 90 | arc.fromValue = @(0.0); 91 | arc.toValue = @(1.0); 92 | arc.duration = 0.4; 93 | arc.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 94 | arc.removedOnCompletion = NO; 95 | arc.fillMode = kCAFillModeForwards; 96 | [_success addAnimation:arc forKey:arc.keyPath]; 97 | } 98 | 99 | - (void)stop { 100 | if(_success.animationKeys) { 101 | [_success removeAllAnimations]; 102 | } 103 | if(self.superlayer) { 104 | [self removeFromSuperlayer]; 105 | } 106 | } 107 | @end 108 | -------------------------------------------------------------------------------- /Classes/XNProgressHUD.h: -------------------------------------------------------------------------------- 1 | // 2 | // XNProgressHUD.h 3 | // XNTools 4 | // 5 | // Created by 罗函 on 2018/2/8. 6 | // 7 | 8 | #import 9 | #import 10 | #import "XNHUDLayerProtocol.h" 11 | 12 | #define HUDScreenSize [UIScreen mainScreen].bounds.size 13 | #define HUDWeakSelf __weak typeof(self) weakSelf = self 14 | #define XNAnimationViewWidth 28.f 15 | #define XNHUD [XNProgressHUD shared] 16 | 17 | typedef NS_ENUM(NSUInteger, XNProgressHUDOrientation) { 18 | XNProgressHUDOrientationVertical = 0, 19 | XNProgressHUDOrientationHorizontal 20 | }; 21 | 22 | typedef NS_ENUM(NSInteger, XNProgressHUDStyle) { 23 | XNProgressHUDStyleTitle = 0, //只显示标题 24 | XNProgressHUDStyleLoading, //只显示圈 25 | XNProgressHUDStyleLoadingAndTitle //显示圈+标题 26 | }; 27 | 28 | typedef NS_ENUM(NSUInteger, XNProgressHUDMaskType) { 29 | XNProgressHUDMaskTypeNone = 0, 30 | XNProgressHUDMaskTypeClear, 31 | XNProgressHUDMaskTypeBlack, 32 | XNProgressHUDMaskTypeCustom 33 | }; 34 | 35 | typedef NS_ENUM (NSInteger, XNAnimationViewStyle) { 36 | XNAnimationViewStyleNone = -1, 37 | XNAnimationViewStyleLoading, 38 | XNAnimationViewStyleProgress, 39 | XNAnimationViewStyleInfoImage, 40 | XNAnimationViewStyleError, 41 | XNAnimationViewStyleSuccess 42 | }; 43 | 44 | typedef void(^HUDDismissBlock) (void); 45 | 46 | typedef struct HUDPadding { 47 | CGFloat top, left, bottom, right; 48 | } HUDPadding; 49 | 50 | CG_INLINE HUDPadding 51 | HUDPaddingMake(CGFloat top, CGFloat left, CGFloat bottom, CGFloat right) { 52 | HUDPadding padding = {top, left, bottom, right}; 53 | return padding; 54 | } 55 | 56 | typedef struct XNHUDMaskColor { 57 | unsigned int clear, black, custom; 58 | } XNHUDMaskColor; 59 | CG_INLINE XNHUDMaskColor 60 | XNHUDMaskColorMake(unsigned int clear, unsigned int black, unsigned int custom) { 61 | XNHUDMaskColor maskColor = {clear, black, custom}; 62 | return maskColor; 63 | } 64 | 65 | // 控制AnimationView显示状态的方法,与协议XNAnimaionViewProtocol对应 66 | @protocol XNProgressHUDMethod 67 | - (XNAnimationViewStyle)getStyleFromAnimationView; 68 | - (void)setStyleInAnimationView:(XNAnimationViewStyle)style; 69 | - (void)startAnimation; 70 | - (void)stopAnimation; 71 | - (void)setProgressInAnimationView:(CGFloat)progress; 72 | @end 73 | 74 | @protocol XNProgressHUDProtocol 75 | @optional 76 | 77 | /** 78 | * 显示Loading 79 | */ 80 | - (void)show; 81 | - (void)showWithMaskType:(XNProgressHUDMaskType)maskType; 82 | 83 | /** 84 | * 显示转圈视图 + 提示文字 85 | */ 86 | - (void)showLoadingWithTitle:(nullable NSString *)title; 87 | - (void)showLoadingWithTitle:(nullable NSString *)title maskType:(XNProgressHUDMaskType)maskType; 88 | 89 | /** 90 | * 显示提示文字 91 | */ 92 | - (void)showWithTitle:(nullable NSString *)title; 93 | - (void)showWithTitle:(nullable NSString *)title maskType:(XNProgressHUDMaskType)maskType; 94 | 95 | /** 96 | * 进度视图 + 提示文字 97 | */ 98 | - (void)showProgressWithProgress:(float)progress; 99 | - (void)showProgressWithTitle:(nullable NSString *)title progress:(float)progress; 100 | - (void)showProgressWithTitle:(nullable NSString *)title progress:(float)progress maskType:(XNProgressHUDMaskType)maskType; 101 | 102 | /** 103 | * 显示提示视图 + 提示文字(警告) 104 | */ 105 | - (void)showInfoWithTitle:(nullable NSString *)title; 106 | - (void)showInfoWithTitle:(nullable NSString *)title maskType:(XNProgressHUDMaskType)maskType; 107 | 108 | /** 109 | * 显示提示视图 + 提示文字(操作失败) 110 | */ 111 | - (void)showErrorWithTitle:(nullable NSString*)title; 112 | - (void)showErrorWithTitle:(nullable NSString*)title maskType:(XNProgressHUDMaskType)maskType; 113 | 114 | /** 115 | * 显示提示视图 + 提示文字(操作成功) 116 | */ 117 | - (void)showSuccessWithTitle:(nullable NSString*)title; 118 | - (void)showSuccessWithTitle:(nullable NSString*)title maskType:(XNProgressHUDMaskType)maskType; 119 | 120 | - (void)dismiss; 121 | - (void)dismissWithDelay:(NSTimeInterval)delay; 122 | 123 | @end 124 | 125 | 126 | @interface XNProgressHUD : NSObject 127 | 128 | @property (nonatomic, strong) UIView * _Nullable maskView; //遮罩 129 | @property (nonatomic, strong) UIView * _Nullable shadeContentView; //阴影视图 130 | @property (nonatomic, assign) CGColorRef _Nullable shadowColor; //阴影颜色 131 | @property (nonatomic, strong) UIView * _Nullable contentView; //标题和动画视图的父视图 132 | @property (nonatomic, strong) UILabel * _Nullable titleLabel; //标题 133 | @property (nonatomic, strong, readwrite) UIView * _Nonnull animationView; //动画视图 134 | @property (nonatomic, assign) CGFloat animationViewWidth; //动画视图的尺寸 135 | @property (nonatomic, assign) XNAnimationViewStyle refreshStyle; //动画视图的样式 136 | @property (nonatomic, assign) CGFloat separatorWidth; //动画视图与标题的间距 137 | //最小延时消失时间(生效于:XNAnimationViewStyleInfoImage、XNAnimationViewStyleError、XNAnimationViewStyleSuccess) 138 | @property (nonatomic, assign) NSTimeInterval minimumDelayDismissDuration; 139 | //最大延时消失时间(生效于:XNAnimationViewStyleLoading、XNAnimationViewStyleProgress) 140 | @property (nonatomic, assign) NSTimeInterval maximumDelayDismissDuration; 141 | @property (nonatomic, assign) BOOL showing; //显示状态 142 | @property (nonatomic, strong) NSString * _Nullable title; //文字 143 | @property (nonatomic, assign) CGPoint position; //显示位置 144 | @property (nonatomic, assign) HUDPadding padding; //内边距 145 | @property (nonatomic, strong) UIColor * _Nullable tintColor; //主色调 146 | @property (nonatomic, assign) CGFloat borderWidth; //圆角 147 | @property (nonatomic, assign) NSTimeInterval duration; //动画时长 148 | @property (nonatomic, assign, readonly) XNProgressHUDStyle style; //样式 149 | @property (nonatomic, assign) XNProgressHUDOrientation orientation; //方向,默认为水平b布局 150 | 151 | /** 152 | * 默认为空, 显示在KeyWindow上, 若不为空,有两种情况: 153 | * 1.targetView=用户自定义的UIWindow,此时maskType不使能,需要锁定点击事件时需设置userInteractionEnabled属性 154 | * 2.targetView=UIView, 使用方法与默认状态下一样 155 | */ 156 | @property (nonatomic, weak) UIView * _Nullable targetView; //指定显示在某个View上 157 | //MaskView 158 | @property (nonatomic, assign, readonly) XNProgressHUDMaskType maskType; 159 | @property (nonatomic, assign) struct XNHUDMaskColor maskColor; 160 | @property (nonatomic, strong) HUDDismissBlock _Nullable hudDismissBlock; //点击遮罩时的回调 161 | 162 | /** 163 | 单例(define:XNHUD) 164 | */ 165 | + (instancetype _Nullable )shared; 166 | 167 | /** 168 | * 只对下一次显示生效:设置延时时间(延时显示时间、延时消失时间) 169 | */ 170 | - (void)setDisposableDelayResponse:(NSTimeInterval)delayResponse delayDismiss:(NSTimeInterval)delayDismiss; 171 | 172 | /** 173 | * 只对下一次显示生效:设置遮罩类型 174 | */ 175 | - (void)setMaskType:(XNProgressHUDMaskType)maskType; 176 | - (void)setMaskType:(XNProgressHUDMaskType)maskType hexColor:(uint32_t)color; 177 | 178 | /** 179 | * 是否正在显示 180 | */ 181 | - (BOOL)isShowing; 182 | 183 | /** 184 | * 清理资源 185 | */ 186 | - (void)clearUp; 187 | 188 | 189 | @end 190 | 191 | -------------------------------------------------------------------------------- /Classes/XNProgressHUD.m: -------------------------------------------------------------------------------- 1 | // 2 | // XNProgressHUD.m 3 | // XNTools 4 | // 5 | // Created by 罗函 on 2018/2/8. 6 | // 7 | 8 | #import "XNProgressHUD.h" 9 | #import "XNAnimationView.h" 10 | 11 | @interface XNProgressHUD() { 12 | UIView *_animationView; 13 | } 14 | @property (nonatomic, strong) NSTimer *displayTimer; 15 | @property (nonatomic, strong) NSTimer *dismissTimer; 16 | @property (nonatomic, assign) CGRect frame; 17 | @property (nonatomic, assign) NSTimeInterval disposableDelayResponse; //延时相应 18 | @property (nonatomic, assign) NSTimeInterval disposableDelayDismiss; //延时消失时间 19 | @property (nonatomic, assign) CGFloat progress; //进度 20 | @property (nonatomic, assign) BOOL needTransitive; 21 | @end 22 | 23 | @implementation XNProgressHUD 24 | 25 | - (void)addSubviewIfNotContain:(UIView *)view superView:(UIView *)superView{ 26 | if((view && superView) && (!view.superview || view.superview != superView)) { 27 | [superView addSubview:view]; 28 | } 29 | } 30 | 31 | - (void)removeFromSuperview:(UIView *)view { 32 | if(view && view.superview) { 33 | [view removeFromSuperview]; 34 | view = nil; 35 | } 36 | } 37 | 38 | - (void)stopTimerAndSetItNil:(NSTimer *)timer { 39 | if(timer) { 40 | [timer invalidate]; 41 | timer = nil; 42 | } 43 | } 44 | 45 | - (UIColor *)createColorWithRGBA:(uint32_t)rgbaValue { 46 | return [UIColor colorWithRed:((rgbaValue & 0xFF000000) >> 24) / 255.0f 47 | green:((rgbaValue & 0xFF0000) >> 16) / 255.0f 48 | blue:((rgbaValue & 0xFF00) >> 8) / 255.0f 49 | alpha:(rgbaValue & 0xFF) / 255.0f]; 50 | } 51 | 52 | - (uint32_t)rgbaValueWithUIColor:(UIColor *)color { 53 | CGFloat r = 0, g = 0, b = 0, a = 0; 54 | [color getRed:&r green:&g blue:&b alpha:&a]; 55 | int8_t red = r * 255; 56 | uint8_t green = g * 255; 57 | uint8_t blue = b * 255; 58 | uint8_t alpha = a * 255; 59 | return (red << 24) + (green << 16) + (blue << 8) + alpha; 60 | } 61 | 62 | + (instancetype)shared { 63 | static XNProgressHUD *instance; 64 | static dispatch_once_t onceToken; 65 | dispatch_once(&onceToken, ^{ 66 | instance = [[XNProgressHUD alloc] init]; 67 | }); 68 | return instance; 69 | } 70 | 71 | - (instancetype)init { 72 | if(!(self = [super init])) return nil; 73 | [self initialize]; 74 | return self; 75 | } 76 | 77 | - (UIView *)maskView { 78 | if(!_maskView) { 79 | _maskView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, HUDScreenSize.width, HUDScreenSize.height)]; 80 | _maskView.userInteractionEnabled = YES; 81 | // 为MaskView添加点击事件 82 | if(_hudDismissBlock) { 83 | [self addMaskTapGestureEvent]; 84 | } 85 | } 86 | return _maskView; 87 | } 88 | 89 | - (UIColor *)maskColorWithMaskType:(XNProgressHUDMaskType)maskType { 90 | unsigned int hexColor; 91 | switch (maskType) { 92 | case XNProgressHUDMaskTypeClear: 93 | hexColor = _maskColor.clear; 94 | break; 95 | case XNProgressHUDMaskTypeBlack: 96 | hexColor = _maskColor.black; 97 | break; 98 | case XNProgressHUDMaskTypeCustom: 99 | hexColor = _maskColor.custom; 100 | break; 101 | default: 102 | hexColor = 0x00000000; 103 | break; 104 | } 105 | UIColor *color = [self createColorWithRGBA:hexColor]; 106 | return color ? color : [UIColor clearColor]; 107 | } 108 | 109 | - (void)setMaskType:(XNProgressHUDMaskType)maskType { 110 | _maskType = maskType; 111 | } 112 | 113 | - (void)setMaskType:(XNProgressHUDMaskType)maskType hexColor:(uint32_t)color { 114 | switch (maskType) { 115 | case XNProgressHUDMaskTypeClear: 116 | _maskColor.clear = color; 117 | break; 118 | case XNProgressHUDMaskTypeBlack: 119 | _maskColor.black= color; 120 | break; 121 | case XNProgressHUDMaskTypeCustom: 122 | _maskColor.custom = color; 123 | break; 124 | default: 125 | break; 126 | } 127 | } 128 | 129 | - (UIView *)animationView { 130 | if(!_animationView) { 131 | XNAnimationView *view = [XNAnimationView new]; 132 | view.tintColor = self.titleLabel.textColor; 133 | view.lineWidth = 2.f; 134 | _animationView = view; 135 | } 136 | return _animationView; 137 | } 138 | 139 | - (void)setAnimationView:(UIView *)animationView { 140 | if (animationView) { 141 | _animationView = animationView; 142 | //_animationView.tintColor = _titleLabel.textColor; 143 | [self.contentView addSubview:animationView]; 144 | } 145 | } 146 | 147 | - (UIView *)shadeContentView { 148 | if(!_shadeContentView) { 149 | _shadeContentView = [UIView new]; 150 | _shadeContentView.backgroundColor = [UIColor clearColor]; 151 | _shadeContentView.layer.shadowColor = _shadowColor; 152 | _shadeContentView.layer.shadowOffset = CGSizeMake(3,3); 153 | _shadeContentView.layer.shadowOpacity = 0.6; 154 | _shadeContentView.layer.shadowRadius = 5.f; 155 | _shadeContentView.userInteractionEnabled = NO; 156 | } 157 | return _shadeContentView; 158 | } 159 | 160 | - (UIView *)contentView { 161 | if(!_contentView) { 162 | _contentView = [UIView new]; 163 | _contentView.backgroundColor = _tintColor; 164 | _contentView.layer.borderColor = [UIColor clearColor].CGColor; 165 | _contentView.layer.borderWidth = 1.f; 166 | _contentView.layer.cornerRadius = 5.f; 167 | _contentView.layer.shouldRasterize = NO; 168 | _contentView.layer.rasterizationScale = 2; 169 | _contentView.layer.edgeAntialiasingMask = kCALayerLeftEdge | kCALayerRightEdge | kCALayerBottomEdge | kCALayerTopEdge; 170 | _contentView.clipsToBounds = YES; 171 | _contentView.layer.masksToBounds = YES; 172 | } 173 | return _contentView; 174 | } 175 | 176 | - (UILabel *)titleLabel { 177 | if(!_titleLabel) { 178 | _titleLabel = [UILabel new]; 179 | _titleLabel.textColor = [UIColor whiteColor]; 180 | _titleLabel.font = [UIFont fontWithName:@"PingFangSC-Medium" size:16.f]; 181 | _titleLabel.textAlignment = NSTextAlignmentLeft; 182 | _titleLabel.numberOfLines = 0; 183 | _titleLabel.lineBreakMode = NSLineBreakByWordWrapping; 184 | } 185 | return _titleLabel; 186 | } 187 | 188 | @synthesize targetView = _targetView; 189 | - (void)setTargetView:(UIView *)targetView { 190 | _targetView = targetView; 191 | } 192 | - (UIView *)targetView { 193 | UIView *view = nil; 194 | if (_targetView) 195 | view = _targetView; 196 | else 197 | view = [UIApplication sharedApplication].keyWindow; 198 | return view; 199 | } 200 | 201 | - (NSTimeInterval)minimumDelayDismissDuration { 202 | return _minimumDelayDismissDuration > 0 ? _minimumDelayDismissDuration : 1.5f; 203 | } 204 | 205 | - (NSTimeInterval)maximumDelayDismissDuration { 206 | return _maximumDelayDismissDuration > 0 ? _maximumDelayDismissDuration : 20.f; 207 | } 208 | 209 | - (void)setStyle:(XNProgressHUDStyle)style { 210 | _style = style; 211 | } 212 | 213 | - (void)setDisposableDelayDismiss:(NSTimeInterval)disposableDelayDismiss { 214 | _disposableDelayDismiss = disposableDelayDismiss; 215 | } 216 | 217 | - (void)setRefreshStyle:(XNAnimationViewStyle)refreshStyle { 218 | _needTransitive = _refreshStyle == refreshStyle; 219 | _refreshStyle = refreshStyle; 220 | } 221 | 222 | - (void)setOrientation:(XNProgressHUDOrientation)orientation { 223 | _needTransitive = _orientation == orientation; 224 | _orientation = orientation; 225 | } 226 | 227 | - (void)setTitle:(NSString *)title { 228 | _title = title; 229 | } 230 | 231 | - (void)setTintColor:(UIColor *)tintColor { 232 | self.contentView.backgroundColor = _tintColor = tintColor; 233 | } 234 | 235 | - (BOOL)isShowing { 236 | return _showing; 237 | } 238 | 239 | - (BOOL)isMaskEnable { 240 | return _maskType != XNProgressHUDMaskTypeNone; 241 | } 242 | 243 | - (BOOL)isWindowAndIsNotKeyWindow:(UIView *)view { 244 | return view && [view isKindOfClass:UIWindow.class] && ![view isEqual:[UIApplication sharedApplication].keyWindow]; 245 | } 246 | 247 | - (CGFloat)maximumWidth { 248 | return [[UIScreen mainScreen] bounds].size.width * 0.7; 249 | } 250 | 251 | - (CGSize)titleLabelContentSize { 252 | if(!self.titleLabel.text || self.titleLabel.text.length == 0) 253 | return CGSizeZero; 254 | else 255 | return [self.titleLabel sizeThatFits:CGSizeMake(self.maximumWidth - _padding.left + _padding.right, MAXFLOAT)]; 256 | } 257 | 258 | - (XNProgressHUDStyle)styleWithTitle:(NSString *)title { 259 | return (title && title.length > 0) ? XNProgressHUDStyleLoadingAndTitle : XNProgressHUDStyleLoading; 260 | } 261 | 262 | - (void)addMaskTapGestureEvent { 263 | [self removeMaskTapGestureEvent]; 264 | UITapGestureRecognizer *maskTapEvent = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismiss)]; 265 | [self.maskView addGestureRecognizer: maskTapEvent]; 266 | } 267 | 268 | - (void)removeMaskTapGestureEvent { 269 | if(self.maskView.gestureRecognizers.count > 0) { 270 | self.maskView.gestureRecognizers = nil; 271 | } 272 | } 273 | 274 | - (void)initialize { 275 | _duration = 0.2f; 276 | _separatorWidth = 5; 277 | _padding = HUDPaddingMake(8, 8, 8, 8); 278 | _maskColor = XNHUDMaskColorMake(0x00000000, 0x00000033, 0x00000000); 279 | _animationViewWidth = XNAnimationViewWidth; 280 | _tintColor = [UIColor colorWithRed:41/255.f green:42/255.f blue:47/255.f alpha:0.7f]; 281 | _shadowColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:1.f].CGColor; 282 | _position = [UIApplication sharedApplication].delegate.window.center; 283 | //shadeView、contentView 284 | [self.shadeContentView addSubview:self.contentView]; 285 | [self.contentView addSubview:self.animationView]; 286 | [self.contentView addSubview:self.titleLabel]; 287 | } 288 | 289 | - (void)update { 290 | //updateFrame 291 | HUDPadding padding = _padding; 292 | CGFloat animWidth = 0, separatorWidth = 0; 293 | CGRect titleFrame = CGRectZero, animFrame = CGRectZero; 294 | CGSize titleSize = CGSizeZero; 295 | if (self.title && self.title.length > 0) 296 | titleSize = [self.titleLabel sizeThatFits:CGSizeMake(HUDScreenSize.width * 0.7f, MAXFLOAT)]; 297 | if (self.style == XNProgressHUDStyleLoading || self.style == XNProgressHUDStyleLoadingAndTitle) { 298 | animWidth = _animationViewWidth; 299 | if (self.style == XNProgressHUDStyleLoadingAndTitle) 300 | separatorWidth = _separatorWidth; 301 | if ((self.style == XNProgressHUDStyleLoading || self.orientation == XNProgressHUDOrientationVertical)) { 302 | if (animWidth < XNAnimationViewWidth * 1.5) { 303 | animWidth = XNAnimationViewWidth * 1.5; 304 | } 305 | } 306 | } 307 | CGFloat width = 0, height = 0; 308 | if (self.orientation == XNProgressHUDOrientationHorizontal) { 309 | width = padding.left + padding.right + separatorWidth + animWidth + titleSize.width; 310 | height = MAX(padding.top + padding.bottom + animWidth, padding.top + padding.bottom + titleSize.height); 311 | _frame.size = CGSizeMake(width, height); 312 | _frame.origin = CGPointMake(_position.x-_frame.size.width/2, _position.y-_frame.size.height/2); 313 | if (animWidth > 0) { 314 | animFrame = CGRectMake(padding.left, (_frame.size.height-animWidth)/2, animWidth, animWidth); 315 | } 316 | titleFrame = CGRectMake(padding.left + animWidth + separatorWidth, (_frame.size.height-titleSize.height)/2, titleSize.width, titleSize.height); 317 | } else { 318 | width = MAX(padding.left + padding.right + animWidth, padding.left + padding.right + titleSize.width); 319 | height = padding.top + padding.bottom + separatorWidth + animWidth + titleSize.height; 320 | _frame.size = CGSizeMake(width, height); 321 | _frame.origin = CGPointMake(_position.x-_frame.size.width/2, _position.y-_frame.size.height/2); 322 | if (animWidth > 0) { 323 | animFrame = CGRectMake((_frame.size.width-animWidth)/2, padding.top, animWidth, animWidth); 324 | } 325 | titleFrame = CGRectMake((_frame.size.width-titleSize.width)/2, padding.top + separatorWidth + animWidth, titleSize.width, titleSize.height); 326 | } 327 | self.shadeContentView.frame = self.frame; 328 | self.contentView.frame = self.shadeContentView.bounds; 329 | if(! CGRectEqualToRect(titleFrame, CGRectZero)) 330 | self.titleLabel.frame = titleFrame; 331 | if(! CGRectEqualToRect(animFrame, CGRectZero)) 332 | self.animationView.frame = animFrame; 333 | else { 334 | self.animationView.frame = CGRectZero;//// 335 | } 336 | } 337 | 338 | #pragma mark - show hud on window 339 | #pragma mark - show hud on viewController 340 | - (void)setDisposableDelayResponse:(NSTimeInterval)delayResponse delayDismiss:(NSTimeInterval)delayDismiss { 341 | _disposableDelayResponse = delayResponse; 342 | _disposableDelayDismiss = delayDismiss; 343 | } 344 | 345 | /** 346 | 显示Loading 347 | */ 348 | - (void)show { 349 | [self setStyle:XNProgressHUDStyleLoading]; 350 | [self setRefreshStyle:XNAnimationViewStyleLoading]; 351 | [self setTitle:nil]; 352 | [self display]; 353 | } 354 | 355 | - (void)showWithMaskType:(XNProgressHUDMaskType)maskType { 356 | [self setMaskType:maskType]; 357 | [self show]; 358 | } 359 | 360 | /** 361 | * 显示提示文字 362 | */ 363 | - (void)showWithTitle:(nullable NSString *)title { 364 | [self setStyle:XNProgressHUDStyleTitle]; 365 | [self setRefreshStyle:XNAnimationViewStyleNone]; 366 | [self setTitle:title]; 367 | [self display]; 368 | } 369 | 370 | - (void)showWithTitle:(nullable NSString *)title maskType:(XNProgressHUDMaskType)maskType { 371 | [self setMaskType:maskType]; 372 | [self showWithTitle:title]; 373 | } 374 | 375 | /** 376 | * 显示转圈视图 + 提示文字 377 | */ 378 | - (void)showLoadingWithTitle:(nullable NSString *)title { 379 | [self setStyle:[self styleWithTitle:title]]; 380 | [self setRefreshStyle:XNAnimationViewStyleLoading]; 381 | [self setTitle:title]; 382 | [self display]; 383 | } 384 | 385 | - (void)showLoadingWithTitle:(nullable NSString *)title maskType:(XNProgressHUDMaskType)maskType { 386 | [self setMaskType:maskType]; 387 | [self showLoadingWithTitle:title]; 388 | } 389 | 390 | /** 391 | * 进度视图 + 提示文字 392 | */ 393 | - (void)showProgressWithProgress:(float)progress { 394 | [self showProgressWithTitle:nil progress:progress]; 395 | } 396 | 397 | - (void)showProgressWithTitle:(nullable NSString *)title progress:(float)progress { 398 | [self setStyle:[self styleWithTitle:title]]; 399 | [self setRefreshStyle:XNAnimationViewStyleProgress]; 400 | [self setTitle:title]; 401 | [self setProgress:progress]; 402 | [self display]; 403 | } 404 | 405 | - (void)showProgressWithTitle:(nullable NSString *)title progress:(float)progress maskType:(XNProgressHUDMaskType)maskType { 406 | [self setMaskType:maskType]; 407 | [self showProgressWithTitle:title progress:progress]; 408 | } 409 | 410 | /** 411 | * 显示提示视图 + 提示文字 412 | */ 413 | - (void)showInfoWithTitle:(nullable NSString *)title { 414 | [self setStyle:[self styleWithTitle:title]]; 415 | [self setRefreshStyle:XNAnimationViewStyleInfoImage]; 416 | [self setTitle:title]; 417 | [self display]; 418 | } 419 | 420 | - (void)showInfoWithTitle:(nullable NSString *)title maskType:(XNProgressHUDMaskType)maskType { 421 | [self setMaskType:maskType]; 422 | [self showInfoWithTitle:title]; 423 | } 424 | 425 | /** 426 | * 显示提示视图 + 提示文字(操作失败) 427 | */ 428 | - (void)showErrorWithTitle:(nullable NSString *)title { 429 | [self setStyle:[self styleWithTitle:title]]; 430 | [self setRefreshStyle:XNAnimationViewStyleError]; 431 | [self setTitle:title]; 432 | [self display]; 433 | } 434 | 435 | - (void)showErrorWithTitle:(nullable NSString *)title maskType:(XNProgressHUDMaskType)maskType { 436 | [self setMaskType:maskType]; 437 | [self showErrorWithTitle:title]; 438 | } 439 | 440 | /** 441 | * 显示提示视图 + 提示文字(操作成功) 442 | */ 443 | - (void)showSuccessWithTitle:(nullable NSString*)title { 444 | [self setStyle:[self styleWithTitle:title]]; 445 | [self setRefreshStyle:XNAnimationViewStyleSuccess]; 446 | [self setTitle:title]; 447 | [self display]; 448 | } 449 | 450 | - (void)showSuccessWithTitle:(nullable NSString*)title maskType:(XNProgressHUDMaskType)maskType { 451 | [self setMaskType:maskType]; 452 | [self showSuccessWithTitle:title]; 453 | } 454 | 455 | 456 | // 从外界直接关闭,也叫强制关闭,需要清理强引用资源,然后再移除视图 457 | - (void)dismiss { 458 | [self clearUp]; 459 | [self didDismiss]; 460 | } 461 | 462 | - (void)dismissWithDelay:(NSTimeInterval)delay { 463 | if(_showing && delay > 0) { 464 | [self startDismissTimerWithDuration:delay]; 465 | } 466 | } 467 | 468 | - (void)display { 469 | if(self.disposableDelayResponse <= 0 || _showing) { 470 | [self stopTimers]; 471 | [self didDisplay]; 472 | }else{ 473 | [self startDisplayTimerWithDuration:self.disposableDelayResponse]; 474 | } 475 | } 476 | 477 | - (void)didDisplayOnMainQueue { 478 | // 标题 479 | // 样式,设置HUD的显示内容 480 | switch (_style) { 481 | case XNProgressHUDStyleTitle:{ //标题 482 | self.titleLabel.text = self.title; 483 | [self removeFromSuperview:self.animationView]; 484 | [self addSubviewIfNotContain:self.titleLabel superView:self.contentView]; 485 | } 486 | break; 487 | case XNProgressHUDStyleLoading:{ //加载中 488 | self.titleLabel.text = self.title = nil; 489 | [self removeFromSuperview:self.titleLabel]; 490 | [self addSubviewIfNotContain:self.animationView superView:self.contentView]; 491 | } 492 | break; 493 | case XNProgressHUDStyleLoadingAndTitle:{//标题+加载中 494 | self.titleLabel.text = self.title; 495 | [self addSubviewIfNotContain:self.animationView superView:self.contentView]; 496 | [self addSubviewIfNotContain:self.titleLabel superView:self.contentView]; 497 | } 498 | break; 499 | default: 500 | break; 501 | } 502 | // 设置RefreshView的显示内容 503 | [self setStyleInAnimationView:self.refreshStyle]; 504 | if(self.refreshStyle == XNAnimationViewStyleProgress) { 505 | [self setProgressInAnimationView:self.progress]; 506 | } 507 | __block UIView *targetView = self.targetView; 508 | // maskView 509 | if(self.isMaskEnable) { 510 | self.maskView.backgroundColor = [self maskColorWithMaskType:self.maskType]; 511 | [self addSubviewIfNotContain:self.maskView superView:targetView]; 512 | } 513 | // contentView 514 | [self addSubviewIfNotContain:self.shadeContentView superView:targetView]; 515 | // 如果没有显示,需要先调整位置,防止视图跳动 516 | __block BOOL showing = self.showing; 517 | self.showing = YES; 518 | if(showing) { 519 | self.animationView.alpha = 1.f; 520 | } else { 521 | self.maskView.alpha = 0.f; 522 | self.shadeContentView.alpha = 0.f; 523 | [self update]; 524 | } 525 | [self startAnimation]; 526 | if ([self isWindowAndIsNotKeyWindow:(targetView)]) { 527 | targetView.hidden = NO; 528 | } 529 | HUDWeakSelf; 530 | [UIView animateWithDuration:_duration animations:^{ 531 | // 如果正在显示,通过动画过度Frame 532 | if(showing) { 533 | [weakSelf update]; 534 | weakSelf.animationView.alpha = 1.f; 535 | }else{ 536 | weakSelf.maskView.alpha = 1.f; 537 | weakSelf.shadeContentView.alpha = 1.f; 538 | } 539 | } completion:^(BOOL finished) { 540 | weakSelf.disposableDelayResponse = 0.f; 541 | }]; 542 | 543 | // 延时自动消失 544 | if(_disposableDelayDismiss > 0) { 545 | [self startDismissTimerWithDuration:_disposableDelayDismiss]; 546 | }else{ 547 | switch ([self getStyleFromAnimationView]) { 548 | case XNAnimationViewStyleNone: 549 | case XNAnimationViewStyleInfoImage: 550 | case XNAnimationViewStyleError: 551 | case XNAnimationViewStyleSuccess: 552 | [self startDismissTimerWithDuration:self.minimumDelayDismissDuration]; 553 | break; 554 | default: 555 | [self startDismissTimerWithDuration:self.maximumDelayDismissDuration]; 556 | break; 557 | } 558 | } 559 | } 560 | 561 | - (void)didDisplay { 562 | [self performSelectorOnMainThread:@selector(didDisplayOnMainQueue) withObject:nil waitUntilDone:NO]; 563 | } 564 | 565 | - (void)didDismiss { 566 | [self performSelectorOnMainThread:@selector(didDismissOnMainQueue) withObject:nil waitUntilDone:NO]; 567 | } 568 | 569 | // 从内部关闭,由定时器调用或直接调用,无强引用隐患,无需清理强引用资源 570 | - (void)didDismissOnMainQueue { 571 | BOOL showing = self.showing; 572 | if(!showing) return; 573 | self.showing = NO; 574 | if(_hudDismissBlock) _hudDismissBlock(); 575 | [self stopAnimation]; 576 | __block UIView *targetView = self.targetView; 577 | HUDWeakSelf; 578 | [UIView animateWithDuration:self.duration animations:^{ 579 | if(weakSelf.isMaskEnable && weakSelf.maskView) 580 | weakSelf.maskView.alpha = 0.f; 581 | weakSelf.shadeContentView.alpha = 0.f; 582 | } completion:^(BOOL finished) { 583 | if ([self isWindowAndIsNotKeyWindow:(targetView)]) { 584 | targetView.hidden = YES; 585 | } 586 | [weakSelf removeFromSuperview:weakSelf.shadeContentView]; 587 | [weakSelf removeFromSuperview:weakSelf.maskView]; 588 | if(weakSelf.hudDismissBlock) 589 | [weakSelf removeMaskTapGestureEvent]; 590 | weakSelf.disposableDelayDismiss = 0.f; 591 | weakSelf.maskType = XNProgressHUDMaskTypeNone; 592 | }]; 593 | } 594 | 595 | - (void)startDisplayTimerWithDuration:(NSTimeInterval)duration{ 596 | [self stopTimers]; 597 | self.displayTimer = [NSTimer scheduledTimerWithTimeInterval:duration target:self selector:@selector(didDisplay) userInfo:nil repeats:NO]; 598 | } 599 | 600 | - (void)startDismissTimerWithDuration:(NSTimeInterval)duration { 601 | [self stopTimerAndSetItNil:_dismissTimer]; 602 | self.dismissTimer = [NSTimer scheduledTimerWithTimeInterval:duration target:self selector:@selector(didDismiss) userInfo:nil repeats:NO]; 603 | } 604 | 605 | - (void)stopTimers { 606 | [self stopTimerAndSetItNil:_displayTimer]; 607 | [self stopTimerAndSetItNil:_dismissTimer]; 608 | } 609 | 610 | - (void)dealloc { 611 | [self clearUp]; 612 | } 613 | 614 | - (void)clearUp { 615 | [self stopTimers]; 616 | } 617 | 618 | #pragma mark - 控制RefreshView显示状态的方法 619 | - (XNAnimationViewStyle)getStyleFromAnimationView { 620 | XNAnimationViewStyle style = XNAnimationViewStyleNone; 621 | if ([self.animationView respondsToSelector:@selector(xn_getStyle)]) { 622 | NSNumber *value = [self.animationView performSelector:@selector(xn_getStyle)]; 623 | style = value.unsignedIntegerValue; 624 | } 625 | return style; 626 | } 627 | 628 | - (void)setStyleInAnimationView:(XNAnimationViewStyle)style { 629 | if ([self.animationView respondsToSelector:@selector(xn_setStyle:)]) { 630 | NSNumber *value = [NSNumber numberWithUnsignedInteger:style]; 631 | [self.animationView performSelector:@selector(xn_setStyle:) withObject:value]; 632 | } 633 | } 634 | 635 | - (void)startAnimation { 636 | if ([self.animationView respondsToSelector:@selector(xn_startAnimation)]) { 637 | [self.animationView performSelector:@selector(xn_startAnimation)]; 638 | } 639 | } 640 | 641 | - (void)stopAnimation { 642 | if ([self.animationView respondsToSelector:@selector(xn_stopAnimation)]) { 643 | [self.animationView performSelector:@selector(xn_stopAnimation)]; 644 | } 645 | } 646 | 647 | - (void)setProgressInAnimationView:(CGFloat)progress { 648 | if ([self.animationView respondsToSelector:@selector(xn_setProgress:)]) { 649 | NSNumber *value = [NSNumber numberWithFloat:progress]; 650 | [self.animationView performSelector:@selector(xn_setProgress:) withObject:value]; 651 | } 652 | } 653 | @end 654 | 655 | 656 | 657 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017 LuohanCC 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # XNProgressHUD 2 | 3 | 一个丝滑、灵活的HUD 4 | 5 | ![hud-01.gif](http://www.wailian.work/images/2019/07/29/hud-01.gif) 6 | ![hud-02.gif](http://www.wailian.work/images/2019/07/29/hud-02.gif) 7 | ![hud-03.gif](http://www.wailian.work/images/2019/07/29/hud-03.gif) 8 | ![hud-04.gif](http://www.wailian.work/images/2019/07/29/hud-04.gif) 9 | # 10 | 一款支持各种自定义的轻量级HUD,支持垂直、水平两种样式。XNProgressHUD非常灵活,所见的部分都可根据自己的要求进行自定义,包括自义动画效果或图片,只需要实现相关协议方法。 11 | 12 | ## 安装使用 13 | ```ruby 14 | pod 'XNProgressHUD' 15 | ``` 16 | 17 | ## 使用说明 18 | 19 | ```Objective-C 20 | // 设置显示位置 21 | [XNHUD setPosition:CGPointMake(self.view.bounds.size.width/2, self.view.bounds.size.height * 0.7)]; 22 | // 设置主色调 23 | [XNHUD setTintColor:[UIColor colorWithRed:38/255.0 green:50/255.0 blue:56/255.0 alpha:0.8]]; 24 | // 设置相应的maskType状态下的颜色(16进制颜色值) 25 | [XNHUD setMaskType:(XNProgressHUDMaskTypeBlack) hexColor:0x00000044]; 26 | [XNHUD setMaskType:(XNProgressHUDMaskTypeCustom) hexColor:0xff000044]; 27 | ``` 28 | 29 | **在UIWindow上显示:** 30 | ```Objective-C 31 | [XNHUD showLoadingWithTitle:@"正在登录"]; 32 | [XNHUD showWithTitle:@"这是一个支持自定义的轻量级HUD"]; 33 | [XNHUD showInfoWithTitle:@"邮箱地址不能为空"]; 34 | [XNHUD showErrorWithTitle:@"拒绝访问"]; 35 | [XNHUD showSuccessWithTitle:@"操作成功"]; 36 | ``` 37 | 38 | **在UIViewController上显示(maskType.enable=true时,导航栏依然可以接受点击事件)** 39 | ```Objective-C 40 | // 引入'UIViewController+XNProgressHUD.h' 41 | [self.hud showLoadingWithTitle:@"正在登录"]; 42 | [self.hud showWithTitle:@"这是一个支持自定义的轻量级HUD"]; 43 | [self.hud showInfoWithTitle:@"邮箱地址不能为空"]; 44 | [self.hud showErrorWithTitle:@"拒绝访问"]; 45 | [self.hud showSuccessWithTitle:@"操作成功"]; 46 | ``` 47 | 48 | **在UIView上显示** 49 | ```Objective-C 50 | UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 300)]; 51 | [self.view addSubview:view]; 52 | // 设置显示的目标View并传入显示位置 53 | [XNHUD setTargetView:view position:CGPointMake(view.bounds.size.width/2, view.bounds.size.height/2)]; 54 | [XNHUD showLoadingWithTitle:@"指定显示在某个View上"]; 55 | ``` 56 | 57 | ## 属性和方法说明 58 | 显示时长minimumDelayDismissDuration作用于非加载样式的视图:***XNAnimationViewStyleInfoImage、XNAnimationViewStyleError、XNAnimationViewStyleSuccess***; 59 | 显示时长maximumDelayDismissDuration作用与加载样式的视图:***XNAnimationViewStyleLoading、XNAnimationViewStyleProgress***。 60 | ```Objective-C 61 | @property (nonatomic, assign) NSTimeInterval minimumDelayDismissDuration; //default:1.5f 62 | @property (nonatomic, assign) NSTimeInterval maximumDelayDismissDuration; //default:20.f 63 | ``` 64 | 65 | 延时显示时间和延时消失时间,该方法只对下一次HUD显示生效(只生效一次)。 66 | ```Objective-C 67 | [XNHUD setDisposableDelayResponse:1.0f delayDismiss:2.0f]; 68 | ``` 69 | 70 | 设置排列方向,默认为垂直方向 71 | ```Objective-C 72 | [XNHUD setOrientation:XNProgressHUDOrientationHorizontal]; 73 | ``` 74 | 75 | ## 自定义XNProgressHUD 76 | 你可以自定义某一个状态下的动画,步骤非常简单,喜欢XNAnimationView中相应的Layer就行了,如果你想替换所有状态下的动画,请重写XNAnimationView。 77 | 78 | 79 | 80 | 这里就介绍这么多,其他功能自行探索。 81 | 82 | 83 | 84 | 85 | ## GitHub地址 86 | https://github.com/LuohanCC/XNProgressHUD 87 | # 88 | **如果你觉得不错,请给我Star ★★★★★★★★★★** 89 | ![给我Star吧](http://www.wailian.work/images/2018/08/03/star.png) 90 | 91 | 92 | -------------------------------------------------------------------------------- /XNProgressHUD.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod spec lint XNProgressHUD.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 = "XNProgressHUD" 12 | s.version = "1.1.1" 13 | s.summary = "一款支持自定义状态视图的的HUD" 14 | s.description = 15 | <<-DESC 16 | 一款支持自定义状态视图的的HUD,继承自XNProgressHUD并实现XNProgressHUDMethod中的方法。 17 | DESC 18 | 19 | s.homepage = "https://github.com/LuohanCC/XNProgressHUD" 20 | s.license = { :type => 'MIT', :file => 'LICENSE' } 21 | s.author = { "罗函" => "luohancc@163.com" } 22 | s.source = { :git => "https://github.com/LuohanCC/XNProgressHUD.git", :tag => "#{s.version}" } 23 | 24 | s.ios.deployment_target = "7.0" 25 | s.source_files = "Classes/**/*.{h,m}" 26 | s.exclude_files = "Classes/Exclude" 27 | s.framework = "UIKit" 28 | s.requires_arc = true 29 | 30 | end 31 | -------------------------------------------------------------------------------- /XNProgressHUD.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 2842D5B32281D7910023B54C /* XNProgressHUD.podspec in Resources */ = {isa = PBXBuildFile; fileRef = 2842D5AA2281D7910023B54C /* XNProgressHUD.podspec */; }; 11 | 2842D5B42281D7910023B54C /* XNProgressHUD.podspec in Resources */ = {isa = PBXBuildFile; fileRef = 2842D5AC2281D7910023B54C /* XNProgressHUD.podspec */; }; 12 | 2842D5B52281D7910023B54C /* XNProgressHUD.podspec in Resources */ = {isa = PBXBuildFile; fileRef = 2842D5AE2281D7910023B54C /* XNProgressHUD.podspec */; }; 13 | 2842D5B62281D7910023B54C /* XNProgressHUD.podspec in Resources */ = {isa = PBXBuildFile; fileRef = 2842D5B02281D7910023B54C /* XNProgressHUD.podspec */; }; 14 | 2842D5B72281D7910023B54C /* XNProgressHUD.podspec in Resources */ = {isa = PBXBuildFile; fileRef = 2842D5B22281D7910023B54C /* XNProgressHUD.podspec */; }; 15 | 2842D5BA2281D7BC0023B54C /* XNProgressHUD.podspec in Resources */ = {isa = PBXBuildFile; fileRef = 2842D5B92281D7BC0023B54C /* XNProgressHUD.podspec */; }; 16 | 285DF6C220E60386001CD2C0 /* XNProgressHUD.m in Sources */ = {isa = PBXBuildFile; fileRef = 285DF6BC20E60386001CD2C0 /* XNProgressHUD.m */; }; 17 | 285DF6C320E60386001CD2C0 /* UIViewController+XNProgressHUD.m in Sources */ = {isa = PBXBuildFile; fileRef = 285DF6BF20E60386001CD2C0 /* UIViewController+XNProgressHUD.m */; }; 18 | 28A0B390207C9E9400D03037 /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = 28A0B38E207C9E9400D03037 /* README.md */; }; 19 | 28A0B391207C9E9400D03037 /* XNProgressHUD.podspec in Resources */ = {isa = PBXBuildFile; fileRef = 28A0B38F207C9E9400D03037 /* XNProgressHUD.podspec */; }; 20 | 28A0B39E207CA6B700D03037 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 28A0B394207CA6B700D03037 /* Assets.xcassets */; }; 21 | 28A0B39F207CA6B700D03037 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 28A0B395207CA6B700D03037 /* ViewController.m */; }; 22 | 28A0B3A0207CA6B700D03037 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 28A0B396207CA6B700D03037 /* LaunchScreen.storyboard */; }; 23 | 28A0B3A1207CA6B700D03037 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 28A0B398207CA6B700D03037 /* Main.storyboard */; }; 24 | 28A0B3A2207CA6B700D03037 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 28A0B39A207CA6B700D03037 /* main.m */; }; 25 | 28A0B3A3207CA6B700D03037 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 28A0B39B207CA6B700D03037 /* AppDelegate.m */; }; 26 | 28A0B3A4207CA6B700D03037 /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 28A0B39C207CA6B700D03037 /* Info.plist */; }; 27 | 28DFD3F42080B24F00AE575B /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = 28DFD3F32080B24E00AE575B /* LICENSE */; }; 28 | 8EAECBC2228281C100919658 /* XNProgressHUD.podspec in Resources */ = {isa = PBXBuildFile; fileRef = 8EAECBC1228281C100919658 /* XNProgressHUD.podspec */; }; 29 | 9A7E97DF22E2B99C00E47064 /* XNAnimationView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A7E97DE22E2B99C00E47064 /* XNAnimationView.m */; }; 30 | 9A7E97E622E2ECF300E47064 /* XNHUDErrorLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A7E97E522E2ECF300E47064 /* XNHUDErrorLayer.m */; }; 31 | 9A7E97EC22E2ED5C00E47064 /* XNHUDProgressLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A7E97EB22E2ED5C00E47064 /* XNHUDProgressLayer.m */; }; 32 | 9A7E97EF22E2ED7100E47064 /* XNHUDSuccessLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A7E97EE22E2ED7100E47064 /* XNHUDSuccessLayer.m */; }; 33 | 9A7E97F222E2ED8900E47064 /* XNHUDLoadingLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A7E97F122E2ED8900E47064 /* XNHUDLoadingLayer.m */; }; 34 | 9A7E97F622E556B900E47064 /* XNHUDInfoLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A7E97F522E556B900E47064 /* XNHUDInfoLayer.m */; }; 35 | 9AEC3AEA22EE91B200EF8B97 /* CustomHUDLoadingLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 9AEC3AE922EE91B200EF8B97 /* CustomHUDLoadingLayer.m */; }; 36 | /* End PBXBuildFile section */ 37 | 38 | /* Begin PBXContainerItemProxy section */ 39 | 28A0B372207C9DCB00D03037 /* PBXContainerItemProxy */ = { 40 | isa = PBXContainerItemProxy; 41 | containerPortal = 28A0B351207C9DC900D03037 /* Project object */; 42 | proxyType = 1; 43 | remoteGlobalIDString = 28A0B358207C9DC900D03037; 44 | remoteInfo = XNProgressHUD; 45 | }; 46 | 28A0B37D207C9DCB00D03037 /* PBXContainerItemProxy */ = { 47 | isa = PBXContainerItemProxy; 48 | containerPortal = 28A0B351207C9DC900D03037 /* Project object */; 49 | proxyType = 1; 50 | remoteGlobalIDString = 28A0B358207C9DC900D03037; 51 | remoteInfo = XNProgressHUD; 52 | }; 53 | /* End PBXContainerItemProxy section */ 54 | 55 | /* Begin PBXFileReference section */ 56 | 2842D5AA2281D7910023B54C /* XNProgressHUD.podspec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = XNProgressHUD.podspec; sourceTree = ""; }; 57 | 2842D5AC2281D7910023B54C /* XNProgressHUD.podspec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = XNProgressHUD.podspec; sourceTree = ""; }; 58 | 2842D5AE2281D7910023B54C /* XNProgressHUD.podspec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = XNProgressHUD.podspec; sourceTree = ""; }; 59 | 2842D5B02281D7910023B54C /* XNProgressHUD.podspec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = XNProgressHUD.podspec; sourceTree = ""; }; 60 | 2842D5B22281D7910023B54C /* XNProgressHUD.podspec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = XNProgressHUD.podspec; sourceTree = ""; }; 61 | 2842D5B92281D7BC0023B54C /* XNProgressHUD.podspec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = XNProgressHUD.podspec; sourceTree = ""; }; 62 | 285DF6BB20E60386001CD2C0 /* UIViewController+XNProgressHUD.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIViewController+XNProgressHUD.h"; sourceTree = ""; }; 63 | 285DF6BC20E60386001CD2C0 /* XNProgressHUD.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XNProgressHUD.m; sourceTree = ""; }; 64 | 285DF6BD20E60386001CD2C0 /* XNAnimaionViewProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XNAnimaionViewProtocol.h; sourceTree = ""; }; 65 | 285DF6BF20E60386001CD2C0 /* UIViewController+XNProgressHUD.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIViewController+XNProgressHUD.m"; sourceTree = ""; }; 66 | 285DF6C020E60386001CD2C0 /* XNProgressHUD.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XNProgressHUD.h; sourceTree = ""; }; 67 | 28A0B359207C9DC900D03037 /* XNProgressHUD.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = XNProgressHUD.app; sourceTree = BUILT_PRODUCTS_DIR; }; 68 | 28A0B371207C9DCB00D03037 /* XNProgressHUDTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = XNProgressHUDTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 69 | 28A0B37C207C9DCB00D03037 /* XNProgressHUDUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = XNProgressHUDUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 70 | 28A0B38E207C9E9400D03037 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; 71 | 28A0B38F207C9E9400D03037 /* XNProgressHUD.podspec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = XNProgressHUD.podspec; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 72 | 28A0B393207CA6B700D03037 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 73 | 28A0B394207CA6B700D03037 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 74 | 28A0B395207CA6B700D03037 /* ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 75 | 28A0B397207CA6B700D03037 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 76 | 28A0B399207CA6B700D03037 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 77 | 28A0B39A207CA6B700D03037 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 78 | 28A0B39B207CA6B700D03037 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; wrapsLines = 0; }; 79 | 28A0B39C207CA6B700D03037 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 80 | 28A0B39D207CA6B700D03037 /* ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 81 | 28DFD3F32080B24E00AE575B /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; 82 | 8EAECBC1228281C100919658 /* XNProgressHUD.podspec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = XNProgressHUD.podspec; sourceTree = ""; }; 83 | 9A7E97DD22E2B99C00E47064 /* XNAnimationView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XNAnimationView.h; sourceTree = ""; }; 84 | 9A7E97DE22E2B99C00E47064 /* XNAnimationView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = XNAnimationView.m; sourceTree = ""; }; 85 | 9A7E97E422E2ECF300E47064 /* XNHUDErrorLayer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XNHUDErrorLayer.h; sourceTree = ""; }; 86 | 9A7E97E522E2ECF300E47064 /* XNHUDErrorLayer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = XNHUDErrorLayer.m; sourceTree = ""; }; 87 | 9A7E97EA22E2ED5C00E47064 /* XNHUDProgressLayer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XNHUDProgressLayer.h; sourceTree = ""; }; 88 | 9A7E97EB22E2ED5C00E47064 /* XNHUDProgressLayer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = XNHUDProgressLayer.m; sourceTree = ""; }; 89 | 9A7E97ED22E2ED7100E47064 /* XNHUDSuccessLayer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XNHUDSuccessLayer.h; sourceTree = ""; }; 90 | 9A7E97EE22E2ED7100E47064 /* XNHUDSuccessLayer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = XNHUDSuccessLayer.m; sourceTree = ""; }; 91 | 9A7E97F022E2ED8900E47064 /* XNHUDLoadingLayer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XNHUDLoadingLayer.h; sourceTree = ""; }; 92 | 9A7E97F122E2ED8900E47064 /* XNHUDLoadingLayer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = XNHUDLoadingLayer.m; sourceTree = ""; }; 93 | 9A7E97F322E2EDD800E47064 /* XNHUDLayerProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XNHUDLayerProtocol.h; sourceTree = ""; }; 94 | 9A7E97F422E556B900E47064 /* XNHUDInfoLayer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XNHUDInfoLayer.h; sourceTree = ""; }; 95 | 9A7E97F522E556B900E47064 /* XNHUDInfoLayer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = XNHUDInfoLayer.m; sourceTree = ""; }; 96 | 9AEC3AE822EE91B200EF8B97 /* CustomHUDLoadingLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CustomHUDLoadingLayer.h; sourceTree = ""; }; 97 | 9AEC3AE922EE91B200EF8B97 /* CustomHUDLoadingLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CustomHUDLoadingLayer.m; sourceTree = ""; }; 98 | /* End PBXFileReference section */ 99 | 100 | /* Begin PBXFrameworksBuildPhase section */ 101 | 28A0B356207C9DC900D03037 /* Frameworks */ = { 102 | isa = PBXFrameworksBuildPhase; 103 | buildActionMask = 2147483647; 104 | files = ( 105 | ); 106 | runOnlyForDeploymentPostprocessing = 0; 107 | }; 108 | 28A0B36E207C9DCB00D03037 /* Frameworks */ = { 109 | isa = PBXFrameworksBuildPhase; 110 | buildActionMask = 2147483647; 111 | files = ( 112 | ); 113 | runOnlyForDeploymentPostprocessing = 0; 114 | }; 115 | 28A0B379207C9DCB00D03037 /* Frameworks */ = { 116 | isa = PBXFrameworksBuildPhase; 117 | buildActionMask = 2147483647; 118 | files = ( 119 | ); 120 | runOnlyForDeploymentPostprocessing = 0; 121 | }; 122 | /* End PBXFrameworksBuildPhase section */ 123 | 124 | /* Begin PBXGroup section */ 125 | 2842D5A82281D7910023B54C /* XNProgressHUD */ = { 126 | isa = PBXGroup; 127 | children = ( 128 | 8EAECBC0228281C100919658 /* 1.1.0 */, 129 | 2842D5B82281D7BC0023B54C /* 1.0.9 */, 130 | 2842D5A92281D7910023B54C /* 1.0.7 */, 131 | 2842D5AB2281D7910023B54C /* 1.0.8 */, 132 | 2842D5AD2281D7910023B54C /* 1.0.4 */, 133 | 2842D5AF2281D7910023B54C /* 1.0.3 */, 134 | 2842D5B12281D7910023B54C /* 1.0.5 */, 135 | ); 136 | path = XNProgressHUD; 137 | sourceTree = ""; 138 | }; 139 | 2842D5A92281D7910023B54C /* 1.0.7 */ = { 140 | isa = PBXGroup; 141 | children = ( 142 | 2842D5AA2281D7910023B54C /* XNProgressHUD.podspec */, 143 | ); 144 | path = 1.0.7; 145 | sourceTree = ""; 146 | }; 147 | 2842D5AB2281D7910023B54C /* 1.0.8 */ = { 148 | isa = PBXGroup; 149 | children = ( 150 | 2842D5AC2281D7910023B54C /* XNProgressHUD.podspec */, 151 | ); 152 | path = 1.0.8; 153 | sourceTree = ""; 154 | }; 155 | 2842D5AD2281D7910023B54C /* 1.0.4 */ = { 156 | isa = PBXGroup; 157 | children = ( 158 | 2842D5AE2281D7910023B54C /* XNProgressHUD.podspec */, 159 | ); 160 | path = 1.0.4; 161 | sourceTree = ""; 162 | }; 163 | 2842D5AF2281D7910023B54C /* 1.0.3 */ = { 164 | isa = PBXGroup; 165 | children = ( 166 | 2842D5B02281D7910023B54C /* XNProgressHUD.podspec */, 167 | ); 168 | path = 1.0.3; 169 | sourceTree = ""; 170 | }; 171 | 2842D5B12281D7910023B54C /* 1.0.5 */ = { 172 | isa = PBXGroup; 173 | children = ( 174 | 2842D5B22281D7910023B54C /* XNProgressHUD.podspec */, 175 | ); 176 | path = 1.0.5; 177 | sourceTree = ""; 178 | }; 179 | 2842D5B82281D7BC0023B54C /* 1.0.9 */ = { 180 | isa = PBXGroup; 181 | children = ( 182 | 2842D5B92281D7BC0023B54C /* XNProgressHUD.podspec */, 183 | ); 184 | path = 1.0.9; 185 | sourceTree = ""; 186 | }; 187 | 285DF6B920E60386001CD2C0 /* Classes */ = { 188 | isa = PBXGroup; 189 | children = ( 190 | 9A7E97F722E599C000E47064 /* XNHUDAnimationView */, 191 | 285DF6BB20E60386001CD2C0 /* UIViewController+XNProgressHUD.h */, 192 | 285DF6BF20E60386001CD2C0 /* UIViewController+XNProgressHUD.m */, 193 | 285DF6C020E60386001CD2C0 /* XNProgressHUD.h */, 194 | 285DF6BC20E60386001CD2C0 /* XNProgressHUD.m */, 195 | 285DF6BD20E60386001CD2C0 /* XNAnimaionViewProtocol.h */, 196 | ); 197 | path = Classes; 198 | sourceTree = ""; 199 | }; 200 | 28A0B350207C9DC900D03037 = { 201 | isa = PBXGroup; 202 | children = ( 203 | 2842D5A82281D7910023B54C /* XNProgressHUD */, 204 | 285DF6B920E60386001CD2C0 /* Classes */, 205 | 28A0B392207CA6B700D03037 /* demo */, 206 | 28A0B38E207C9E9400D03037 /* README.md */, 207 | 28A0B38F207C9E9400D03037 /* XNProgressHUD.podspec */, 208 | 28DFD3F32080B24E00AE575B /* LICENSE */, 209 | 28A0B35A207C9DC900D03037 /* Products */, 210 | ); 211 | sourceTree = ""; 212 | }; 213 | 28A0B35A207C9DC900D03037 /* Products */ = { 214 | isa = PBXGroup; 215 | children = ( 216 | 28A0B359207C9DC900D03037 /* XNProgressHUD.app */, 217 | 28A0B371207C9DCB00D03037 /* XNProgressHUDTests.xctest */, 218 | 28A0B37C207C9DCB00D03037 /* XNProgressHUDUITests.xctest */, 219 | ); 220 | name = Products; 221 | sourceTree = ""; 222 | }; 223 | 28A0B392207CA6B700D03037 /* demo */ = { 224 | isa = PBXGroup; 225 | children = ( 226 | 9A7E97E022E2EC8900E47064 /* custom */, 227 | 28A0B393207CA6B700D03037 /* AppDelegate.h */, 228 | 28A0B39B207CA6B700D03037 /* AppDelegate.m */, 229 | 28A0B394207CA6B700D03037 /* Assets.xcassets */, 230 | 28A0B39C207CA6B700D03037 /* Info.plist */, 231 | 28A0B396207CA6B700D03037 /* LaunchScreen.storyboard */, 232 | 28A0B39A207CA6B700D03037 /* main.m */, 233 | 28A0B398207CA6B700D03037 /* Main.storyboard */, 234 | 28A0B39D207CA6B700D03037 /* ViewController.h */, 235 | 28A0B395207CA6B700D03037 /* ViewController.m */, 236 | ); 237 | path = demo; 238 | sourceTree = ""; 239 | }; 240 | 8EAECBC0228281C100919658 /* 1.1.0 */ = { 241 | isa = PBXGroup; 242 | children = ( 243 | 8EAECBC1228281C100919658 /* XNProgressHUD.podspec */, 244 | ); 245 | path = 1.1.0; 246 | sourceTree = ""; 247 | }; 248 | 9A7E97E022E2EC8900E47064 /* custom */ = { 249 | isa = PBXGroup; 250 | children = ( 251 | 9AEC3AE822EE91B200EF8B97 /* CustomHUDLoadingLayer.h */, 252 | 9AEC3AE922EE91B200EF8B97 /* CustomHUDLoadingLayer.m */, 253 | ); 254 | path = custom; 255 | sourceTree = ""; 256 | }; 257 | 9A7E97F722E599C000E47064 /* XNHUDAnimationView */ = { 258 | isa = PBXGroup; 259 | children = ( 260 | 9A7E97F322E2EDD800E47064 /* XNHUDLayerProtocol.h */, 261 | 9A7E97DD22E2B99C00E47064 /* XNAnimationView.h */, 262 | 9A7E97DE22E2B99C00E47064 /* XNAnimationView.m */, 263 | 9A7E97E422E2ECF300E47064 /* XNHUDErrorLayer.h */, 264 | 9A7E97E522E2ECF300E47064 /* XNHUDErrorLayer.m */, 265 | 9A7E97EA22E2ED5C00E47064 /* XNHUDProgressLayer.h */, 266 | 9A7E97EB22E2ED5C00E47064 /* XNHUDProgressLayer.m */, 267 | 9A7E97ED22E2ED7100E47064 /* XNHUDSuccessLayer.h */, 268 | 9A7E97EE22E2ED7100E47064 /* XNHUDSuccessLayer.m */, 269 | 9A7E97F022E2ED8900E47064 /* XNHUDLoadingLayer.h */, 270 | 9A7E97F122E2ED8900E47064 /* XNHUDLoadingLayer.m */, 271 | 9A7E97F422E556B900E47064 /* XNHUDInfoLayer.h */, 272 | 9A7E97F522E556B900E47064 /* XNHUDInfoLayer.m */, 273 | ); 274 | path = XNHUDAnimationView; 275 | sourceTree = ""; 276 | }; 277 | /* End PBXGroup section */ 278 | 279 | /* Begin PBXNativeTarget section */ 280 | 28A0B358207C9DC900D03037 /* XNProgressHUD */ = { 281 | isa = PBXNativeTarget; 282 | buildConfigurationList = 28A0B385207C9DCB00D03037 /* Build configuration list for PBXNativeTarget "XNProgressHUD" */; 283 | buildPhases = ( 284 | 28A0B355207C9DC900D03037 /* Sources */, 285 | 28A0B356207C9DC900D03037 /* Frameworks */, 286 | 28A0B357207C9DC900D03037 /* Resources */, 287 | ); 288 | buildRules = ( 289 | ); 290 | dependencies = ( 291 | ); 292 | name = XNProgressHUD; 293 | productName = XNProgressHUD; 294 | productReference = 28A0B359207C9DC900D03037 /* XNProgressHUD.app */; 295 | productType = "com.apple.product-type.application"; 296 | }; 297 | 28A0B370207C9DCB00D03037 /* XNProgressHUDTests */ = { 298 | isa = PBXNativeTarget; 299 | buildConfigurationList = 28A0B388207C9DCB00D03037 /* Build configuration list for PBXNativeTarget "XNProgressHUDTests" */; 300 | buildPhases = ( 301 | 28A0B36D207C9DCB00D03037 /* Sources */, 302 | 28A0B36E207C9DCB00D03037 /* Frameworks */, 303 | 28A0B36F207C9DCB00D03037 /* Resources */, 304 | ); 305 | buildRules = ( 306 | ); 307 | dependencies = ( 308 | 28A0B373207C9DCB00D03037 /* PBXTargetDependency */, 309 | ); 310 | name = XNProgressHUDTests; 311 | productName = XNProgressHUDTests; 312 | productReference = 28A0B371207C9DCB00D03037 /* XNProgressHUDTests.xctest */; 313 | productType = "com.apple.product-type.bundle.unit-test"; 314 | }; 315 | 28A0B37B207C9DCB00D03037 /* XNProgressHUDUITests */ = { 316 | isa = PBXNativeTarget; 317 | buildConfigurationList = 28A0B38B207C9DCB00D03037 /* Build configuration list for PBXNativeTarget "XNProgressHUDUITests" */; 318 | buildPhases = ( 319 | 28A0B378207C9DCB00D03037 /* Sources */, 320 | 28A0B379207C9DCB00D03037 /* Frameworks */, 321 | 28A0B37A207C9DCB00D03037 /* Resources */, 322 | ); 323 | buildRules = ( 324 | ); 325 | dependencies = ( 326 | 28A0B37E207C9DCB00D03037 /* PBXTargetDependency */, 327 | ); 328 | name = XNProgressHUDUITests; 329 | productName = XNProgressHUDUITests; 330 | productReference = 28A0B37C207C9DCB00D03037 /* XNProgressHUDUITests.xctest */; 331 | productType = "com.apple.product-type.bundle.ui-testing"; 332 | }; 333 | /* End PBXNativeTarget section */ 334 | 335 | /* Begin PBXProject section */ 336 | 28A0B351207C9DC900D03037 /* Project object */ = { 337 | isa = PBXProject; 338 | attributes = { 339 | LastUpgradeCheck = 0930; 340 | ORGANIZATIONNAME = "罗函"; 341 | TargetAttributes = { 342 | 28A0B358207C9DC900D03037 = { 343 | CreatedOnToolsVersion = 9.3; 344 | }; 345 | 28A0B370207C9DCB00D03037 = { 346 | CreatedOnToolsVersion = 9.3; 347 | TestTargetID = 28A0B358207C9DC900D03037; 348 | }; 349 | 28A0B37B207C9DCB00D03037 = { 350 | CreatedOnToolsVersion = 9.3; 351 | TestTargetID = 28A0B358207C9DC900D03037; 352 | }; 353 | }; 354 | }; 355 | buildConfigurationList = 28A0B354207C9DC900D03037 /* Build configuration list for PBXProject "XNProgressHUD" */; 356 | compatibilityVersion = "Xcode 9.3"; 357 | developmentRegion = en; 358 | hasScannedForEncodings = 0; 359 | knownRegions = ( 360 | en, 361 | Base, 362 | ); 363 | mainGroup = 28A0B350207C9DC900D03037; 364 | productRefGroup = 28A0B35A207C9DC900D03037 /* Products */; 365 | projectDirPath = ""; 366 | projectRoot = ""; 367 | targets = ( 368 | 28A0B358207C9DC900D03037 /* XNProgressHUD */, 369 | 28A0B370207C9DCB00D03037 /* XNProgressHUDTests */, 370 | 28A0B37B207C9DCB00D03037 /* XNProgressHUDUITests */, 371 | ); 372 | }; 373 | /* End PBXProject section */ 374 | 375 | /* Begin PBXResourcesBuildPhase section */ 376 | 28A0B357207C9DC900D03037 /* Resources */ = { 377 | isa = PBXResourcesBuildPhase; 378 | buildActionMask = 2147483647; 379 | files = ( 380 | 28A0B391207C9E9400D03037 /* XNProgressHUD.podspec in Resources */, 381 | 28A0B3A1207CA6B700D03037 /* Main.storyboard in Resources */, 382 | 28A0B3A4207CA6B700D03037 /* Info.plist in Resources */, 383 | 2842D5BA2281D7BC0023B54C /* XNProgressHUD.podspec in Resources */, 384 | 28DFD3F42080B24F00AE575B /* LICENSE in Resources */, 385 | 2842D5B62281D7910023B54C /* XNProgressHUD.podspec in Resources */, 386 | 28A0B3A0207CA6B700D03037 /* LaunchScreen.storyboard in Resources */, 387 | 2842D5B52281D7910023B54C /* XNProgressHUD.podspec in Resources */, 388 | 2842D5B32281D7910023B54C /* XNProgressHUD.podspec in Resources */, 389 | 2842D5B42281D7910023B54C /* XNProgressHUD.podspec in Resources */, 390 | 2842D5B72281D7910023B54C /* XNProgressHUD.podspec in Resources */, 391 | 8EAECBC2228281C100919658 /* XNProgressHUD.podspec in Resources */, 392 | 28A0B39E207CA6B700D03037 /* Assets.xcassets in Resources */, 393 | 28A0B390207C9E9400D03037 /* README.md in Resources */, 394 | ); 395 | runOnlyForDeploymentPostprocessing = 0; 396 | }; 397 | 28A0B36F207C9DCB00D03037 /* Resources */ = { 398 | isa = PBXResourcesBuildPhase; 399 | buildActionMask = 2147483647; 400 | files = ( 401 | ); 402 | runOnlyForDeploymentPostprocessing = 0; 403 | }; 404 | 28A0B37A207C9DCB00D03037 /* Resources */ = { 405 | isa = PBXResourcesBuildPhase; 406 | buildActionMask = 2147483647; 407 | files = ( 408 | ); 409 | runOnlyForDeploymentPostprocessing = 0; 410 | }; 411 | /* End PBXResourcesBuildPhase section */ 412 | 413 | /* Begin PBXSourcesBuildPhase section */ 414 | 28A0B355207C9DC900D03037 /* Sources */ = { 415 | isa = PBXSourcesBuildPhase; 416 | buildActionMask = 2147483647; 417 | files = ( 418 | 9A7E97F222E2ED8900E47064 /* XNHUDLoadingLayer.m in Sources */, 419 | 285DF6C320E60386001CD2C0 /* UIViewController+XNProgressHUD.m in Sources */, 420 | 285DF6C220E60386001CD2C0 /* XNProgressHUD.m in Sources */, 421 | 28A0B3A2207CA6B700D03037 /* main.m in Sources */, 422 | 9AEC3AEA22EE91B200EF8B97 /* CustomHUDLoadingLayer.m in Sources */, 423 | 9A7E97EF22E2ED7100E47064 /* XNHUDSuccessLayer.m in Sources */, 424 | 28A0B39F207CA6B700D03037 /* ViewController.m in Sources */, 425 | 28A0B3A3207CA6B700D03037 /* AppDelegate.m in Sources */, 426 | 9A7E97E622E2ECF300E47064 /* XNHUDErrorLayer.m in Sources */, 427 | 9A7E97DF22E2B99C00E47064 /* XNAnimationView.m in Sources */, 428 | 9A7E97EC22E2ED5C00E47064 /* XNHUDProgressLayer.m in Sources */, 429 | 9A7E97F622E556B900E47064 /* XNHUDInfoLayer.m in Sources */, 430 | ); 431 | runOnlyForDeploymentPostprocessing = 0; 432 | }; 433 | 28A0B36D207C9DCB00D03037 /* Sources */ = { 434 | isa = PBXSourcesBuildPhase; 435 | buildActionMask = 2147483647; 436 | files = ( 437 | ); 438 | runOnlyForDeploymentPostprocessing = 0; 439 | }; 440 | 28A0B378207C9DCB00D03037 /* Sources */ = { 441 | isa = PBXSourcesBuildPhase; 442 | buildActionMask = 2147483647; 443 | files = ( 444 | ); 445 | runOnlyForDeploymentPostprocessing = 0; 446 | }; 447 | /* End PBXSourcesBuildPhase section */ 448 | 449 | /* Begin PBXTargetDependency section */ 450 | 28A0B373207C9DCB00D03037 /* PBXTargetDependency */ = { 451 | isa = PBXTargetDependency; 452 | target = 28A0B358207C9DC900D03037 /* XNProgressHUD */; 453 | targetProxy = 28A0B372207C9DCB00D03037 /* PBXContainerItemProxy */; 454 | }; 455 | 28A0B37E207C9DCB00D03037 /* PBXTargetDependency */ = { 456 | isa = PBXTargetDependency; 457 | target = 28A0B358207C9DC900D03037 /* XNProgressHUD */; 458 | targetProxy = 28A0B37D207C9DCB00D03037 /* PBXContainerItemProxy */; 459 | }; 460 | /* End PBXTargetDependency section */ 461 | 462 | /* Begin PBXVariantGroup section */ 463 | 28A0B396207CA6B700D03037 /* LaunchScreen.storyboard */ = { 464 | isa = PBXVariantGroup; 465 | children = ( 466 | 28A0B397207CA6B700D03037 /* Base */, 467 | ); 468 | name = LaunchScreen.storyboard; 469 | sourceTree = ""; 470 | }; 471 | 28A0B398207CA6B700D03037 /* Main.storyboard */ = { 472 | isa = PBXVariantGroup; 473 | children = ( 474 | 28A0B399207CA6B700D03037 /* Base */, 475 | ); 476 | name = Main.storyboard; 477 | sourceTree = ""; 478 | }; 479 | /* End PBXVariantGroup section */ 480 | 481 | /* Begin XCBuildConfiguration section */ 482 | 28A0B383207C9DCB00D03037 /* Debug */ = { 483 | isa = XCBuildConfiguration; 484 | buildSettings = { 485 | ALWAYS_SEARCH_USER_PATHS = NO; 486 | CLANG_ANALYZER_NONNULL = YES; 487 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 488 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 489 | CLANG_CXX_LIBRARY = "libc++"; 490 | CLANG_ENABLE_MODULES = YES; 491 | CLANG_ENABLE_OBJC_ARC = YES; 492 | CLANG_ENABLE_OBJC_WEAK = YES; 493 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 494 | CLANG_WARN_BOOL_CONVERSION = YES; 495 | CLANG_WARN_COMMA = YES; 496 | CLANG_WARN_CONSTANT_CONVERSION = YES; 497 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 498 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 499 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 500 | CLANG_WARN_EMPTY_BODY = YES; 501 | CLANG_WARN_ENUM_CONVERSION = YES; 502 | CLANG_WARN_INFINITE_RECURSION = YES; 503 | CLANG_WARN_INT_CONVERSION = YES; 504 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 505 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 506 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 507 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 508 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 509 | CLANG_WARN_STRICT_PROTOTYPES = YES; 510 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 511 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 512 | CLANG_WARN_UNREACHABLE_CODE = YES; 513 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 514 | CODE_SIGN_IDENTITY = "iPhone Developer"; 515 | COPY_PHASE_STRIP = NO; 516 | DEBUG_INFORMATION_FORMAT = dwarf; 517 | ENABLE_STRICT_OBJC_MSGSEND = YES; 518 | ENABLE_TESTABILITY = YES; 519 | GCC_C_LANGUAGE_STANDARD = gnu11; 520 | GCC_DYNAMIC_NO_PIC = NO; 521 | GCC_NO_COMMON_BLOCKS = YES; 522 | GCC_OPTIMIZATION_LEVEL = 0; 523 | GCC_PREPROCESSOR_DEFINITIONS = ( 524 | "DEBUG=1", 525 | "$(inherited)", 526 | ); 527 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 528 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 529 | GCC_WARN_UNDECLARED_SELECTOR = YES; 530 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 531 | GCC_WARN_UNUSED_FUNCTION = YES; 532 | GCC_WARN_UNUSED_VARIABLE = YES; 533 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 534 | MTL_ENABLE_DEBUG_INFO = YES; 535 | ONLY_ACTIVE_ARCH = YES; 536 | SDKROOT = iphoneos; 537 | }; 538 | name = Debug; 539 | }; 540 | 28A0B384207C9DCB00D03037 /* Release */ = { 541 | isa = XCBuildConfiguration; 542 | buildSettings = { 543 | ALWAYS_SEARCH_USER_PATHS = NO; 544 | CLANG_ANALYZER_NONNULL = YES; 545 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 546 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 547 | CLANG_CXX_LIBRARY = "libc++"; 548 | CLANG_ENABLE_MODULES = YES; 549 | CLANG_ENABLE_OBJC_ARC = YES; 550 | CLANG_ENABLE_OBJC_WEAK = YES; 551 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 552 | CLANG_WARN_BOOL_CONVERSION = YES; 553 | CLANG_WARN_COMMA = YES; 554 | CLANG_WARN_CONSTANT_CONVERSION = YES; 555 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 556 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 557 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 558 | CLANG_WARN_EMPTY_BODY = YES; 559 | CLANG_WARN_ENUM_CONVERSION = YES; 560 | CLANG_WARN_INFINITE_RECURSION = YES; 561 | CLANG_WARN_INT_CONVERSION = YES; 562 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 563 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 564 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 565 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 566 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 567 | CLANG_WARN_STRICT_PROTOTYPES = YES; 568 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 569 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 570 | CLANG_WARN_UNREACHABLE_CODE = YES; 571 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 572 | CODE_SIGN_IDENTITY = "iPhone Developer"; 573 | COPY_PHASE_STRIP = NO; 574 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 575 | ENABLE_NS_ASSERTIONS = NO; 576 | ENABLE_STRICT_OBJC_MSGSEND = YES; 577 | GCC_C_LANGUAGE_STANDARD = gnu11; 578 | GCC_NO_COMMON_BLOCKS = YES; 579 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 580 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 581 | GCC_WARN_UNDECLARED_SELECTOR = YES; 582 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 583 | GCC_WARN_UNUSED_FUNCTION = YES; 584 | GCC_WARN_UNUSED_VARIABLE = YES; 585 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 586 | MTL_ENABLE_DEBUG_INFO = NO; 587 | SDKROOT = iphoneos; 588 | VALIDATE_PRODUCT = YES; 589 | }; 590 | name = Release; 591 | }; 592 | 28A0B386207C9DCB00D03037 /* Debug */ = { 593 | isa = XCBuildConfiguration; 594 | buildSettings = { 595 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 596 | CODE_SIGN_IDENTITY = "iPhone Developer"; 597 | CODE_SIGN_STYLE = Automatic; 598 | DEVELOPMENT_TEAM = H2V5ST8BY2; 599 | INFOPLIST_FILE = "$(SRCROOT)/Demo/Info.plist"; 600 | LD_RUNPATH_SEARCH_PATHS = ( 601 | "$(inherited)", 602 | "@executable_path/Frameworks", 603 | ); 604 | PRODUCT_BUNDLE_IDENTIFIER = com.luohancc.XNProgressHUD; 605 | PRODUCT_NAME = "$(TARGET_NAME)"; 606 | PROVISIONING_PROFILE_SPECIFIER = ""; 607 | TARGETED_DEVICE_FAMILY = "1,2"; 608 | }; 609 | name = Debug; 610 | }; 611 | 28A0B387207C9DCB00D03037 /* Release */ = { 612 | isa = XCBuildConfiguration; 613 | buildSettings = { 614 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 615 | CODE_SIGN_IDENTITY = "iPhone Developer"; 616 | CODE_SIGN_STYLE = Automatic; 617 | DEVELOPMENT_TEAM = H2V5ST8BY2; 618 | INFOPLIST_FILE = "$(SRCROOT)/Demo/Info.plist"; 619 | LD_RUNPATH_SEARCH_PATHS = ( 620 | "$(inherited)", 621 | "@executable_path/Frameworks", 622 | ); 623 | PRODUCT_BUNDLE_IDENTIFIER = com.luohancc.XNProgressHUD; 624 | PRODUCT_NAME = "$(TARGET_NAME)"; 625 | PROVISIONING_PROFILE_SPECIFIER = ""; 626 | TARGETED_DEVICE_FAMILY = "1,2"; 627 | }; 628 | name = Release; 629 | }; 630 | 28A0B389207C9DCB00D03037 /* Debug */ = { 631 | isa = XCBuildConfiguration; 632 | buildSettings = { 633 | BUNDLE_LOADER = "$(TEST_HOST)"; 634 | CODE_SIGN_STYLE = Automatic; 635 | DEVELOPMENT_TEAM = 6B7777MZAW; 636 | INFOPLIST_FILE = XNProgressHUDTests/Info.plist; 637 | LD_RUNPATH_SEARCH_PATHS = ( 638 | "$(inherited)", 639 | "@executable_path/Frameworks", 640 | "@loader_path/Frameworks", 641 | ); 642 | PRODUCT_BUNDLE_IDENTIFIER = com.luohan.XNProgressHUDTests; 643 | PRODUCT_NAME = "$(TARGET_NAME)"; 644 | TARGETED_DEVICE_FAMILY = "1,2"; 645 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/XNProgressHUD.app/XNProgressHUD"; 646 | }; 647 | name = Debug; 648 | }; 649 | 28A0B38A207C9DCB00D03037 /* Release */ = { 650 | isa = XCBuildConfiguration; 651 | buildSettings = { 652 | BUNDLE_LOADER = "$(TEST_HOST)"; 653 | CODE_SIGN_STYLE = Automatic; 654 | DEVELOPMENT_TEAM = 6B7777MZAW; 655 | INFOPLIST_FILE = XNProgressHUDTests/Info.plist; 656 | LD_RUNPATH_SEARCH_PATHS = ( 657 | "$(inherited)", 658 | "@executable_path/Frameworks", 659 | "@loader_path/Frameworks", 660 | ); 661 | PRODUCT_BUNDLE_IDENTIFIER = com.luohan.XNProgressHUDTests; 662 | PRODUCT_NAME = "$(TARGET_NAME)"; 663 | TARGETED_DEVICE_FAMILY = "1,2"; 664 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/XNProgressHUD.app/XNProgressHUD"; 665 | }; 666 | name = Release; 667 | }; 668 | 28A0B38C207C9DCB00D03037 /* Debug */ = { 669 | isa = XCBuildConfiguration; 670 | buildSettings = { 671 | CODE_SIGN_STYLE = Automatic; 672 | DEVELOPMENT_TEAM = 6B7777MZAW; 673 | INFOPLIST_FILE = XNProgressHUDUITests/Info.plist; 674 | LD_RUNPATH_SEARCH_PATHS = ( 675 | "$(inherited)", 676 | "@executable_path/Frameworks", 677 | "@loader_path/Frameworks", 678 | ); 679 | PRODUCT_BUNDLE_IDENTIFIER = com.luohan.XNProgressHUDUITests; 680 | PRODUCT_NAME = "$(TARGET_NAME)"; 681 | TARGETED_DEVICE_FAMILY = "1,2"; 682 | TEST_TARGET_NAME = XNProgressHUD; 683 | }; 684 | name = Debug; 685 | }; 686 | 28A0B38D207C9DCB00D03037 /* Release */ = { 687 | isa = XCBuildConfiguration; 688 | buildSettings = { 689 | CODE_SIGN_STYLE = Automatic; 690 | DEVELOPMENT_TEAM = 6B7777MZAW; 691 | INFOPLIST_FILE = XNProgressHUDUITests/Info.plist; 692 | LD_RUNPATH_SEARCH_PATHS = ( 693 | "$(inherited)", 694 | "@executable_path/Frameworks", 695 | "@loader_path/Frameworks", 696 | ); 697 | PRODUCT_BUNDLE_IDENTIFIER = com.luohan.XNProgressHUDUITests; 698 | PRODUCT_NAME = "$(TARGET_NAME)"; 699 | TARGETED_DEVICE_FAMILY = "1,2"; 700 | TEST_TARGET_NAME = XNProgressHUD; 701 | }; 702 | name = Release; 703 | }; 704 | /* End XCBuildConfiguration section */ 705 | 706 | /* Begin XCConfigurationList section */ 707 | 28A0B354207C9DC900D03037 /* Build configuration list for PBXProject "XNProgressHUD" */ = { 708 | isa = XCConfigurationList; 709 | buildConfigurations = ( 710 | 28A0B383207C9DCB00D03037 /* Debug */, 711 | 28A0B384207C9DCB00D03037 /* Release */, 712 | ); 713 | defaultConfigurationIsVisible = 0; 714 | defaultConfigurationName = Release; 715 | }; 716 | 28A0B385207C9DCB00D03037 /* Build configuration list for PBXNativeTarget "XNProgressHUD" */ = { 717 | isa = XCConfigurationList; 718 | buildConfigurations = ( 719 | 28A0B386207C9DCB00D03037 /* Debug */, 720 | 28A0B387207C9DCB00D03037 /* Release */, 721 | ); 722 | defaultConfigurationIsVisible = 0; 723 | defaultConfigurationName = Release; 724 | }; 725 | 28A0B388207C9DCB00D03037 /* Build configuration list for PBXNativeTarget "XNProgressHUDTests" */ = { 726 | isa = XCConfigurationList; 727 | buildConfigurations = ( 728 | 28A0B389207C9DCB00D03037 /* Debug */, 729 | 28A0B38A207C9DCB00D03037 /* Release */, 730 | ); 731 | defaultConfigurationIsVisible = 0; 732 | defaultConfigurationName = Release; 733 | }; 734 | 28A0B38B207C9DCB00D03037 /* Build configuration list for PBXNativeTarget "XNProgressHUDUITests" */ = { 735 | isa = XCConfigurationList; 736 | buildConfigurations = ( 737 | 28A0B38C207C9DCB00D03037 /* Debug */, 738 | 28A0B38D207C9DCB00D03037 /* Release */, 739 | ); 740 | defaultConfigurationIsVisible = 0; 741 | defaultConfigurationName = Release; 742 | }; 743 | /* End XCConfigurationList section */ 744 | }; 745 | rootObject = 28A0B351207C9DC900D03037 /* Project object */; 746 | } 747 | -------------------------------------------------------------------------------- /XNProgressHUD.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /XNProgressHUD.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /XNProgressHUD.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildSystemType 6 | Original 7 | 8 | 9 | -------------------------------------------------------------------------------- /XNProgressHUD.xcodeproj/project.xcworkspace/xcuserdata/anker.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LuohanCC/XNProgressHUD/14883c9f870a3f4adc8eeebf6b3bfd05ec88c1f0/XNProgressHUD.xcodeproj/project.xcworkspace/xcuserdata/anker.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /XNProgressHUD.xcodeproj/project.xcworkspace/xcuserdata/luohan.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LuohanCC/XNProgressHUD/14883c9f870a3f4adc8eeebf6b3bfd05ec88c1f0/XNProgressHUD.xcodeproj/project.xcworkspace/xcuserdata/luohan.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /XNProgressHUD.xcodeproj/project.xcworkspace/xcuserdata/luohan.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildLocationStyle 6 | UseAppPreferences 7 | CustomBuildLocationType 8 | RelativeToDerivedData 9 | DerivedDataLocationStyle 10 | Default 11 | EnabledFullIndexStoreVisibility 12 | 13 | IssueFilterStyle 14 | ShowActiveSchemeOnly 15 | LiveSourceIssuesEnabled 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /XNProgressHUD.xcodeproj/project.xcworkspace/xcuserdata/ocean.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LuohanCC/XNProgressHUD/14883c9f870a3f4adc8eeebf6b3bfd05ec88c1f0/XNProgressHUD.xcodeproj/project.xcworkspace/xcuserdata/ocean.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /XNProgressHUD.xcodeproj/xcuserdata/anker.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /XNProgressHUD.xcodeproj/xcuserdata/anker.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | XNProgressHUD.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /XNProgressHUD.xcodeproj/xcuserdata/luohan.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /XNProgressHUD.xcodeproj/xcuserdata/luohan.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | XNProgressHUD.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | XNProgressHUD.xcscheme_^#shared#^_ 13 | 14 | orderHint 15 | 0 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /XNProgressHUD.xcodeproj/xcuserdata/ocean.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | XNProgressHUD.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /XNProgressHUD/1.0.3/XNProgressHUD.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod spec lint XNProgressHUD.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 = "XNProgressHUD" 12 | s.version = "1.0.3" 13 | s.summary = "一款支持自定义状态视图的的HUD" 14 | s.description = 15 | <<-DESC 16 | 一款支持自定义状态视图的的HUD,继承自XNProgressHUD并实现XNProgressHUDMethod中的方法。 17 | DESC 18 | 19 | s.homepage = "https://github.com/LuohanCC/XNProgressHUD" 20 | s.license = { :type => 'MIT', :file => 'LICENSE' } 21 | s.author = { "罗函" => "luohancc@163.com" } 22 | s.source = { :git => "https://github.com/LuohanCC/XNProgressHUD.git", :tag => "#{s.version}" } 23 | 24 | s.ios.deployment_target = "7.0" 25 | s.source_files = "SVProgressHUD/**/*.{h,m}" 26 | s.exclude_files = "Classes/Exclude" 27 | s.framework = "UIKit" 28 | s.requires_arc = true 29 | 30 | end 31 | -------------------------------------------------------------------------------- /XNProgressHUD/1.0.4/XNProgressHUD.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod spec lint XNProgressHUD.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 = "XNProgressHUD" 12 | s.version = "1.0.4" 13 | s.summary = "一款支持自定义状态视图的的HUD" 14 | s.description = 15 | <<-DESC 16 | 一款支持自定义状态视图的的HUD,继承自XNProgressHUD并实现XNProgressHUDMethod中的方法。 17 | DESC 18 | 19 | s.homepage = "https://github.com/LuohanCC/XNProgressHUD" 20 | s.license = { :type => 'MIT', :file => 'LICENSE' } 21 | s.author = { "罗函" => "luohancc@163.com" } 22 | s.source = { :git => "https://github.com/LuohanCC/XNProgressHUD.git", :tag => "#{s.version}" } 23 | 24 | s.ios.deployment_target = "7.0" 25 | s.source_files = "SVProgressHUD/**/*.{h,m}" 26 | s.exclude_files = "Classes/Exclude" 27 | s.framework = "UIKit" 28 | s.requires_arc = true 29 | 30 | end 31 | -------------------------------------------------------------------------------- /XNProgressHUD/1.0.5/XNProgressHUD.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod spec lint XNProgressHUD.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 = "XNProgressHUD" 12 | s.version = "1.0.5" 13 | s.summary = "一款支持自定义状态视图的的HUD" 14 | s.description = 15 | <<-DESC 16 | 一款支持自定义状态视图的的HUD,继承自XNProgressHUD并实现XNProgressHUDMethod中的方法。 17 | DESC 18 | 19 | s.homepage = "https://github.com/LuohanCC/XNProgressHUD" 20 | s.license = { :type => 'MIT', :file => 'LICENSE' } 21 | s.author = { "罗函" => "luohancc@163.com" } 22 | s.source = { :git => "https://github.com/LuohanCC/XNProgressHUD.git", :tag => "#{s.version}" } 23 | 24 | s.ios.deployment_target = "7.0" 25 | s.source_files = "SVProgressHUD/**/*.{h,m}" 26 | s.exclude_files = "Classes/Exclude" 27 | s.framework = "UIKit" 28 | s.requires_arc = true 29 | 30 | end 31 | -------------------------------------------------------------------------------- /XNProgressHUD/1.0.7/XNProgressHUD.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod spec lint XNProgressHUD.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 = "XNProgressHUD" 12 | s.version = "1.0.7" 13 | s.summary = "一款支持自定义状态视图的的HUD" 14 | s.description = 15 | <<-DESC 16 | 一款支持自定义状态视图的的HUD,继承自XNProgressHUD并实现XNProgressHUDMethod中的方法。 17 | DESC 18 | 19 | s.homepage = "https://github.com/LuohanCC/XNProgressHUD" 20 | s.license = { :type => 'MIT', :file => 'LICENSE' } 21 | s.author = { "罗函" => "luohancc@163.com" } 22 | s.source = { :git => "https://github.com/LuohanCC/XNProgressHUD.git", :tag => "#{s.version}" } 23 | 24 | s.ios.deployment_target = "7.0" 25 | s.source_files = "SVProgressHUD/**/*.{h,m}" 26 | s.exclude_files = "Classes/Exclude" 27 | s.framework = "UIKit" 28 | s.requires_arc = true 29 | 30 | end 31 | -------------------------------------------------------------------------------- /XNProgressHUD/1.0.8/XNProgressHUD.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod spec lint XNProgressHUD.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 = "XNProgressHUD" 12 | s.version = "1.0.8" 13 | s.summary = "一款支持自定义状态视图的的HUD" 14 | s.description = 15 | <<-DESC 16 | 一款支持自定义状态视图的的HUD,继承自XNProgressHUD并实现XNProgressHUDMethod中的方法。 17 | DESC 18 | 19 | s.homepage = "https://github.com/LuohanCC/XNProgressHUD" 20 | s.license = { :type => 'MIT', :file => 'LICENSE' } 21 | s.author = { "罗函" => "luohancc@163.com" } 22 | s.source = { :git => "https://github.com/LuohanCC/XNProgressHUD.git", :tag => "#{s.version}" } 23 | 24 | s.ios.deployment_target = "7.0" 25 | s.source_files = "Classes/**/*.{h,m}" 26 | s.exclude_files = "Classes/Exclude" 27 | s.framework = "UIKit" 28 | s.requires_arc = true 29 | 30 | end 31 | -------------------------------------------------------------------------------- /XNProgressHUD/1.0.9/XNProgressHUD.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod spec lint XNProgressHUD.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 = "XNProgressHUD" 12 | s.version = "1.0.9" 13 | s.summary = "一款支持自定义状态视图的的HUD" 14 | s.description = 15 | <<-DESC 16 | 一款支持自定义状态视图的的HUD,继承自XNProgressHUD并实现XNProgressHUDMethod中的方法。 17 | DESC 18 | 19 | s.homepage = "https://github.com/LuohanCC/XNProgressHUD" 20 | s.license = { :type => 'MIT', :file => 'LICENSE' } 21 | s.author = { "罗函" => "luohancc@163.com" } 22 | s.source = { :git => "https://github.com/LuohanCC/XNProgressHUD.git", :tag => "#{s.version}" } 23 | 24 | s.ios.deployment_target = "7.0" 25 | s.source_files = "Classes/**/*.{h,m}" 26 | s.exclude_files = "Classes/Exclude" 27 | s.framework = "UIKit" 28 | s.requires_arc = true 29 | 30 | end 31 | -------------------------------------------------------------------------------- /XNProgressHUD/1.1.0/XNProgressHUD.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod spec lint XNProgressHUD.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 = "XNProgressHUD" 12 | s.version = "1.1.0" 13 | s.summary = "一款支持自定义状态视图的的HUD" 14 | s.description = 15 | <<-DESC 16 | 一款支持自定义状态视图的的HUD,继承自XNProgressHUD并实现XNProgressHUDMethod中的方法。 17 | DESC 18 | 19 | s.homepage = "https://github.com/LuohanCC/XNProgressHUD" 20 | s.license = { :type => 'MIT', :file => 'LICENSE' } 21 | s.author = { "罗函" => "luohancc@163.com" } 22 | s.source = { :git => "https://github.com/LuohanCC/XNProgressHUD.git", :tag => "#{s.version}" } 23 | 24 | s.ios.deployment_target = "7.0" 25 | s.source_files = "Classes/**/*.{h,m}" 26 | s.exclude_files = "Classes/Exclude" 27 | s.framework = "UIKit" 28 | s.requires_arc = true 29 | 30 | end 31 | -------------------------------------------------------------------------------- /XNProgressHUD/1.1.1/XNProgressHUD.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod spec lint XNProgressHUD.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 = "XNProgressHUD" 12 | s.version = "1.1.1" 13 | s.summary = "一款支持自定义状态视图的的HUD" 14 | s.description = 15 | <<-DESC 16 | 一款支持自定义状态视图的的HUD,继承自XNProgressHUD并实现XNProgressHUDMethod中的方法。 17 | DESC 18 | 19 | s.homepage = "https://github.com/LuohanCC/XNProgressHUD" 20 | s.license = { :type => 'MIT', :file => 'LICENSE' } 21 | s.author = { "罗函" => "luohancc@163.com" } 22 | s.source = { :git => "https://github.com/LuohanCC/XNProgressHUD.git", :tag => "#{s.version}" } 23 | 24 | s.ios.deployment_target = "7.0" 25 | s.source_files = "Classes/**/*.{h,m}" 26 | s.exclude_files = "Classes/Exclude" 27 | s.framework = "UIKit" 28 | s.requires_arc = true 29 | 30 | end 31 | -------------------------------------------------------------------------------- /demo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // XNProgressHUD 4 | // 5 | // Created by 罗函 on 2018/4/10. 6 | // Copyright © 2018年 罗函. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /demo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // XNProgressHUD 4 | // 5 | // Created by 罗函 on 2018/4/10. 6 | // Copyright © 2018年 罗函. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "ViewController.h" 11 | 12 | @interface AppDelegate () 13 | 14 | @end 15 | 16 | @implementation AppDelegate 17 | 18 | 19 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 20 | // Override point for customization after application launch. 21 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 22 | self.window.backgroundColor = [UIColor darkGrayColor]; 23 | [self initRootViewController]; 24 | [self.window makeKeyAndVisible]; 25 | return YES; 26 | } 27 | 28 | - (void)initRootViewController { 29 | UIStoryboard *board = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; 30 | ViewController *vc = [board instantiateViewControllerWithIdentifier:@"ViewController_ID"]; 31 | UINavigationController *navi = [[UINavigationController alloc] initWithRootViewController:vc]; 32 | self.window.rootViewController = navi; 33 | } 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /demo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /demo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /demo/Assets.xcassets/image/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /demo/Assets.xcassets/image/ico_xnprogresshud_error.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "ico_xnprogresshud_error@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "ico_xnprogresshud_error@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /demo/Assets.xcassets/image/ico_xnprogresshud_error.imageset/ico_xnprogresshud_error@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LuohanCC/XNProgressHUD/14883c9f870a3f4adc8eeebf6b3bfd05ec88c1f0/demo/Assets.xcassets/image/ico_xnprogresshud_error.imageset/ico_xnprogresshud_error@2x.png -------------------------------------------------------------------------------- /demo/Assets.xcassets/image/ico_xnprogresshud_error.imageset/ico_xnprogresshud_error@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LuohanCC/XNProgressHUD/14883c9f870a3f4adc8eeebf6b3bfd05ec88c1f0/demo/Assets.xcassets/image/ico_xnprogresshud_error.imageset/ico_xnprogresshud_error@3x.png -------------------------------------------------------------------------------- /demo/Assets.xcassets/image/ico_xnprogresshud_info.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "ico_xnprogresshud_info@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "ico_xnprogresshud_info@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /demo/Assets.xcassets/image/ico_xnprogresshud_info.imageset/ico_xnprogresshud_info@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LuohanCC/XNProgressHUD/14883c9f870a3f4adc8eeebf6b3bfd05ec88c1f0/demo/Assets.xcassets/image/ico_xnprogresshud_info.imageset/ico_xnprogresshud_info@2x.png -------------------------------------------------------------------------------- /demo/Assets.xcassets/image/ico_xnprogresshud_info.imageset/ico_xnprogresshud_info@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LuohanCC/XNProgressHUD/14883c9f870a3f4adc8eeebf6b3bfd05ec88c1f0/demo/Assets.xcassets/image/ico_xnprogresshud_info.imageset/ico_xnprogresshud_info@3x.png -------------------------------------------------------------------------------- /demo/Assets.xcassets/image/ico_xnprogresshud_success.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "ico_xnprogresshud_success@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "ico_xnprogresshud_success@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /demo/Assets.xcassets/image/ico_xnprogresshud_success.imageset/ico_xnprogresshud_success@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LuohanCC/XNProgressHUD/14883c9f870a3f4adc8eeebf6b3bfd05ec88c1f0/demo/Assets.xcassets/image/ico_xnprogresshud_success.imageset/ico_xnprogresshud_success@2x.png -------------------------------------------------------------------------------- /demo/Assets.xcassets/image/ico_xnprogresshud_success.imageset/ico_xnprogresshud_success@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LuohanCC/XNProgressHUD/14883c9f870a3f4adc8eeebf6b3bfd05ec88c1f0/demo/Assets.xcassets/image/ico_xnprogresshud_success.imageset/ico_xnprogresshud_success@3x.png -------------------------------------------------------------------------------- /demo/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 | -------------------------------------------------------------------------------- /demo/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 | 57 | 63 | 69 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 97 | 120 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 173 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 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 | 264 | 265 | 266 | 267 | 268 | 269 | -------------------------------------------------------------------------------- /demo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /demo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // XNProgressHUD 4 | // 5 | // Created by 罗函 on 2018/4/10. 6 | // Copyright © 2018年 罗函. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | @property (nonatomic, assign, getter=isCustomized) BOOL customized; 13 | //- (instancetype)initWithCustomized:(BOOL)customized; 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /demo/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // XNProgressHUD 4 | // 5 | // Created by 罗函 on 2018/4/10. 6 | // Copyright © 2018年 罗函. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "XNAnimationView.h" 11 | #import "XNProgressHUD.h" 12 | #import "UIViewController+XNProgressHUD.h" 13 | #import "XNAnimationView.h" 14 | #import "CustomHUDLoadingLayer.h" 15 | 16 | @interface ViewController () 17 | @property (weak, nonatomic) IBOutlet UISlider *sliderProgress; 18 | @property (weak, nonatomic) IBOutlet UISwitch *switchDelayed; 19 | @property (weak, nonatomic) IBOutlet UISegmentedControl *segMaskType; 20 | @property (weak, nonatomic) IBOutlet UISegmentedControl *segDisplay; 21 | @property (nonatomic, assign) NSTimeInterval delayResponse; 22 | @property (nonatomic, assign) NSTimeInterval delayDismiss; 23 | @property (nonatomic, strong) UIWindow *userWindow; 24 | @property (nonatomic, strong) XNAnimationView *userAnimationView; 25 | @end 26 | 27 | @implementation ViewController 28 | 29 | - (XNAnimationView *)userAnimationView { 30 | if (!_userAnimationView) { 31 | _userAnimationView = [XNAnimationView new]; 32 | } 33 | return _userAnimationView; 34 | } 35 | 36 | - (void)viewDidLoad { 37 | [super viewDidLoad]; 38 | // Do any additional setup after loading the view, typically from a nib. 39 | self.navigationController.navigationBar.barTintColor = [UIColor colorWithRed:225/255.0 green:101/255.0 blue:49/255.0 alpha:1]; 40 | self.navigationController.navigationBar.tintColor = [UIColor whiteColor]; 41 | self.title = @"XNProgressHUD"; 42 | self.view.backgroundColor = [UIColor colorWithRed:228/255.0 green:230/255.0 blue:234/255.0 alpha:1]; 43 | 44 | UIBarButtonItem *barButton = [[UIBarButtonItem alloc] initWithTitle:@"Custom" style:(UIBarButtonItemStylePlain) target:self action:@selector(barButtonClick:)]; 45 | self.navigationItem.rightBarButtonItem = barButton; 46 | 47 | [self initSubviews]; 48 | } 49 | 50 | - (void)barButtonClick:(UIBarButtonItem *)barButton { 51 | UIStoryboard *board = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; 52 | ViewController *vc = [board instantiateViewControllerWithIdentifier:@"ViewController_ID"]; 53 | vc.customized = YES; 54 | [self.navigationController pushViewController:vc animated:YES]; 55 | } 56 | 57 | - (UIWindow *)userWindow { 58 | if (!_userWindow) { 59 | _userWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 60 | _userWindow.windowLevel = UIWindowLevelAlert + 1; 61 | _userWindow.hidden = NO; 62 | } 63 | return _userWindow; 64 | } 65 | 66 | - (void)initSubviews { 67 | // init trefreshView. 68 | _delayResponse = 1.0f; 69 | _delayDismiss = 3.f; 70 | 71 | // init HUD. 72 | [XNHUD setPosition:CGPointMake(self.view.bounds.size.width/2, self.view.bounds.size.height * 0.7)]; 73 | [XNHUD setMaskType:(XNProgressHUDMaskTypeCustom) hexColor:0x88000055]; 74 | // init hud of the vc. 75 | [self.hud setPosition:CGPointMake(self.view.bounds.size.width/2, self.view.bounds.size.height * 0.7)]; 76 | [self.hud setTintColor:[UIColor colorWithRed:38/255.0 green:50/255.0 blue:56/255.0 alpha:0.8]]; 77 | [self.hud setRefreshStyle:(XNAnimationViewStyleProgress)]; 78 | [self.hud setMaskType:(XNProgressHUDMaskTypeBlack) hexColor:0x00000044]; 79 | [self.hud setMaskType:(XNProgressHUDMaskTypeCustom) hexColor:0xff000044]; 80 | } 81 | 82 | // 正在下载 83 | - (IBAction)sliderProgressClick:(UISlider *)sender { 84 | [self.targetHud showProgressWithTitle:@"正在下载" progress:sender.value]; 85 | } 86 | 87 | // 自定义图片 88 | - (IBAction)switchCustomStatusView:(UISwitch *)sender { 89 | XNAnimationView *animationView = (XNAnimationView *)XNHUD.animationView; 90 | if (sender.on) { 91 | [animationView setInfoImage:[UIImage imageNamed:@"ico_xnprogresshud_info"]]; 92 | [animationView setErrorImage:[UIImage imageNamed:@"ico_xnprogresshud_error"]]; 93 | [animationView setSuccessImage:[UIImage imageNamed:@"ico_xnprogresshud_success"]]; 94 | } else { 95 | [animationView setInfoImage:nil]; 96 | [animationView setErrorImage:nil]; 97 | [animationView setSuccessImage:nil]; 98 | } 99 | } 100 | 101 | // 自定义加载动画 102 | - (IBAction)switchLoadingAnimationLayer:(UISwitch *)sender { 103 | [XNHUD dismiss]; 104 | XNAnimationView *animationView = (XNAnimationView *)XNHUD.animationView; 105 | CustomHUDLoadingLayer *customLayer = [CustomHUDLoadingLayer new]; 106 | animationView.loadingLayer = sender.on ? customLayer : nil; 107 | } 108 | 109 | // maskType 110 | - (IBAction)maskTypeClick:(UISegmentedControl *)sender { 111 | [self.targetHud setMaskType:sender.selectedSegmentIndex]; 112 | } 113 | 114 | // 重复上一次操作 115 | - (IBAction)repeatitionClick:(UIButton *)sender { 116 | [self showhudWithIndex:_segDisplay.selectedSegmentIndex]; 117 | } 118 | 119 | // 显示样式 120 | - (IBAction)showHUDWithSegmentIndex:(UISegmentedControl *)sender { 121 | //self.segMaskType.selectedSegmentIndex = 0; 122 | [self.targetHud setMaskType:_segMaskType.selectedSegmentIndex]; 123 | [self showhudWithIndex:sender.selectedSegmentIndex]; 124 | } 125 | 126 | - (XNProgressHUD *)targetHud { 127 | // return self.hud; 128 | return XNHUD; 129 | } 130 | 131 | - (void)showhudWithIndex:(NSInteger)index { 132 | switch (index) { 133 | case 0:{ 134 | if(_switchDelayed.on) { 135 | [self.targetHud setDisposableDelayResponse:_delayResponse delayDismiss:_delayDismiss]; 136 | } 137 | [self.targetHud show]; 138 | } 139 | break; 140 | case 1:{ 141 | if(_switchDelayed.on) { 142 | [self.targetHud setDisposableDelayResponse:_delayResponse delayDismiss:_delayDismiss]; 143 | } 144 | [self.targetHud showLoadingWithTitle:@"正在登录"]; 145 | } 146 | break; 147 | case 2:{ 148 | [self.targetHud showWithTitle:@"这是一个支持自定义的轻量级HUD"]; 149 | } 150 | break; 151 | case 3:{ 152 | [self.targetHud showInfoWithTitle:@"请输入账号"]; 153 | } 154 | break; 155 | case 4:{ 156 | [self.targetHud showErrorWithTitle:@"拒绝访问"]; 157 | } 158 | break; 159 | case 5:{ 160 | [self.targetHud showSuccessWithTitle:@"操作成功"]; 161 | } 162 | break; 163 | default: 164 | break; 165 | } 166 | } 167 | 168 | // 选择方向 169 | - (IBAction)horizontionChanged:(UISegmentedControl *)sender { 170 | [self.targetHud setOrientation:sender.selectedSegmentIndex]; 171 | } 172 | 173 | - (IBAction)targetViewDidChanged:(UISegmentedControl *)sender { 174 | [self.targetHud setMaskType:_segMaskType.selectedSegmentIndex]; 175 | switch (sender.selectedSegmentIndex) { 176 | case 0: { // show HUD at the keyWindow. 177 | UIView *v = [UIApplication sharedApplication].keyWindow; 178 | self.targetHud.targetView = nil; 179 | self.targetHud.position = CGPointMake(v.bounds.size.width/2, v.bounds.size.height * 0.7); 180 | [self.targetHud setMaskType:(XNProgressHUDMaskTypeCustom) hexColor:0x88000055]; 181 | [self.targetHud showSuccessWithTitle:@"默认显示在KeyWindow上显示"]; 182 | } 183 | break; 184 | case 1: { // show HUD at the custom Window. 185 | UIAlertController *alertVc = [UIAlertController alertControllerWithTitle:@"UIAlertController" message:@"通过设置\"XNHUD.windowLevel\"可以使HUD显示在UIAlertController之上" preferredStyle:(UIAlertControllerStyleAlert)]; 186 | [alertVc addAction:[UIAlertAction actionWithTitle:@"确定" style:(UIAlertActionStyleDefault) handler:nil]]; 187 | [self presentViewController:alertVc animated:YES completion:nil]; 188 | self.targetHud.targetView = self.userWindow; 189 | self.targetHud.position = CGPointMake(self.userWindow.bounds.size.width/2, self.userWindow.bounds.size.height/2); 190 | [self.targetHud setMaskType:(XNProgressHUDMaskTypeCustom) hexColor:0x00880011]; 191 | [self.targetHud showSuccessWithTitle:@"显示在AlertViewcontroller之上"]; 192 | } 193 | break; 194 | default: { //show HUD at the targetView. 195 | self.targetHud.padding = HUDPaddingMake(8, 8, 8, 8); 196 | self.targetHud.orientation = XNProgressHUDOrientationHorizontal; 197 | self.targetHud.targetView = self.view; 198 | self.targetHud.position = CGPointMake(self.view.bounds.size.width/2, self.view.bounds.size.height * 0.7); 199 | [self.targetHud setMaskType:(XNProgressHUDMaskTypeCustom) hexColor:0x00008855]; 200 | [self.targetHud showSuccessWithTitle:@"指定显示在某个View上"]; 201 | } 202 | break; 203 | } 204 | } 205 | 206 | // dismiss 207 | - (IBAction)dismissClick:(id)sender { 208 | [self.targetHud dismiss]; 209 | } 210 | @end 211 | -------------------------------------------------------------------------------- /demo/custom/CustomHUDLoadingLayer.h: -------------------------------------------------------------------------------- 1 | // 2 | // CustomHUDLoadingLayer.h 3 | // XNProgressHUD 4 | // 5 | // Created by jarvis on 2019/7/20. 6 | // Copyright © 2019 罗函. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "XNHUDLayerProtocol.h" 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface CustomHUDLoadingLayer : CALayer 15 | 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /demo/custom/CustomHUDLoadingLayer.m: -------------------------------------------------------------------------------- 1 | // 2 | // CustomHUDLoadingLayer.m 3 | // XNProgressHUD 4 | // 5 | // Created by jarvis on 2019/7/20. 6 | // Copyright © 2019 罗函. All rights reserved. 7 | // 8 | 9 | #import "CustomHUDLoadingLayer.h" 10 | 11 | static NSString *kMMRingStrokeAnimationKey = @"materialdesignspinner.stroke"; 12 | 13 | @interface CustomHUDLoadingLayer() 14 | @property (nonatomic, strong) CAShapeLayer *loading; 15 | @property (nonatomic, strong) CAShapeLayer *loadingBG; 16 | @end 17 | 18 | @implementation CustomHUDLoadingLayer 19 | @synthesize timingFunction; 20 | @synthesize targetLayer; 21 | @synthesize animationDuration; 22 | @synthesize lineCap; 23 | @synthesize xn_lineWidth; 24 | @synthesize xn_strokeColor; 25 | 26 | - (instancetype)init { 27 | if (!(self = [super init])) return nil; 28 | _loadingBG = [CAShapeLayer layer]; 29 | [self addSublayer:_loadingBG]; 30 | _loading = [CAShapeLayer layer]; 31 | [self addSublayer:_loading]; 32 | return self; 33 | } 34 | 35 | - (void)setCustomPath:(CAShapeLayer *)layer { 36 | float w = self.bounds.size.width * 1.2; 37 | float h = w * 0.65; 38 | 39 | UIBezierPath *bezier2Path = [UIBezierPath bezierPath]; 40 | [bezier2Path moveToPoint: CGPointMake(w, 0)]; 41 | [bezier2Path addLineToPoint: CGPointMake(1, h)]; 42 | [bezier2Path addLineToPoint: CGPointMake(1, h - h)]; 43 | [bezier2Path addLineToPoint: CGPointMake(w, h)]; 44 | [bezier2Path addLineToPoint: CGPointMake(w, 0)]; 45 | [bezier2Path closePath]; 46 | [[UIColor clearColor] setStroke]; 47 | [[UIColor clearColor] setFill]; 48 | [bezier2Path stroke]; 49 | 50 | layer.path = bezier2Path.CGPath; 51 | layer.bounds = bezier2Path.bounds; 52 | CGPathRef strokingPath = CGPathCreateCopyByStrokingPath(layer.path, nil, 4, kCGLineCapSquare,kCGLineJoinRound, 4); 53 | layer.bounds = CGPathGetPathBoundingBox(strokingPath); 54 | layer.fillColor = [UIColor clearColor].CGColor; 55 | } 56 | 57 | - (void)drawInContext:(CGContextRef)ctx { 58 | [super drawInContext:ctx]; 59 | UIGraphicsPushContext(ctx); 60 | 61 | [self setCustomPath:_loading]; 62 | [self setCustomPath:_loadingBG]; 63 | 64 | _loading.lineCap = kCALineCapRound; 65 | _loading.lineJoin = kCALineJoinBevel; 66 | _loading.strokeColor = xn_strokeColor; 67 | _loading.lineWidth = xn_lineWidth; 68 | _loading.position = CGPointMake(CGRectGetWidth(self.bounds)/2, CGRectGetHeight(self.bounds)/2); 69 | _loadingBG.strokeColor = [[UIColor colorWithCGColor:xn_strokeColor] colorWithAlphaComponent:0.2].CGColor; 70 | _loadingBG.lineWidth = xn_lineWidth; 71 | _loadingBG.position = CGPointMake(CGRectGetWidth(self.bounds)/2, CGRectGetHeight(self.bounds)/2); 72 | 73 | UIGraphicsPopContext(); 74 | } 75 | 76 | #pragma mark - XNHUDLayerProtocol 77 | - (void)prepare { 78 | if (self.animationDuration == 0) { 79 | self.animationDuration = 2.0; 80 | } 81 | if (!self.timingFunction) { 82 | self.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 83 | } 84 | 85 | // drawing 86 | [self setNeedsDisplay]; 87 | } 88 | 89 | - (void)play { 90 | [_loading removeAnimationForKey:kMMRingStrokeAnimationKey]; 91 | 92 | if (!self.superlayer) { 93 | [self.targetLayer addSublayer:self]; 94 | } 95 | float duration = self.animationDuration; 96 | 97 | CABasicAnimation *headAnimation = [CABasicAnimation animation]; 98 | headAnimation.keyPath = @"strokeStart"; 99 | headAnimation.beginTime = duration / 4; 100 | headAnimation.duration = duration / 2; 101 | headAnimation.fromValue = @(0.f); 102 | headAnimation.toValue = @(1.0f); 103 | headAnimation.timingFunction = self.timingFunction; 104 | 105 | CABasicAnimation *endHeadAnimation = [CABasicAnimation animation]; 106 | endHeadAnimation.keyPath = @"strokeStart"; 107 | endHeadAnimation.beginTime = headAnimation.beginTime + headAnimation.duration; 108 | endHeadAnimation.duration = duration / 4; 109 | endHeadAnimation.fromValue = headAnimation.toValue; 110 | endHeadAnimation.toValue = @(1.0f); 111 | endHeadAnimation.timingFunction = self.timingFunction; 112 | 113 | CABasicAnimation *tailAnimation = [CABasicAnimation animation]; 114 | tailAnimation.keyPath = @"strokeEnd"; 115 | tailAnimation.duration = duration / 2; 116 | tailAnimation.fromValue = @(0.f); 117 | tailAnimation.toValue = @(1.0f); 118 | tailAnimation.timingFunction = self.timingFunction; 119 | 120 | CABasicAnimation *endTailAnimation = [CABasicAnimation animation]; 121 | endTailAnimation.keyPath = @"strokeEnd"; 122 | endTailAnimation.beginTime = tailAnimation.beginTime + tailAnimation.duration; 123 | endTailAnimation.duration = duration - tailAnimation.duration; 124 | endTailAnimation.fromValue = tailAnimation.toValue; 125 | endTailAnimation.toValue = @(1.0f); 126 | endTailAnimation.timingFunction = self.timingFunction; 127 | 128 | CAAnimationGroup *animations = [CAAnimationGroup animation]; 129 | [animations setDuration:duration-0.3]; 130 | [animations setAnimations:@[headAnimation, endHeadAnimation, tailAnimation, endTailAnimation]]; 131 | animations.repeatCount = INFINITY; 132 | animations.removedOnCompletion = NO; 133 | animations.fillMode = kCAFillModeForwards; 134 | [_loading addAnimation:animations forKey:kMMRingStrokeAnimationKey]; 135 | } 136 | 137 | - (void)stop { 138 | if(_loading.animationKeys) { 139 | [_loading removeAnimationForKey:kMMRingStrokeAnimationKey]; 140 | } 141 | if(self.superlayer) { 142 | [self removeFromSuperlayer]; 143 | } 144 | } 145 | 146 | 147 | 148 | 149 | @end 150 | -------------------------------------------------------------------------------- /demo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // XNProgressHUD 4 | // 5 | // Created by 罗函 on 2018/4/10. 6 | // Copyright © 2018年 罗函. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | --------------------------------------------------------------------------------