UIView+GlowView.m 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. //
  2. // UIView+GlowView.m
  3. // GlowView
  4. //
  5. // Created by YouXianMing on 15/7/4.
  6. // Copyright (c) 2015年 YouXianMing. All rights reserved.
  7. //
  8. #import "UIView+GlowView.h"
  9. #import <objc/runtime.h>
  10. @interface UIView ()
  11. @property (nonatomic, strong) CALayer *glowLayer;
  12. @property (nonatomic, strong) dispatch_source_t dispatchSource;
  13. @end
  14. @implementation UIView (GlowView)
  15. - (void)createGlowLayer {
  16. UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, [UIScreen mainScreen].scale);
  17. [self.layer renderInContext:UIGraphicsGetCurrentContext()];
  18. UIBezierPath* path = [UIBezierPath bezierPathWithRect:self.bounds];
  19. [[self accessGlowColor] setFill];
  20. [path fillWithBlendMode:kCGBlendModeSourceAtop alpha:1.0];
  21. self.glowLayer = [CALayer layer];
  22. self.glowLayer.frame = self.bounds;
  23. self.glowLayer.contents = (__bridge id)UIGraphicsGetImageFromCurrentImageContext().CGImage;
  24. self.glowLayer.opacity = 0.f;
  25. self.glowLayer.shadowOffset = CGSizeMake(0, 0);
  26. self.glowLayer.shadowOpacity = 1.f;
  27. UIGraphicsEndImageContext();
  28. }
  29. - (void)insertGlowLayer {
  30. if (self.glowLayer) {
  31. [self.layer addSublayer:self.glowLayer];
  32. }
  33. }
  34. - (void)removeGlowLayer {
  35. if (self.glowLayer) {
  36. [self.glowLayer removeFromSuperlayer];
  37. }
  38. }
  39. - (void)glowToshowAnimated:(BOOL)animated {
  40. self.glowLayer.shadowColor = [self accessGlowColor].CGColor;
  41. self.glowLayer.shadowRadius = [self accessGlowRadius].floatValue;
  42. if (animated) {
  43. CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
  44. animation.fromValue = @(0.f);
  45. animation.toValue = [self accessGlowOpacity];
  46. self.glowLayer.opacity = [self accessGlowOpacity].floatValue;
  47. animation.duration = [self accessAnimationDuration].floatValue;
  48. [self.glowLayer addAnimation:animation forKey:@"glowLayerOpacity"];
  49. } else {
  50. [self.glowLayer removeAnimationForKey:@"glowLayerOpacity"];
  51. self.glowLayer.opacity = [self accessGlowOpacity].floatValue;
  52. }
  53. }
  54. - (void)glowToHideAnimated:(BOOL)animated {
  55. self.glowLayer.shadowColor = [self accessGlowColor].CGColor;
  56. self.glowLayer.shadowRadius = [self accessGlowRadius].floatValue;
  57. if (animated) {
  58. CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
  59. animation.fromValue = [self accessGlowOpacity];
  60. animation.toValue = @(0.f);
  61. self.glowLayer.opacity = 0.f;
  62. animation.duration = [self accessAnimationDuration].floatValue;
  63. [self.glowLayer addAnimation:animation forKey:@"glowLayerOpacity"];
  64. } else {
  65. [self.glowLayer removeAnimationForKey:@"glowLayerOpacity"];
  66. self.glowLayer.opacity = 0.f;
  67. }
  68. }
  69. - (void)startGlowLoop {
  70. if (self.dispatchSource == nil) {
  71. CGFloat seconds = [self accessAnimationDuration].floatValue * 2 + [self accessGlowDuration].floatValue + [self accessHideDuration].floatValue;
  72. CGFloat delaySeconds = [self accessAnimationDuration].floatValue + [self accessGlowDuration].floatValue;
  73. self.dispatchSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
  74. __weak UIView *weakSelf = self;
  75. dispatch_source_set_timer(self.dispatchSource, dispatch_time(DISPATCH_TIME_NOW, 0), NSEC_PER_SEC * seconds, 0);
  76. dispatch_source_set_event_handler(self.dispatchSource, ^{
  77. [weakSelf glowToshowAnimated:YES];
  78. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * delaySeconds), dispatch_get_main_queue(), ^{
  79. [weakSelf glowToHideAnimated:YES];
  80. });
  81. });
  82. dispatch_resume(self.dispatchSource);
  83. }
  84. }
  85. #pragma mark - 处理数据越界问题
  86. - (NSNumber *)accessGlowOpacity {
  87. if (self.glowOpacity) {
  88. if (self.glowOpacity.floatValue <= 0 || self.glowOpacity.floatValue > 1) {
  89. return @(0.8);
  90. } else {
  91. return self.glowOpacity;
  92. }
  93. } else {
  94. return @(0.8);
  95. }
  96. }
  97. - (NSNumber *)accessGlowDuration {
  98. if (self.glowDuration) {
  99. if (self.glowDuration.floatValue <= 0) {
  100. return @(0.5f);
  101. } else {
  102. return self.glowDuration;
  103. }
  104. } else {
  105. return @(0.5f);
  106. }
  107. }
  108. - (NSNumber *)accessHideDuration {
  109. if (self.hideDuration) {
  110. if (self.hideDuration.floatValue < 0) {
  111. return @(0.5);
  112. } else {
  113. return self.hideDuration;
  114. }
  115. } else {
  116. return @(0.5f);
  117. }
  118. }
  119. - (NSNumber *)accessAnimationDuration {
  120. if (self.glowAnimationDuration) {
  121. if (self.glowAnimationDuration.floatValue <= 0) {
  122. return @(1.f);
  123. } else {
  124. return self.glowAnimationDuration;
  125. }
  126. } else {
  127. return @(1.f);
  128. }
  129. }
  130. - (UIColor *)accessGlowColor {
  131. if (self.glowColor) {
  132. return self.glowColor;
  133. } else {
  134. return [UIColor redColor];
  135. }
  136. }
  137. - (NSNumber *)accessGlowRadius {
  138. if (self.glowRadius) {
  139. if (self.glowRadius.floatValue <= 0) {
  140. return @(2.f);
  141. } else {
  142. return self.glowRadius;
  143. }
  144. } else {
  145. return @(2.f);
  146. }
  147. }
  148. #pragma mark - runtime属性
  149. - (void)setDispatchSource:(dispatch_source_t)dispatchSource {
  150. objc_setAssociatedObject(self, @selector(dispatchSource), dispatchSource, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  151. }
  152. - (dispatch_source_t)dispatchSource {
  153. return objc_getAssociatedObject(self, _cmd);
  154. }
  155. - (void)setGlowColor:(UIColor *)glowColor {
  156. objc_setAssociatedObject(self, @selector(glowColor), glowColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  157. }
  158. - (UIColor *)glowColor {
  159. return objc_getAssociatedObject(self, _cmd);
  160. }
  161. - (void)setGlowOpacity:(NSNumber *)glowOpacity {
  162. objc_setAssociatedObject(self, @selector(glowOpacity), glowOpacity, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  163. }
  164. - (NSNumber *)glowOpacity {
  165. return objc_getAssociatedObject(self, _cmd);
  166. }
  167. - (void)setGlowRadius:(NSNumber *)glowRadius {
  168. objc_setAssociatedObject(self, @selector(glowRadius), glowRadius, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  169. }
  170. - (NSNumber *)glowRadius {
  171. return objc_getAssociatedObject(self, _cmd);
  172. }
  173. - (void)setGlowAnimationDuration:(NSNumber *)glowAnimationDuration {
  174. objc_setAssociatedObject(self, @selector(glowAnimationDuration), glowAnimationDuration, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  175. }
  176. - (NSNumber *)glowAnimationDuration {
  177. return objc_getAssociatedObject(self, _cmd);
  178. }
  179. - (void)setGlowDuration:(NSNumber *)glowDuration {
  180. objc_setAssociatedObject(self, @selector(glowDuration), glowDuration, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  181. }
  182. - (NSNumber *)glowDuration {
  183. return objc_getAssociatedObject(self, _cmd);
  184. }
  185. - (void)setHideDuration:(NSNumber *)hideDuration {
  186. objc_setAssociatedObject(self, @selector(hideDuration), hideDuration, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  187. }
  188. - (NSNumber *)hideDuration {
  189. return objc_getAssociatedObject(self, _cmd);
  190. }
  191. NSString * const _recognizerGlowLayer = @"_recognizerGlowLayer";
  192. - (void)setGlowLayer:(CALayer *)glowLayer {
  193. objc_setAssociatedObject(self, @selector(glowLayer), glowLayer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  194. }
  195. - (CALayer *)glowLayer {
  196. return objc_getAssociatedObject(self, _cmd);
  197. }
  198. @end