MMPopupCategory.m 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  1. //
  2. // UIColor+MMPopup.m
  3. // MMPopupView
  4. //
  5. // Created by Ralph Li on 9/6/15.
  6. // Copyright © 2015 LJC. All rights reserved.
  7. //
  8. #import "MMPopupCategory.h"
  9. #import "MMPopupDefine.h"
  10. #import "MMPopupWindow.h"
  11. #import <Masonry/Masonry.h>
  12. #import <objc/runtime.h>
  13. @implementation UIColor (MMPopup)
  14. + (UIColor *) mm_colorWithHex:(NSUInteger)hex {
  15. float r = (hex & 0xff000000) >> 24;
  16. float g = (hex & 0x00ff0000) >> 16;
  17. float b = (hex & 0x0000ff00) >> 8;
  18. float a = (hex & 0x000000ff);
  19. return [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:a/255.0];
  20. }
  21. @end
  22. @implementation UIImage (MMPopup)
  23. + (UIImage *) mm_imageWithColor:(UIColor *)color {
  24. return [UIImage mm_imageWithColor:color Size:CGSizeMake(4.0f, 4.0f)];
  25. }
  26. + (UIImage *) mm_imageWithColor:(UIColor *)color Size:(CGSize)size
  27. {
  28. CGRect rect = CGRectMake(0.0f, 0.0f, size.width, size.height);
  29. UIGraphicsBeginImageContext(size);
  30. CGContextRef context = UIGraphicsGetCurrentContext();
  31. CGContextSetFillColorWithColor(context, [color CGColor]);
  32. CGContextFillRect(context, rect);
  33. UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
  34. UIGraphicsEndImageContext();
  35. return [image mm_stretched];
  36. }
  37. - (UIImage *) mm_stretched
  38. {
  39. CGSize size = self.size;
  40. UIEdgeInsets insets = UIEdgeInsetsMake(truncf(size.height-1)/2, truncf(size.width-1)/2, truncf(size.height-1)/2, truncf(size.width-1)/2);
  41. return [self resizableImageWithCapInsets:insets];
  42. }
  43. @end
  44. @implementation UIButton (MMPopup)
  45. + (id) mm_buttonWithTarget:(id)target action:(SEL)sel
  46. {
  47. id btn = [self buttonWithType:UIButtonTypeCustom];
  48. [btn addTarget:target action:sel forControlEvents:UIControlEventTouchUpInside];
  49. [btn setExclusiveTouch:YES];
  50. return btn;
  51. }
  52. @end
  53. @implementation NSString (MMPopup)
  54. - (NSString *)mm_truncateByCharLength:(NSUInteger)charLength
  55. {
  56. __block NSUInteger length = 0;
  57. [self enumerateSubstringsInRange:NSMakeRange(0, [self length])
  58. options:NSStringEnumerationByComposedCharacterSequences
  59. usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
  60. if ( length+substringRange.length > charLength )
  61. {
  62. *stop = YES;
  63. return;
  64. }
  65. length+=substringRange.length;
  66. }];
  67. return [self substringToIndex:length];
  68. }
  69. @end
  70. static const void *mm_dimReferenceCountKey = &mm_dimReferenceCountKey;
  71. static const void *mm_dimBackgroundViewKey = &mm_dimBackgroundViewKey;
  72. static const void *mm_dimAnimationDurationKey = &mm_dimAnimationDurationKey;
  73. static const void *mm_dimBackgroundAnimatingKey = &mm_dimBackgroundAnimatingKey;
  74. static const void *mm_dimBackgroundBlurViewKey = &mm_dimBackgroundBlurViewKey;
  75. static const void *mm_dimBackgroundBlurEnabledKey = &mm_dimBackgroundBlurEnabledKey;
  76. static const void *mm_dimBackgroundBlurEffectStyleKey = &mm_dimBackgroundBlurEffectStyleKey;
  77. @interface UIView (MMPopupInner)
  78. @property (nonatomic, assign, readwrite) NSInteger mm_dimReferenceCount;
  79. @end
  80. @implementation UIView (MMPopupInner)
  81. @dynamic mm_dimReferenceCount;
  82. - (NSInteger)mm_dimReferenceCount {
  83. return [objc_getAssociatedObject(self, mm_dimReferenceCountKey) integerValue];
  84. }
  85. - (void)setMm_dimReferenceCount:(NSInteger)mm_dimReferenceCount
  86. {
  87. objc_setAssociatedObject(self, mm_dimReferenceCountKey, @(mm_dimReferenceCount), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  88. }
  89. @end
  90. @implementation UIView (MMPopup)
  91. @dynamic mm_dimBackgroundView;
  92. @dynamic mm_dimAnimationDuration;
  93. @dynamic mm_dimBackgroundAnimating;
  94. @dynamic mm_dimBackgroundBlurView;
  95. //mm_dimBackgroundView
  96. - (UIView *)mm_dimBackgroundView
  97. {
  98. UIView *dimView = objc_getAssociatedObject(self, mm_dimBackgroundViewKey);
  99. if ( !dimView )
  100. {
  101. dimView = [UIView new];
  102. [self addSubview:dimView];
  103. [dimView mas_makeConstraints:^(MASConstraintMaker *make) {
  104. make.edges.equalTo(self);
  105. }];
  106. dimView.alpha = 0.0f;
  107. // dimView.backgroundColor = MMHexColor(0x0000007F);
  108. dimView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.2];
  109. dimView.layer.zPosition = FLT_MAX;
  110. self.mm_dimAnimationDuration = 0.2f;
  111. objc_setAssociatedObject(self, mm_dimBackgroundViewKey, dimView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  112. }
  113. return dimView;
  114. }
  115. //mm_dimBackgroundBlurEnabled
  116. - (BOOL)mm_dimBackgroundBlurEnabled
  117. {
  118. return [objc_getAssociatedObject(self, mm_dimBackgroundBlurEnabledKey) boolValue];
  119. }
  120. - (void)setMm_dimBackgroundBlurEnabled:(BOOL)mm_dimBackgroundBlurEnabled
  121. {
  122. objc_setAssociatedObject(self, mm_dimBackgroundBlurEnabledKey, @(mm_dimBackgroundBlurEnabled), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  123. if ( mm_dimBackgroundBlurEnabled )
  124. {
  125. self.mm_dimBackgroundView.backgroundColor = MMHexColor(0x00000000);
  126. self.mm_dimBackgroundBlurEffectStyle = self.mm_dimBackgroundBlurEffectStyle;
  127. self.mm_dimBackgroundBlurView.hidden = NO;
  128. }
  129. else
  130. {
  131. self.mm_dimBackgroundView.backgroundColor = MMHexColor(0x0000007F);
  132. self.mm_dimBackgroundBlurView.hidden = YES;
  133. }
  134. }
  135. //mm_dimBackgroundBlurEffectStyle
  136. - (UIBlurEffectStyle)mm_dimBackgroundBlurEffectStyle
  137. {
  138. return [objc_getAssociatedObject(self, mm_dimBackgroundBlurEffectStyleKey) integerValue];
  139. }
  140. - (void)setMm_dimBackgroundBlurEffectStyle:(UIBlurEffectStyle)mm_dimBackgroundBlurEffectStyle
  141. {
  142. objc_setAssociatedObject(self, mm_dimBackgroundBlurEffectStyleKey, @(mm_dimBackgroundBlurEffectStyle), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  143. if ( self.mm_dimBackgroundBlurEnabled )
  144. {
  145. [self.mm_dimBackgroundBlurView removeFromSuperview];
  146. self.mm_dimBackgroundBlurView = nil;
  147. UIView *blurView = [self mm_dimBackgroundBlurView];
  148. [self.mm_dimBackgroundView addSubview:blurView];
  149. [blurView mas_makeConstraints:^(MASConstraintMaker *make) {
  150. make.edges.equalTo(self.mm_dimBackgroundView);
  151. }];
  152. }
  153. }
  154. //mm_dimBackgroundBlurView
  155. - (UIView *)mm_dimBackgroundBlurView
  156. {
  157. UIView *blurView = objc_getAssociatedObject(self, mm_dimBackgroundBlurViewKey);
  158. if ( !blurView )
  159. {
  160. blurView = [UIView new];
  161. if ( [UIVisualEffectView class] )
  162. {
  163. UIVisualEffectView *effectView = [[UIVisualEffectView alloc] initWithEffect:[UIBlurEffect effectWithStyle:self.mm_dimBackgroundBlurEffectStyle]];
  164. [blurView addSubview:effectView];
  165. [effectView mas_makeConstraints:^(MASConstraintMaker *make) {
  166. make.edges.equalTo(blurView);
  167. }];
  168. }
  169. else
  170. {
  171. blurView.backgroundColor = @[MMHexColor(0x000007F),MMHexColor(0xFFFFFF7F),MMHexColor(0xFFFFFF7F)][self.mm_dimBackgroundBlurEffectStyle];
  172. }
  173. blurView.userInteractionEnabled = NO;
  174. objc_setAssociatedObject(self, mm_dimBackgroundBlurViewKey, blurView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  175. }
  176. return blurView;
  177. }
  178. - (void)setMm_dimBackgroundBlurView:(UIView *)mm_dimBackgroundBlurView
  179. {
  180. objc_setAssociatedObject(self, mm_dimBackgroundBlurViewKey, mm_dimBackgroundBlurView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  181. }
  182. //mm_dimBackgroundAnimating
  183. - (BOOL)mm_dimBackgroundAnimating
  184. {
  185. return [objc_getAssociatedObject(self, mm_dimBackgroundAnimatingKey) boolValue];
  186. }
  187. - (void)setMm_dimBackgroundAnimating:(BOOL)mm_dimBackgroundAnimating
  188. {
  189. objc_setAssociatedObject(self, mm_dimBackgroundAnimatingKey, @(mm_dimBackgroundAnimating), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  190. }
  191. //mm_dimAnimationDuration
  192. - (NSTimeInterval)mm_dimAnimationDuration
  193. {
  194. return [objc_getAssociatedObject(self, mm_dimAnimationDurationKey) doubleValue];
  195. }
  196. - (void)setMm_dimAnimationDuration:(NSTimeInterval)mm_dimAnimationDuration
  197. {
  198. objc_setAssociatedObject(self, mm_dimAnimationDurationKey, @(mm_dimAnimationDuration), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
  199. }
  200. - (void)mm_showDimBackground
  201. {
  202. ++self.mm_dimReferenceCount;
  203. if ( self.mm_dimReferenceCount > 1 )
  204. {
  205. return;
  206. }
  207. self.mm_dimBackgroundView.hidden = NO;
  208. self.mm_dimBackgroundAnimating = YES;
  209. if ( self == [MMPopupWindow sharedWindow].attachView )
  210. {
  211. [MMPopupWindow sharedWindow].hidden = NO;
  212. [[MMPopupWindow sharedWindow] makeKeyAndVisible];
  213. }
  214. else if ( [self isKindOfClass:[UIWindow class]] )
  215. {
  216. self.hidden = NO;
  217. [(UIWindow*)self makeKeyAndVisible];
  218. }
  219. else
  220. {
  221. [self bringSubviewToFront:self.mm_dimBackgroundView];
  222. }
  223. [UIView animateWithDuration:self.mm_dimAnimationDuration
  224. delay:0
  225. options:UIViewAnimationOptionCurveEaseOut | UIViewAnimationOptionBeginFromCurrentState
  226. animations:^{
  227. self.mm_dimBackgroundView.alpha = 1.0f;
  228. } completion:^(BOOL finished) {
  229. if ( finished )
  230. {
  231. self.mm_dimBackgroundAnimating = NO;
  232. }
  233. }];
  234. }
  235. - (void)mm_hideDimBackground
  236. {
  237. --self.mm_dimReferenceCount;
  238. if ( self.mm_dimReferenceCount > 0 )
  239. {
  240. return;
  241. }
  242. self.mm_dimBackgroundAnimating = YES;
  243. [UIView animateWithDuration:self.mm_dimAnimationDuration
  244. delay:0
  245. options:UIViewAnimationOptionCurveEaseIn | UIViewAnimationOptionBeginFromCurrentState
  246. animations:^{
  247. self.mm_dimBackgroundView.alpha = 0.0f;
  248. } completion:^(BOOL finished) {
  249. if ( finished )
  250. {
  251. self.mm_dimBackgroundAnimating = NO;
  252. if ( self == [MMPopupWindow sharedWindow].attachView )
  253. {
  254. [MMPopupWindow sharedWindow].hidden = YES;
  255. [[[UIApplication sharedApplication].delegate window] makeKeyWindow];
  256. }
  257. else if ( self == [MMPopupWindow sharedWindow] )
  258. {
  259. self.hidden = YES;
  260. [[[UIApplication sharedApplication].delegate window] makeKeyWindow];
  261. }
  262. }
  263. }];
  264. }
  265. - (void) mm_distributeSpacingHorizontallyWith:(NSArray*)views
  266. {
  267. NSMutableArray *spaces = [NSMutableArray arrayWithCapacity:views.count+1];
  268. for ( int i = 0 ; i < views.count+1 ; ++i )
  269. {
  270. UIView *v = [UIView new];
  271. [spaces addObject:v];
  272. [self addSubview:v];
  273. [v mas_makeConstraints:^(MASConstraintMaker *make) {
  274. make.width.equalTo(v.mas_height);
  275. }];
  276. }
  277. UIView *v0 = spaces[0];
  278. [v0 mas_makeConstraints:^(MASConstraintMaker *make) {
  279. make.left.equalTo(self.mas_left);
  280. make.centerY.equalTo(((UIView*)views[0]).mas_centerY);
  281. }];
  282. UIView *lastSpace = v0;
  283. for ( int i = 0 ; i < views.count; ++i )
  284. {
  285. UIView *obj = views[i];
  286. UIView *space = spaces[i+1];
  287. [obj mas_makeConstraints:^(MASConstraintMaker *make) {
  288. make.left.equalTo(lastSpace.mas_right);
  289. }];
  290. [space mas_makeConstraints:^(MASConstraintMaker *make) {
  291. make.left.equalTo(obj.mas_right);
  292. make.centerY.equalTo(obj.mas_centerY);
  293. make.width.equalTo(v0);
  294. }];
  295. lastSpace = space;
  296. }
  297. [lastSpace mas_makeConstraints:^(MASConstraintMaker *make) {
  298. make.right.equalTo(self.mas_right);
  299. }];
  300. }
  301. - (void) mm_distributeSpacingVerticallyWith:(NSArray*)views
  302. {
  303. NSMutableArray *spaces = [NSMutableArray arrayWithCapacity:views.count+1];
  304. for ( int i = 0 ; i < views.count+1 ; ++i )
  305. {
  306. UIView *v = [UIView new];
  307. [spaces addObject:v];
  308. [self addSubview:v];
  309. [v mas_makeConstraints:^(MASConstraintMaker *make) {
  310. make.width.equalTo(v.mas_height);
  311. }];
  312. }
  313. UIView *v0 = spaces[0];
  314. [v0 mas_makeConstraints:^(MASConstraintMaker *make) {
  315. make.top.equalTo(self.mas_top);
  316. make.centerX.equalTo(((UIView*)views[0]).mas_centerX);
  317. }];
  318. UIView *lastSpace = v0;
  319. for ( int i = 0 ; i < views.count; ++i )
  320. {
  321. UIView *obj = views[i];
  322. UIView *space = spaces[i+1];
  323. [obj mas_makeConstraints:^(MASConstraintMaker *make) {
  324. make.top.equalTo(lastSpace.mas_bottom);
  325. }];
  326. [space mas_makeConstraints:^(MASConstraintMaker *make) {
  327. make.top.equalTo(obj.mas_bottom);
  328. make.centerX.equalTo(obj.mas_centerX);
  329. make.height.equalTo(v0);
  330. }];
  331. lastSpace = space;
  332. }
  333. [lastSpace mas_makeConstraints:^(MASConstraintMaker *make) {
  334. make.bottom.equalTo(self.mas_bottom);
  335. }];
  336. }
  337. @end