扩展QuadCurveMenu,实现了八个方向上的弹出菜单

最近在看一些开源项目,其中有一个弹出菜单QuadCurveMenu觉得挺不错,可惜只可以向右上角弹出菜单,于是就修改了下,实现了八个方向的弹出菜单,现在发上来供大家批评指正。

  1. //
  2. //QuadCurveMenu.h
  3. //AwesomeMenu
  4. //
  5. //CreatedbyLeveyon11/30/11.
  6. //Copyright(c)2011Lunaapp.com.Allrightsreserved.
  7. //
  8. #import<UIKit/UIKit.h>
  9. #import"QuadCurveMenuItem.h"
  10. @protocolQuadCurveMenuDelegate;
  11. //defulttypeislikethis
  12. /*
  13. *O
  14. *O
  15. *O
  16. *O
  17. *0O
  18. */
  19. typedefenum
  20. {
  21. QuadCurveMenuTypeUpAndRight=0,
  22. QuadCurveMenuTypeUpAndLeft,
  23. QuadCurveMenuTypeDownAndRight,
  24. QuadCurveMenuTypeDownAndLeft,
  25. QuadCurveMenuTypeUp,
  26. QuadCurveMenuTypeDown,
  27. QuadCurveMenuTypeLeft,
  28. QuadCurveMenuTypeRight,
  29. QuadCurveMenuTypeDefault=QuadCurveMenuTypeUpAndRight
  30. }QuadCureMenuType;
  31. @interfaceQuadCurveMenu:UIView<QuadCurveMenuItemDelegate>
  32. {
  33. NSArray*_menusArray;
  34. int_flag;
  35. NSTimer*_timer;
  36. QuadCurveMenuItem*_addButton;
  37. QuadCureMenuType_type;
  38. id<QuadCurveMenuDelegate>_delegate;
  39. CGPoint_startPoint;
  40. }
  41. @property(nonatomic,copy)NSArray*menusArray;
  42. @property(nonatomic)QuadCureMenuTypetype;
  43. @property(nonatomic,getter=isExpanding)BOOLexpanding;
  44. @property(nonatomic,assign)id<QuadCurveMenuDelegate>delegate;
  45. -(id)initWithFrame:(CGRect)framemenus:(NSArray*)aMenusArray;
  46. -(void)setType:(QuadCureMenuType)type;
  47. -(void)setStartPoint:(CGPoint)startpoint;
  48. @end
  49. @protocolQuadCurveMenuDelegate<NSObject>
  50. -(void)quadCurveMenu:(QuadCurveMenu*)menudidSelectIndex:(NSInteger)idx;
  51. @end

  1. //
  2. //QuadCurveMenu.m
  3. //AwesomeMenu
  4. //
  5. //CreatedbyLeveyon11/30/11.
  6. //Copyright(c)2011Lunaapp.com.Allrightsreserved.
  7. //
  8. #import"QuadCurveMenu.h"
  9. #import<QuartzCore/QuartzCore.h>
  10. #defineNEARRADIUS130.0f
  11. #defineENDRADIUS140.0f
  12. #defineFARRADIUS160.0f
  13. #defineBETWEENADIUS50.0f
  14. #defineSTARTPOINTCGPointMake(100,130)
  15. #defineTIMEOFFSET0.05f
  16. @interfaceQuadCurveMenu()
  17. -(void)_expand;
  18. -(void)_close;
  19. -(CAAnimationGroup*)_blowupAnimationAtPoint:(CGPoint)p;
  20. -(CAAnimationGroup*)_shrinkAnimationAtPoint:(CGPoint)p;
  21. @end
  22. @implementationQuadCurveMenu
  23. @synthesizeexpanding=_expanding;
  24. @synthesizedelegate=_delegate;
  25. @synthesizemenusArray=_menusArray;
  26. @synthesizetype=_type;
  27. #pragmamark-initialization&cleaningup
  28. -(id)initWithFrame:(CGRect)framemenus:(NSArray*)aMenusArray
  29. {
  30. self=[superinitWithFrame:frame];
  31. if(self){
  32. self.backgroundColor=[UIColorclearColor];
  33. _startPoint=STARTPOINT;
  34. _menusArray=[aMenusArraycopy];
  35. //addthemenubuttons
  36. intcount=[_menusArraycount];
  37. for(inti=0;i<count;i++)
  38. {
  39. QuadCurveMenuItem*item=[_menusArrayobjectAtIndex:i];
  40. item.tag=1000+i;
  41. item.startPoint=STARTPOINT;
  42. item.endPoint=CGPointMake(_startPoint.x+ENDRADIUS*sinf(i*M_PI_2/(count-1)),_startPoint.y-ENDRADIUS*cosf(i*M_PI_2/(count-1)));
  43. item.nearPoint=CGPointMake(_startPoint.x+NEARRADIUS*sinf(i*M_PI_2/(count-1)),_startPoint.y-NEARRADIUS*cosf(i*M_PI_2/(count-1)));
  44. item.farPoint=CGPointMake(_startPoint.x+FARRADIUS*sinf(i*M_PI_2/(count-1)),_startPoint.y-FARRADIUS*cosf(i*M_PI_2/(count-1)));
  45. item.center=item.startPoint;
  46. item.delegate=self;
  47. [selfaddSubview:item];
  48. }
  49. //addthe"Add"Button.
  50. _addButton=[[QuadCurveMenuItemalloc]initWithImage:[UIImageimageNamed:@"story-add-button.png"]
  51. highlightedImage:[UIImageimageNamed:@"story-add-button-pressed.png"]
  52. ContentImage:[UIImageimageNamed:@"story-add-plus.png"]
  53. highlightedContentImage:[UIImageimageNamed:@"story-add-plus-pressed.png"]];
  54. _addButton.delegate=self;
  55. _addButton.center=_startPoint;
  56. [selfaddSubview:_addButton];
  57. }
  58. returnself;
  59. }
  60. -(void)setType:(QuadCureMenuType)type
  61. {
  62. _type=type;
  63. intdx=1;
  64. intdy=1;
  65. BOOLisTwoDirctions=YES;
  66. if(_menusArray!=nil){
  67. switch(type){
  68. caseQuadCurveMenuTypeUpAndRight:
  69. break;
  70. caseQuadCurveMenuTypeUpAndLeft:
  71. dx=-1;
  72. break;
  73. caseQuadCurveMenuTypeDownAndRight:
  74. dy=-1;
  75. break;
  76. caseQuadCurveMenuTypeDownAndLeft:
  77. dy=dx=-1;
  78. break;
  79. caseQuadCurveMenuTypeUp:
  80. isTwoDirctions=NO;dx=0;dy=-1;
  81. break;
  82. caseQuadCurveMenuTypeDown:
  83. isTwoDirctions=NO;dx=0;dy=1;
  84. break;
  85. caseQuadCurveMenuTypeLeft:
  86. isTwoDirctions=NO;dx=-1;dy=0;
  87. break;
  88. caseQuadCurveMenuTypeRight:
  89. isTwoDirctions=NO;dx=1;dy=0;
  90. default:
  91. break;
  92. }
  93. intcount=[_menusArraycount];
  94. for(inti=0;i<count;i++)
  95. {
  96. QuadCurveMenuItem*item=[_menusArrayobjectAtIndex:i];
  97. item.startPoint=_startPoint;
  98. if(isTwoDirctions){
  99. item.endPoint=CGPointMake(_startPoint.x+dx*ENDRADIUS*sinf(i*M_PI_2/(count-1)),_startPoint.y-dy*ENDRADIUS*cosf(i*M_PI_2/(count-1)));
  100. item.nearPoint=CGPointMake(_startPoint.x+dx*NEARRADIUS*sinf(i*M_PI_2/(count-1)),_startPoint.y-dy*NEARRADIUS*cosf(i*M_PI_2/(count-1)));
  101. item.farPoint=CGPointMake(_startPoint.x+dx*FARRADIUS*sinf(i*M_PI_2/(count-1)),_startPoint.y-dy*FARRADIUS*cosf(i*M_PI_2/(count-1)));
  102. }else
  103. {
  104. item.endPoint=CGPointMake(_startPoint.x+dx*i*BETWEENADIUS,_startPoint.y+dy*i*BETWEENADIUS);
  105. item.nearPoint=CGPointMake(_startPoint.x+dx*i*(BETWEENADIUS-15),_startPoint.y+dy*i*(BETWEENADIUS-15));
  106. item.farPoint=CGPointMake(_startPoint.x+dx*i*(BETWEENADIUS+20),_startPoint.y+dy*i*(BETWEENADIUS+20));
  107. }
  108. item.center=item.startPoint;
  109. }
  110. }
  111. }
  112. -(void)setStartPoint:(CGPoint)startpoint
  113. {
  114. _startPoint=startpoint;
  115. _addButton.center=_startPoint;
  116. [selfsetType:_type];
  117. };
  118. -(void)dealloc
  119. {
  120. [_addButtonrelease];
  121. [_menusArrayrelease];
  122. [superdealloc];
  123. }
  124. #pragmamark-UIView'smethods
  125. -(BOOL)pointInside:(CGPoint)pointwithEvent:(UIEvent*)event
  126. {
  127. //ifthemenustateisexpanding,everywherecanbetouch
  128. //otherwise,onlytheaddbuttonarecanbetouch
  129. if(YES==_expanding)
  130. {
  131. returnYES;
  132. }
  133. else
  134. {
  135. returnCGRectContainsPoint(_addButton.frame,point);
  136. }
  137. }
  138. -(void)touchesBegan:(NSSet*)toucheswithEvent:(UIEvent*)event
  139. {
  140. self.expanding=!self.isExpanding;
  141. }
  142. #pragmamark-QuadCurveMenuItemdelegates
  143. -(void)quadCurveMenuItemTouchesBegan:(QuadCurveMenuItem*)item
  144. {
  145. if(item==_addButton)
  146. {
  147. self.expanding=!self.isExpanding;
  148. }
  149. }
  150. -(void)quadCurveMenuItemTouchesEnd:(QuadCurveMenuItem*)item
  151. {
  152. //excludethe"add"button
  153. if(item==_addButton)
  154. {
  155. return;
  156. }
  157. //blowuptheselectedmenubutton
  158. CAAnimationGroup*blowup=[self_blowupAnimationAtPoint:item.center];
  159. [item.layeraddAnimation:blowupforKey:@"blowup"];
  160. item.center=item.startPoint;
  161. //shrinkothermenubuttons
  162. for(inti=0;i<[_menusArraycount];i++)
  163. {
  164. QuadCurveMenuItem*otherItem=[_menusArrayobjectAtIndex:i];
  165. CAAnimationGroup*shrink=[self_shrinkAnimationAtPoint:otherItem.center];
  166. if(otherItem.tag==item.tag){
  167. continue;
  168. }
  169. [otherItem.layeraddAnimation:shrinkforKey:@"shrink"];
  170. otherItem.center=otherItem.startPoint;
  171. }
  172. _expanding=NO;
  173. //rotate"add"button
  174. floatangle=self.isExpanding?-M_PI_4:0.0f;
  175. [UIViewanimateWithDuration:0.2fanimations:^{
  176. _addButton.transform=CGAffineTransformMakeRotation(angle);
  177. }];
  178. if([_delegaterespondsToSelector:@selector(quadCurveMenu:didSelectIndex:)])
  179. {
  180. [_delegatequadCurveMenu:selfdidSelectIndex:item.tag-1000];
  181. }
  182. }
  183. #pragmamark-instantmethods
  184. -(void)setMenusArray:(NSArray*)aMenusArray
  185. {
  186. if(aMenusArray==_menusArray)
  187. {
  188. return;
  189. }
  190. [_menusArrayrelease];
  191. _menusArray=[aMenusArraycopy];
  192. //cleansubviews
  193. for(UIView*vinself.subviews)
  194. {
  195. if(v.tag>=1000)
  196. {
  197. [vremoveFromSuperview];
  198. }
  199. }
  200. //addthemenubuttons
  201. intcount=[_menusArraycount];
  202. for(inti=0;i<count;i++)
  203. {
  204. QuadCurveMenuItem*item=[_menusArrayobjectAtIndex:i];
  205. item.tag=1000+i;
  206. item.startPoint=_startPoint;
  207. item.endPoint=CGPointMake(_startPoint.x+ENDRADIUS*sinf(i*M_PI_2/(count-1)),_startPoint.y-ENDRADIUS*cosf(i*M_PI_2/(count-1)));
  208. item.nearPoint=CGPointMake(_startPoint.x+NEARRADIUS*sinf(i*M_PI_2/(count-1)),_startPoint.y-NEARRADIUS*cosf(i*M_PI_2/(count-1)));
  209. item.farPoint=CGPointMake(_startPoint.x+FARRADIUS*sinf(i*M_PI_2/(count-1)),_startPoint.y-FARRADIUS*cosf(i*M_PI_2/(count-1)));
  210. item.center=item.startPoint;
  211. item.delegate=self;
  212. [selfaddSubview:item];
  213. }
  214. }
  215. -(BOOL)isExpanding
  216. {
  217. return_expanding;
  218. }
  219. -(void)setExpanding:(BOOL)expanding
  220. {
  221. _expanding=expanding;
  222. //rotateaddbutton
  223. floatangle=self.isExpanding?-M_PI_4:0.0f;
  224. [UIViewanimateWithDuration:0.2fanimations:^{
  225. _addButton.transform=CGAffineTransformMakeRotation(angle);
  226. }];
  227. //expandorcloseanimation
  228. if(!_timer)
  229. {
  230. _flag=self.isExpanding?0:5;
  231. SELselector=self.isExpanding?@selector(_expand):@selector(_close);
  232. _timer=[[NSTimerscheduledTimerWithTimeInterval:TIMEOFFSETtarget:selfselector:selectoruserInfo:nilrepeats:YES]retain];
  233. }
  234. }
  235. #pragmamark-privatemethods
  236. -(void)_expand
  237. {
  238. if(_flag==6)
  239. {
  240. [_timerinvalidate];
  241. [_timerrelease];
  242. _timer=nil;
  243. return;
  244. }
  245. inttag=1000+_flag;
  246. QuadCurveMenuItem*item=(QuadCurveMenuItem*)[selfviewWithTag:tag];
  247. CAKeyframeAnimation*rotateAnimation=[CAKeyframeAnimationanimationWithKeyPath:@"transform.rotation.z"];
  248. rotateAnimation.values=[NSArrayarrayWithObjects:[NSNumbernumberWithFloat:M_PI],[NSNumbernumberWithFloat:0.0f],nil];
  249. rotateAnimation.duration=0.5f;
  250. rotateAnimation.keyTimes=[NSArrayarrayWithObjects:
  251. [NSNumbernumberWithFloat:.3],
  252. [NSNumbernumberWithFloat:.4],nil];
  253. CAKeyframeAnimation*positionAnimation=[CAKeyframeAnimationanimationWithKeyPath:@"position"];
  254. positionAnimation.duration=0.5f;
  255. CGMutablePathRefpath=CGPathCreateMutable();
  256. CGPathMoveToPoint(path,NULL,item.startPoint.x,item.startPoint.y);
  257. CGPathAddLineToPoint(path,NULL,item.farPoint.x,item.farPoint.y);
  258. CGPathAddLineToPoint(path,NULL,item.nearPoint.x,item.nearPoint.y);
  259. CGPathAddLineToPoint(path,NULL,item.endPoint.x,item.endPoint.y);
  260. positionAnimation.path=path;
  261. CGPathRelease(path);
  262. CAAnimationGroup*animationgroup=[CAAnimationGroupanimation];
  263. animationgroup.animations=[NSArrayarrayWithObjects:positionAnimation,rotateAnimation,nil];
  264. animationgroup.duration=0.5f;
  265. animationgroup.fillMode=kCAFillModeForwards;
  266. animationgroup.timingFunction=[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionEaseIn];
  267. [item.layeraddAnimation:animationgroupforKey:@"Expand"];
  268. item.center=item.endPoint;
  269. _flag++;
  270. }
  271. -(void)_close
  272. {
  273. if(_flag==-1)
  274. {
  275. [_timerinvalidate];
  276. [_timerrelease];
  277. _timer=nil;
  278. return;
  279. }
  280. inttag=1000+_flag;
  281. QuadCurveMenuItem*item=(QuadCurveMenuItem*)[selfviewWithTag:tag];
  282. CAKeyframeAnimation*rotateAnimation=[CAKeyframeAnimationanimationWithKeyPath:@"transform.rotation.z"];
  283. rotateAnimation.values=[NSArrayarrayWithObjects:[NSNumbernumberWithFloat:0.0f],[NSNumbernumberWithFloat:M_PI*2],[NSNumbernumberWithFloat:0.0f],nil];
  284. rotateAnimation.duration=0.5f;
  285. rotateAnimation.keyTimes=[NSArrayarrayWithObjects:
  286. [NSNumbernumberWithFloat:.0],
  287. [NSNumbernumberWithFloat:.4],
  288. [NSNumbernumberWithFloat:.5],nil];
  289. CAKeyframeAnimation*positionAnimation=[CAKeyframeAnimationanimationWithKeyPath:@"position"];
  290. positionAnimation.duration=0.5f;
  291. CGMutablePathRefpath=CGPathCreateMutable();
  292. CGPathMoveToPoint(path,NULL,item.endPoint.x,item.endPoint.y);
  293. CGPathAddLineToPoint(path,NULL,item.farPoint.x,item.farPoint.y);
  294. CGPathAddLineToPoint(path,NULL,item.startPoint.x,item.startPoint.y);
  295. positionAnimation.path=path;
  296. CGPathRelease(path);
  297. CAAnimationGroup*animationgroup=[CAAnimationGroupanimation];
  298. animationgroup.animations=[NSArrayarrayWithObjects:positionAnimation,rotateAnimation,nil];
  299. animationgroup.duration=0.5f;
  300. animationgroup.fillMode=kCAFillModeForwards;
  301. animationgroup.timingFunction=[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionEaseIn];
  302. [item.layeraddAnimation:animationgroupforKey:@"Close"];
  303. item.center=item.startPoint;
  304. _flag--;
  305. }
  306. -(CAAnimationGroup*)_blowupAnimationAtPoint:(CGPoint)p
  307. {
  308. CAKeyframeAnimation*positionAnimation=[CAKeyframeAnimationanimationWithKeyPath:@"position"];
  309. positionAnimation.values=[NSArrayarrayWithObjects:[NSValuevalueWithCGPoint:p],nil];
  310. positionAnimation.keyTimes=[NSArrayarrayWithObjects:[NSNumbernumberWithFloat:.3],nil];
  311. CABasicAnimation*scaleAnimation=[CABasicAnimationanimationWithKeyPath:@"transform"];
  312. scaleAnimation.toValue=[NSValuevalueWithCATransform3D:CATransform3DMakeScale(3,3,1)];
  313. CABasicAnimation*opacityAnimation=[CABasicAnimationanimationWithKeyPath:@"opacity"];
  314. opacityAnimation.toValue=[NSNumbernumberWithFloat:0.0f];
  315. CAAnimationGroup*animationgroup=[CAAnimationGroupanimation];
  316. animationgroup.animations=[NSArrayarrayWithObjects:positionAnimation,scaleAnimation,opacityAnimation,nil];
  317. animationgroup.duration=0.3f;
  318. animationgroup.fillMode=kCAFillModeForwards;
  319. returnanimationgroup;
  320. }
  321. -(CAAnimationGroup*)_shrinkAnimationAtPoint:(CGPoint)p
  322. {
  323. CAKeyframeAnimation*positionAnimation=[CAKeyframeAnimationanimationWithKeyPath:@"position"];
  324. positionAnimation.values=[NSArrayarrayWithObjects:[NSValuevalueWithCGPoint:p],nil];
  325. positionAnimation.keyTimes=[NSArrayarrayWithObjects:[NSNumbernumberWithFloat:.3],nil];
  326. CABasicAnimation*scaleAnimation=[CABasicAnimationanimationWithKeyPath:@"transform"];
  327. scaleAnimation.toValue=[NSValuevalueWithCATransform3D:CATransform3DMakeScale(.01,.01,1)];
  328. CABasicAnimation*opacityAnimation=[CABasicAnimationanimationWithKeyPath:@"opacity"];
  329. opacityAnimation.toValue=[NSNumbernumberWithFloat:0.0f];
  330. CAAnimationGroup*animationgroup=[CAAnimationGroupanimation];
  331. animationgroup.animations=[NSArrayarrayWithObjects:positionAnimation,scaleAnimation,opacityAnimation,nil];
  332. animationgroup.duration=0.3f;
  333. animationgroup.fillMode=kCAFillModeForwards;
  334. returnanimationgroup;
  335. }
  336. @end

运行截图:

扩展QuadCurveMenu,实现了八个方向上的弹出菜单扩展QuadCurveMenu,实现了八个方向上的弹出菜单DEMO下载地址:http://download.csdn.net/detail/toss156/4164935

你可能感兴趣的:(menu)