UIView+SPSBLoadingTipsView.m 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. //
  2. // UIView+SPSBLoadingTipsView.m
  3. // 我的社保
  4. //
  5. // Created by shanp on 2021/4/21.
  6. //
  7. #import "UIView+SPSBLoadingTipsView.h"
  8. #import <objc/runtime.h>
  9. #import <JXHSystemShortcut.h>
  10. #import "SPSBUIGeneralHeader.h"
  11. #import <CALayer+JXHShadow.h>
  12. static UIView *spsb_loadingToast = nil;
  13. static bool spsb_isLoading = false;
  14. @interface UIView ()
  15. @property UIView *spsb_toast;
  16. @end
  17. @implementation UIView (SPSBLoadingTipsView)
  18. #pragma mark - Loading
  19. - (void)showLoadingToastWithTitle:(NSString *)title userClick:(bool)userClick {
  20. jxh_windowUserInteractionEnabled(userClick);
  21. [self _spsb_createLoadingToastWithTitle:title];
  22. }
  23. #pragma mark - Normal
  24. - (void)showToastWithTitle:(NSString *)title {
  25. [self showToastWithTitle:title duration:SPSBDismissToastDefaultTime];
  26. }
  27. - (void)showToastWithTitle:(NSString *)title duration:(NSTimeInterval)duration {
  28. [self showToastWithTitle:title duration:duration completion:nil];
  29. }
  30. - (void)showToastWithTitle:(NSString *)title duration:(NSTimeInterval)duration completion:(void (^ _Nullable)(void))completion {
  31. [self dismissToast];
  32. UIView *toast = self.spsb_toast = UIView.new;
  33. toast.alpha = 0;
  34. [toast setLayerCornerRadius:4 clipToBounds:false];
  35. toast.backgroundColor = spsb_000000_color(0.8);
  36. toast.alpha = 0.9;
  37. UIWindow *window = spsb_keyWindow();
  38. if (!window) {
  39. return;
  40. }
  41. [window addSubview:toast];
  42. [toast makeConstraints:^(JXHConstraintMaker *make) {
  43. make.width.lessThanOrEqualTo(jxh_screenWidth() - 80);
  44. make.center.equalTo(window);
  45. }];
  46. UILabel *titleLabel = [UILabel convenienceWithFont:spsb_font(16) textColor:spsb_FFFFFF_color(1.f) limitWidth:jxh_screenWidth() - 80 - 48];
  47. [titleLabel setAttributedStringWithText:title textAlignment:NSTextAlignmentCenter lineSpacing:5 lineHeight:0 paragraphSpacing:0 lineBreakMode:0];
  48. [toast addSubview:titleLabel];
  49. [titleLabel makeConstraints:^(JXHConstraintMaker *make) {
  50. make.edges.equalTo((UIEdgeInsets){12, 24, 12, 24});
  51. }];
  52. [toast setNeedsLayout];
  53. [toast layoutIfNeeded];
  54. CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
  55. animation.fromValue = [NSNumber numberWithFloat:1.8];
  56. animation.toValue = [NSNumber numberWithFloat:1.0];
  57. animation.duration = 0.2;
  58. animation.removedOnCompletion = true;
  59. [toast.layer addAnimation:animation forKey:nil];
  60. [UIView animateWithDuration:0.2 animations:^{
  61. toast.alpha = 1.f;
  62. }];
  63. jxh_delayAction(duration, dispatch_get_main_queue(), ^{
  64. [self _spsb_dismissToast:toast completion:completion];
  65. });
  66. }
  67. - (void)_spsb_dismissToast:(UIView *)toast completion:(void(^_Nullable)(void))completion {
  68. if (!toast) return;
  69. CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
  70. animation.fromValue = [NSNumber numberWithFloat:1.0];
  71. animation.toValue = [NSNumber numberWithFloat:0];
  72. animation.duration = 0.2;
  73. animation.removedOnCompletion = true;
  74. [toast.layer addAnimation:animation forKey:nil];
  75. [UIView animateWithDuration:0.2 animations:^{
  76. toast.alpha = 0.f;
  77. } completion:^(BOOL finished) {
  78. [toast removeFromSuperview];
  79. if (completion) {
  80. completion();
  81. }
  82. }];
  83. }
  84. #define spsb_loadingImageViewTag 3000
  85. - (void)_spsb_createLoadingToastWithTitle:(NSString *)title {
  86. [self _spsb_dismissToast];
  87. UIView *toast = spsb_loadingToast = UIView.new;
  88. toast.backgroundColor = spsb_000000_color(0.8);
  89. [toast setLayerCornerRadius:10 clipToBounds:false];
  90. UIWindow *window = spsb_keyWindow();
  91. if (!window) return;
  92. [window addSubview:toast];
  93. [toast makeConstraints:^(JXHConstraintMaker *make) {
  94. make.width.greaterThanOrEqualTo(110);
  95. make.width.lessThanOrEqualTo(215);
  96. make.center.equalTo(window);
  97. }];
  98. UIView *backView = [[UIView alloc] init];
  99. [backView setLayerCornerRadius:20 clipToBounds:false];
  100. [backView setLayerBorderWidth:3 borderColor:spsb_FFFFFF_color(1.f)];
  101. [toast addSubview:backView];
  102. [backView makeConstraints:^(JXHConstraintMaker *make) {
  103. make.top.equalTo(15);
  104. make.size.equalTo(CGSizeMake(40, 40));
  105. make.centerX.equalTo(toast);
  106. }];
  107. UIView *frontView = [[UIView alloc] init];
  108. [frontView setLayerCornerRadius:20 clipToBounds:false];
  109. [frontView setLayerBorderWidth:3 borderColor:spsb_3296FB_color()];
  110. [toast addSubview:frontView];
  111. [frontView makeConstraints:^(JXHConstraintMaker *make) {
  112. make.top.equalTo(15);
  113. make.size.equalTo(CGSizeMake(40, 40));
  114. make.centerX.equalTo(toast);
  115. }];
  116. UILabel *titleLabel = [UILabel convenienceWithFont:spsb_font(16) text:title textColor:spsb_FFFFFF_color(1.f) textAlignment:NSTextAlignmentCenter];
  117. [toast addSubview:titleLabel];
  118. [titleLabel makeConstraints:^(JXHConstraintMaker *make) {
  119. make.top.equalTo(backView.bottom).offset(10);
  120. make.leading.equalTo(10);
  121. make.trailing.equalTo(-10);
  122. make.bottom.equalTo(-15);
  123. }];
  124. spsb_isLoading = true;
  125. [self loading:frontView p:0.15];
  126. }
  127. - (void)loading:(UIView *)view p:(CGFloat)p {
  128. if (!spsb_isLoading) {
  129. return;
  130. }
  131. if (p >= 1) {
  132. p = 0;
  133. }
  134. CGFloat begin = M_PI * 2 * p - M_PI * 2 * 0.15;
  135. CGFloat startA = -M_PI_2 + begin;
  136. CGFloat endA = -M_PI_2 + M_PI * 2 * p;
  137. CGRect rect = CGRectMake(0, 0, 40, 40);
  138. CGPoint center = CGPointMake(rect.size.width / 2, rect.size.height / 2);
  139. CGFloat radius = rect.size.width / 2;
  140. UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:startA endAngle:endA clockwise:true];
  141. [path addLineToPoint:center];
  142. CAShapeLayer *maskLayer = [CAShapeLayer layer];
  143. maskLayer.path = path.CGPath;
  144. view.layer.mask = maskLayer;
  145. jxh_delayAction(0.02, dispatch_get_main_queue(), ^{
  146. [self loading:view p:p + 0.025];
  147. });
  148. }
  149. - (void)_spsb_dismissLoadingToast {
  150. if (spsb_loadingToast) {
  151. spsb_isLoading = false;
  152. spsb_loadingToast.hidden = true;
  153. [spsb_loadingToast removeFromSuperview];
  154. spsb_loadingToast = nil;
  155. }
  156. }
  157. #undef spsb_loadingImageViewTag
  158. - (void)_spsb_dismissToast {
  159. [self _spsb_dismissLoadingToast];
  160. if (self.spsb_toast) {
  161. self.spsb_toast.hidden = true;
  162. [self.spsb_toast removeFromSuperview];
  163. self.spsb_toast = nil;
  164. }
  165. }
  166. - (void)dismissToast {
  167. [self _spsb_dismissToast];
  168. jxh_windowUserInteractionEnabled(true);
  169. }
  170. - (UIView *)spsb_toast {
  171. UIView *object = objc_getAssociatedObject(self, @selector(setSpsb_toast:));
  172. return object;
  173. }
  174. - (void)setSpsb_toast:(UIView *)spsb_toast {
  175. objc_setAssociatedObject(self, _cmd, spsb_toast, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  176. }
  177. @end