RQMultiButtons.m 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. //
  2. // RQMultiButtons.m
  3. // jiaPei
  4. //
  5. // Created by 张嵘 on 2018/12/26.
  6. // Copyright © 2018 JCZ. All rights reserved.
  7. //
  8. #import "RQMultiButtons.h"
  9. @interface RQCustomMultiButtons : NSObject
  10. @property NSInteger customId;
  11. @property (strong, nonatomic) UIImage *icon;
  12. @property (strong, nonatomic) NSString *title;
  13. @property (strong, nonatomic) UIColor *backgroundColor;
  14. @end
  15. @implementation RQCustomMultiButtons
  16. @end
  17. @interface RQMultiButtons ()
  18. @property (strong, nonatomic) NSMutableArray *buttons;
  19. @property (strong, nonatomic) NSMutableDictionary *buttonIndexTypes;
  20. @property (strong, nonatomic) UIView *faderView;
  21. @end
  22. @implementation RQMultiButtons
  23. @synthesize delegate = _delegate, parentView;
  24. - (instancetype)initCenteredInWindowWithRadius:(NSInteger)radiusValue {
  25. UIWindow *window = [[[UIApplication sharedApplication] delegate] window];
  26. return [self initWithPoint:CGPointMake((CGFloat) (window.frame.size.width * 0.5), (CGFloat) (window.frame.size.height * 0.5)) radius:radiusValue inView:window];
  27. }
  28. - (instancetype)initWithPoint:(CGPoint)point radius:(NSInteger)radiusValue inView:(UIView *)inView {
  29. self = [super initWithFrame:CGRectMake(point.x - radiusValue, point.y - radiusValue, 2 * radiusValue, 2 * radiusValue)];
  30. if (self) {
  31. self.radius = radiusValue;
  32. self.bubbleRadius = 40;
  33. self.parentView = inView;
  34. self.faderAlpha = 0.15;
  35. self.faderColor = [UIColor blackColor];
  36. self.customButtons = [[NSMutableArray alloc] init];
  37. self.dismissOnBackgroundTap = YES;
  38. UITapGestureRecognizer *tapges = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(shareViewBackgroundTapped:)];
  39. [self addGestureRecognizer:tapges];
  40. }
  41. return self;
  42. }
  43. #pragma mark -
  44. #pragma mark Actions
  45. - (void)buttonWasTapped:(UIButton *)button {
  46. NSInteger buttonType = [_buttonIndexTypes[@(button.tag)] integerValue];
  47. [self shareButtonTappedWithType:buttonType];
  48. }
  49. - (void)shareButtonTappedWithType:(NSInteger)buttonType {
  50. [self hide];
  51. if([self.delegate respondsToSelector:@selector(rqMultiButtons:tappedButtonWithType:)]) {
  52. [self.delegate rqMultiButtons:self tappedButtonWithType:buttonType];
  53. }
  54. }
  55. #pragma mark -
  56. #pragma mark Methods
  57. -(void)show
  58. {
  59. if(!self.isAnimating)
  60. {
  61. self.isAnimating = YES;
  62. [self.parentView addSubview:self];
  63. // Create background
  64. _faderView = [[UIView alloc] initWithFrame:self.parentView.bounds];
  65. _faderView.backgroundColor = self.faderColor;
  66. _faderView.alpha = 0.0f;
  67. if (self.dismissOnBackgroundTap) {
  68. UITapGestureRecognizer *tapges = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(shareViewBackgroundTapped:)];
  69. [_faderView addGestureRecognizer:tapges];
  70. }
  71. [parentView insertSubview:_faderView belowSubview:self];
  72. [UIView animateWithDuration:0.25 animations:^{
  73. _faderView.alpha = self.faderAlpha;
  74. }];
  75. // --
  76. if(_buttons) {
  77. _buttons = nil;
  78. }
  79. _buttons = [[NSMutableArray alloc] init];
  80. _buttonIndexTypes = [[NSMutableDictionary alloc] init];
  81. for (RQCustomMultiButtons *customButton in self.customButtons)
  82. {
  83. [self createButtonWithIcon:customButton.icon title:customButton.title backgroundColor:customButton.backgroundColor andButtonId:customButton.customId];
  84. }
  85. if(_buttons.count == 0) return;
  86. float bubbleDistanceFromPivot = self.radius - self.bubbleRadius;
  87. float bubblesBetweenAngel = 360 / _buttons.count / 2;
  88. float angely = (float) ((180 - bubblesBetweenAngel) * 0.5);
  89. float startAngel = 270 - angely;
  90. NSMutableArray *coordinates = [NSMutableArray array];
  91. for (NSUInteger i = 0; i < _buttons.count; ++i)
  92. {
  93. UIButton *button = _buttons[i];
  94. button.tag = i;
  95. float angle = startAngel + i * bubblesBetweenAngel;
  96. float x = (float) (cos(angle * M_PI / 180) * bubbleDistanceFromPivot + self.radius);
  97. float y = (float) (sin(angle * M_PI / 180) * bubbleDistanceFromPivot + self.radius);
  98. [coordinates addObject:@{@"x" : @(x), @"y" : @(y)}];
  99. button.transform = CGAffineTransformMakeScale(0.001, 0.001);
  100. button.center = CGPointMake(self.radius, self.radius);
  101. }
  102. NSInteger inetratorI = 0;
  103. for (NSDictionary *coordinate in coordinates)
  104. {
  105. UIButton *button = _buttons[inetratorI];
  106. float delayTime = (float) (inetratorI * 0.1);
  107. [self performSelector:@selector(showBubbleWithAnimation:) withObject:@{@"button" : button, @"coordinate" : coordinate} afterDelay:delayTime];
  108. ++inetratorI;
  109. }
  110. }
  111. }
  112. -(void)hide
  113. {
  114. if(!self.isAnimating)
  115. {
  116. self.isAnimating = YES;
  117. NSInteger inetratorI = 0;
  118. for (UIButton *button in _buttons)
  119. {
  120. CGFloat delayTime = (CGFloat) (inetratorI * 0.1);
  121. [self performSelector:@selector(hideBubbleWithAnimation:) withObject:button afterDelay:delayTime];
  122. ++inetratorI;
  123. }
  124. }
  125. }
  126. #pragma mark -
  127. #pragma mark Helper functions
  128. -(void)shareViewBackgroundTapped:(UITapGestureRecognizer *)tapGesture
  129. {
  130. [self hide];
  131. }
  132. -(void)showBubbleWithAnimation:(NSDictionary *)info
  133. {
  134. UIButton *bubble = (UIButton *) info[@"button"];
  135. NSDictionary *coordinate = (NSDictionary *) info[@"coordinate"];
  136. [UIView animateWithDuration:0.25 animations:^{
  137. bubble.center = CGPointMake([coordinate[@"x"] floatValue], [coordinate[@"y"] floatValue]);
  138. bubble.alpha = 1;
  139. bubble.transform = CGAffineTransformMakeScale(1.2, 1.2);
  140. } completion:^(BOOL finished) {
  141. [UIView animateWithDuration:0.15 animations:^{
  142. bubble.transform = CGAffineTransformMakeScale(0.8, 0.8);
  143. } completion:^(BOOL finished) {
  144. [UIView animateWithDuration:0.15 animations:^{
  145. bubble.transform = CGAffineTransformMakeScale(1, 1);
  146. } completion:^(BOOL finished) {
  147. if(bubble.tag == _buttons.count - 1) self.isAnimating = NO;
  148. bubble.layer.shadowColor = [UIColor blackColor].CGColor;
  149. bubble.layer.shadowOpacity = 0.2;
  150. bubble.layer.shadowOffset = CGSizeMake(0, 1);
  151. bubble.layer.shadowRadius = 2;
  152. }];
  153. }];
  154. }];
  155. }
  156. - (void)hideBubbleWithAnimation:(UIButton *)bubble {
  157. [UIView animateWithDuration:0.2 animations:^{
  158. bubble.transform = CGAffineTransformMakeScale(1.2, 1.2);
  159. } completion:^(BOOL finished) {
  160. [UIView animateWithDuration:0.25 animations:^{
  161. bubble.center = CGPointMake(self.radius, self.radius);
  162. bubble.transform = CGAffineTransformMakeScale(0.001, 0.001);
  163. bubble.alpha = 0;
  164. } completion:^(BOOL finished) {
  165. if(bubble.tag == _buttons.count - 1) {
  166. self.isAnimating = NO;
  167. self.hidden = YES;
  168. [UIView animateWithDuration:0.25 animations:^{
  169. _faderView.alpha = 0;
  170. } completion:^(BOOL finished) {
  171. [_faderView removeFromSuperview];
  172. if([self.delegate respondsToSelector:@selector(rqMultiButtonsDidHide:)]) {
  173. [self.delegate rqMultiButtonsDidHide:self];
  174. }
  175. [self removeFromSuperview];
  176. }];
  177. }
  178. [bubble removeFromSuperview];
  179. }];
  180. }];
  181. }
  182. - (void)createButtonWithIcon:(UIImage *)icon title:(NSString *)title backgroundColor:(UIColor *)color andButtonId:(NSInteger)buttonId {
  183. UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
  184. [button addTarget:self action:@selector(buttonWasTapped:) forControlEvents:UIControlEventTouchUpInside];
  185. button.frame = CGRectMake(0, 0, 2 * self.bubbleRadius, 2 * self.bubbleRadius);
  186. // Circle background
  187. UIView *circle = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 2 * self.bubbleRadius, 2 * self.bubbleRadius)];
  188. circle.backgroundColor = color;
  189. circle.layer.cornerRadius = self.bubbleRadius;
  190. circle.layer.masksToBounds = YES;
  191. circle.opaque = NO;
  192. circle.alpha = 0.97;
  193. // Circle icon
  194. UIImageView *iconView = [[UIImageView alloc] initWithImage:icon];
  195. CGRect f = iconView.frame;
  196. f.origin.x = (CGFloat) ((circle.frame.size.width - f.size.width) * 0.5);
  197. f.origin.y = [title isEqualToString:@"随机练习"]? (CGFloat) ((circle.frame.size.height - f.size.height) * 0.5 - 5) : ((CGFloat) ((circle.frame.size.height - f.size.height) * 0.5 + 10));
  198. iconView.frame = f;
  199. [circle addSubview:iconView];
  200. UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 2 * self.bubbleRadius - 20, 2 * self.bubbleRadius, 10)];
  201. titleLabel.text = title;
  202. titleLabel.font = [UIFont systemFontOfSize:10];
  203. titleLabel.textColor = defGreen;
  204. titleLabel.textAlignment = NSTextAlignmentCenter;
  205. [circle addSubview:titleLabel];
  206. [button setBackgroundImage:[self imageWithView:circle] forState:UIControlStateNormal];
  207. [_buttons addObject:button];
  208. _buttonIndexTypes[@(_buttons.count - 1)] = @(buttonId);
  209. [self addSubview:button];
  210. }
  211. - (void)createButtonWithIcon:(NSString *)iconName backgroundColor:(NSInteger)rgb andType:(RQMultiButtonsType)type {
  212. NSBundle *classBundle = [NSBundle bundleForClass:[self class]];
  213. NSBundle *resourcesBundle = [NSBundle bundleWithPath:[NSString stringWithFormat:@"%@/AAShareBubbles.bundle", classBundle.bundlePath]];
  214. UIImage *icon = [UIImage imageNamed:iconName inBundle:resourcesBundle compatibleWithTraitCollection:nil];
  215. UIColor *color = [self colorFromRGB:rgb];
  216. [self createButtonWithIcon:icon title:@"顺序练习" backgroundColor:color andButtonId:type];
  217. }
  218. - (void)addCustomButtonWithIcon:(UIImage *)icon title:(NSString *)title backgroundColor:(UIColor *)color andButtonId:(NSInteger)buttonId {
  219. NSAssert(buttonId >= 100, @"Custom Button Ids must be >= 100");
  220. RQCustomMultiButtons *customButton = [[RQCustomMultiButtons alloc] init];
  221. customButton.backgroundColor = color;
  222. customButton.icon = icon;
  223. customButton.title = title;
  224. customButton.customId = buttonId;
  225. [self.customButtons addObject:customButton];
  226. }
  227. - (UIColor *)colorFromRGB:(NSInteger)rgb {
  228. return [UIColor colorWithRed:((float)((rgb & 0xFF0000) >> 16))/255.0 green:((float)((rgb & 0xFF00) >> 8))/255.0 blue:((float)(rgb & 0xFF))/255.0 alpha:1.0];
  229. }
  230. - (UIImage *)imageWithView:(UIView *)view {
  231. UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0);
  232. [view.layer renderInContext:UIGraphicsGetCurrentContext()];
  233. UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
  234. UIGraphicsEndImageContext();
  235. return img;
  236. }
  237. @end