扩展QuadCurveMenu,实现了八个方向上的弹出菜单
最近在看一些开源项目,其中有一个弹出菜单QuadCurveMenu觉得挺不错,可惜只可以向右上角弹出菜单,于是就修改了下,实现了八个方向的弹出菜单,现在发上来供大家批评指正。
- //
- //QuadCurveMenu.h
- //AwesomeMenu
- //
- //CreatedbyLeveyon11/30/11.
- //Copyright(c)2011Lunaapp.com.Allrightsreserved.
- //
- #import<UIKit/UIKit.h>
- #import"QuadCurveMenuItem.h"
- @protocolQuadCurveMenuDelegate;
- //defulttypeislikethis
- /*
- *O
- *O
- *O
- *O
- *0O
- */
- typedefenum
- {
- QuadCurveMenuTypeUpAndRight=0,
- QuadCurveMenuTypeUpAndLeft,
- QuadCurveMenuTypeDownAndRight,
- QuadCurveMenuTypeDownAndLeft,
- QuadCurveMenuTypeUp,
- QuadCurveMenuTypeDown,
- QuadCurveMenuTypeLeft,
- QuadCurveMenuTypeRight,
- QuadCurveMenuTypeDefault=QuadCurveMenuTypeUpAndRight
- }QuadCureMenuType;
- @interfaceQuadCurveMenu:UIView<QuadCurveMenuItemDelegate>
- {
- NSArray*_menusArray;
- int_flag;
- NSTimer*_timer;
- QuadCurveMenuItem*_addButton;
- QuadCureMenuType_type;
- id<QuadCurveMenuDelegate>_delegate;
- CGPoint_startPoint;
- }
- @property(nonatomic,copy)NSArray*menusArray;
- @property(nonatomic)QuadCureMenuTypetype;
- @property(nonatomic,getter=isExpanding)BOOLexpanding;
- @property(nonatomic,assign)id<QuadCurveMenuDelegate>delegate;
- -(id)initWithFrame:(CGRect)framemenus:(NSArray*)aMenusArray;
- -(void)setType:(QuadCureMenuType)type;
- -(void)setStartPoint:(CGPoint)startpoint;
- @end
- @protocolQuadCurveMenuDelegate<NSObject>
- -(void)quadCurveMenu:(QuadCurveMenu*)menudidSelectIndex:(NSInteger)idx;
- @end
- //
- //QuadCurveMenu.m
- //AwesomeMenu
- //
- //CreatedbyLeveyon11/30/11.
- //Copyright(c)2011Lunaapp.com.Allrightsreserved.
- //
- #import"QuadCurveMenu.h"
- #import<QuartzCore/QuartzCore.h>
- #defineNEARRADIUS130.0f
- #defineENDRADIUS140.0f
- #defineFARRADIUS160.0f
- #defineBETWEENADIUS50.0f
- #defineSTARTPOINTCGPointMake(100,130)
- #defineTIMEOFFSET0.05f
- @interfaceQuadCurveMenu()
- -(void)_expand;
- -(void)_close;
- -(CAAnimationGroup*)_blowupAnimationAtPoint:(CGPoint)p;
- -(CAAnimationGroup*)_shrinkAnimationAtPoint:(CGPoint)p;
- @end
- @implementationQuadCurveMenu
- @synthesizeexpanding=_expanding;
- @synthesizedelegate=_delegate;
- @synthesizemenusArray=_menusArray;
- @synthesizetype=_type;
- #pragmamark-initialization&cleaningup
- -(id)initWithFrame:(CGRect)framemenus:(NSArray*)aMenusArray
- {
- self=[superinitWithFrame:frame];
- if(self){
- self.backgroundColor=[UIColorclearColor];
- _startPoint=STARTPOINT;
- _menusArray=[aMenusArraycopy];
- //addthemenubuttons
- intcount=[_menusArraycount];
- for(inti=0;i<count;i++)
- {
- QuadCurveMenuItem*item=[_menusArrayobjectAtIndex:i];
- item.tag=1000+i;
- item.startPoint=STARTPOINT;
- item.endPoint=CGPointMake(_startPoint.x+ENDRADIUS*sinf(i*M_PI_2/(count-1)),_startPoint.y-ENDRADIUS*cosf(i*M_PI_2/(count-1)));
- item.nearPoint=CGPointMake(_startPoint.x+NEARRADIUS*sinf(i*M_PI_2/(count-1)),_startPoint.y-NEARRADIUS*cosf(i*M_PI_2/(count-1)));
- item.farPoint=CGPointMake(_startPoint.x+FARRADIUS*sinf(i*M_PI_2/(count-1)),_startPoint.y-FARRADIUS*cosf(i*M_PI_2/(count-1)));
- item.center=item.startPoint;
- item.delegate=self;
- [selfaddSubview:item];
- }
- //addthe"Add"Button.
- _addButton=[[QuadCurveMenuItemalloc]initWithImage:[UIImageimageNamed:@"story-add-button.png"]
- highlightedImage:[UIImageimageNamed:@"story-add-button-pressed.png"]
- ContentImage:[UIImageimageNamed:@"story-add-plus.png"]
- highlightedContentImage:[UIImageimageNamed:@"story-add-plus-pressed.png"]];
- _addButton.delegate=self;
- _addButton.center=_startPoint;
- [selfaddSubview:_addButton];
- }
- returnself;
- }
- -(void)setType:(QuadCureMenuType)type
- {
- _type=type;
- intdx=1;
- intdy=1;
- BOOLisTwoDirctions=YES;
- if(_menusArray!=nil){
- switch(type){
- caseQuadCurveMenuTypeUpAndRight:
- break;
- caseQuadCurveMenuTypeUpAndLeft:
- dx=-1;
- break;
- caseQuadCurveMenuTypeDownAndRight:
- dy=-1;
- break;
- caseQuadCurveMenuTypeDownAndLeft:
- dy=dx=-1;
- break;
- caseQuadCurveMenuTypeUp:
- isTwoDirctions=NO;dx=0;dy=-1;
- break;
- caseQuadCurveMenuTypeDown:
- isTwoDirctions=NO;dx=0;dy=1;
- break;
- caseQuadCurveMenuTypeLeft:
- isTwoDirctions=NO;dx=-1;dy=0;
- break;
- caseQuadCurveMenuTypeRight:
- isTwoDirctions=NO;dx=1;dy=0;
- default:
- break;
- }
- intcount=[_menusArraycount];
- for(inti=0;i<count;i++)
- {
- QuadCurveMenuItem*item=[_menusArrayobjectAtIndex:i];
- item.startPoint=_startPoint;
- if(isTwoDirctions){
- 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)));
- 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)));
- 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)));
- }else
- {
- item.endPoint=CGPointMake(_startPoint.x+dx*i*BETWEENADIUS,_startPoint.y+dy*i*BETWEENADIUS);
- item.nearPoint=CGPointMake(_startPoint.x+dx*i*(BETWEENADIUS-15),_startPoint.y+dy*i*(BETWEENADIUS-15));
- item.farPoint=CGPointMake(_startPoint.x+dx*i*(BETWEENADIUS+20),_startPoint.y+dy*i*(BETWEENADIUS+20));
- }
- item.center=item.startPoint;
- }
- }
- }
- -(void)setStartPoint:(CGPoint)startpoint
- {
- _startPoint=startpoint;
- _addButton.center=_startPoint;
- [selfsetType:_type];
- };
- -(void)dealloc
- {
- [_addButtonrelease];
- [_menusArrayrelease];
- [superdealloc];
- }
- #pragmamark-UIView'smethods
- -(BOOL)pointInside:(CGPoint)pointwithEvent:(UIEvent*)event
- {
- //ifthemenustateisexpanding,everywherecanbetouch
- //otherwise,onlytheaddbuttonarecanbetouch
- if(YES==_expanding)
- {
- returnYES;
- }
- else
- {
- returnCGRectContainsPoint(_addButton.frame,point);
- }
- }
- -(void)touchesBegan:(NSSet*)toucheswithEvent:(UIEvent*)event
- {
- self.expanding=!self.isExpanding;
- }
- #pragmamark-QuadCurveMenuItemdelegates
- -(void)quadCurveMenuItemTouchesBegan:(QuadCurveMenuItem*)item
- {
- if(item==_addButton)
- {
- self.expanding=!self.isExpanding;
- }
- }
- -(void)quadCurveMenuItemTouchesEnd:(QuadCurveMenuItem*)item
- {
- //excludethe"add"button
- if(item==_addButton)
- {
- return;
- }
- //blowuptheselectedmenubutton
- CAAnimationGroup*blowup=[self_blowupAnimationAtPoint:item.center];
- [item.layeraddAnimation:blowupforKey:@"blowup"];
- item.center=item.startPoint;
- //shrinkothermenubuttons
- for(inti=0;i<[_menusArraycount];i++)
- {
- QuadCurveMenuItem*otherItem=[_menusArrayobjectAtIndex:i];
- CAAnimationGroup*shrink=[self_shrinkAnimationAtPoint:otherItem.center];
- if(otherItem.tag==item.tag){
- continue;
- }
- [otherItem.layeraddAnimation:shrinkforKey:@"shrink"];
- otherItem.center=otherItem.startPoint;
- }
- _expanding=NO;
- //rotate"add"button
- floatangle=self.isExpanding?-M_PI_4:0.0f;
- [UIViewanimateWithDuration:0.2fanimations:^{
- _addButton.transform=CGAffineTransformMakeRotation(angle);
- }];
- if([_delegaterespondsToSelector:@selector(quadCurveMenu:didSelectIndex:)])
- {
- [_delegatequadCurveMenu:selfdidSelectIndex:item.tag-1000];
- }
- }
- #pragmamark-instantmethods
- -(void)setMenusArray:(NSArray*)aMenusArray
- {
- if(aMenusArray==_menusArray)
- {
- return;
- }
- [_menusArrayrelease];
- _menusArray=[aMenusArraycopy];
- //cleansubviews
- for(UIView*vinself.subviews)
- {
- if(v.tag>=1000)
- {
- [vremoveFromSuperview];
- }
- }
- //addthemenubuttons
- intcount=[_menusArraycount];
- for(inti=0;i<count;i++)
- {
- QuadCurveMenuItem*item=[_menusArrayobjectAtIndex:i];
- item.tag=1000+i;
- item.startPoint=_startPoint;
- item.endPoint=CGPointMake(_startPoint.x+ENDRADIUS*sinf(i*M_PI_2/(count-1)),_startPoint.y-ENDRADIUS*cosf(i*M_PI_2/(count-1)));
- item.nearPoint=CGPointMake(_startPoint.x+NEARRADIUS*sinf(i*M_PI_2/(count-1)),_startPoint.y-NEARRADIUS*cosf(i*M_PI_2/(count-1)));
- item.farPoint=CGPointMake(_startPoint.x+FARRADIUS*sinf(i*M_PI_2/(count-1)),_startPoint.y-FARRADIUS*cosf(i*M_PI_2/(count-1)));
- item.center=item.startPoint;
- item.delegate=self;
- [selfaddSubview:item];
- }
- }
- -(BOOL)isExpanding
- {
- return_expanding;
- }
- -(void)setExpanding:(BOOL)expanding
- {
- _expanding=expanding;
- //rotateaddbutton
- floatangle=self.isExpanding?-M_PI_4:0.0f;
- [UIViewanimateWithDuration:0.2fanimations:^{
- _addButton.transform=CGAffineTransformMakeRotation(angle);
- }];
- //expandorcloseanimation
- if(!_timer)
- {
- _flag=self.isExpanding?0:5;
- [email protected](_expand):@selector(_close);
- _timer=[[NSTimerscheduledTimerWithTimeInterval:TIMEOFFSETtarget:selfselector:selectoruserInfo:nilrepeats:YES]retain];
- }
- }
- #pragmamark-privatemethods
- -(void)_expand
- {
- if(_flag==6)
- {
- [_timerinvalidate];
- [_timerrelease];
- _timer=nil;
- return;
- }
- inttag=1000+_flag;
- QuadCurveMenuItem*item=(QuadCurveMenuItem*)[selfviewWithTag:tag];
- CAKeyframeAnimation*rotateAnimation=[CAKeyframeAnimationanimationWithKeyPath:@"transform.rotation.z"];
- rotateAnimation.values=[NSArrayarrayWithObjects:[NSNumbernumberWithFloat:M_PI],[NSNumbernumberWithFloat:0.0f],nil];
- rotateAnimation.duration=0.5f;
- rotateAnimation.keyTimes=[NSArrayarrayWithObjects:
- [NSNumbernumberWithFloat:.3],
- [NSNumbernumberWithFloat:.4],nil];
- CAKeyframeAnimation*positionAnimation=[CAKeyframeAnimationanimationWithKeyPath:@"position"];
- positionAnimation.duration=0.5f;
- CGMutablePathRefpath=CGPathCreateMutable();
- CGPathMoveToPoint(path,NULL,item.startPoint.x,item.startPoint.y);
- CGPathAddLineToPoint(path,NULL,item.farPoint.x,item.farPoint.y);
- CGPathAddLineToPoint(path,NULL,item.nearPoint.x,item.nearPoint.y);
- CGPathAddLineToPoint(path,NULL,item.endPoint.x,item.endPoint.y);
- positionAnimation.path=path;
- CGPathRelease(path);
- CAAnimationGroup*animationgroup=[CAAnimationGroupanimation];
- animationgroup.animations=[NSArrayarrayWithObjects:positionAnimation,rotateAnimation,nil];
- animationgroup.duration=0.5f;
- animationgroup.fillMode=kCAFillModeForwards;
- animationgroup.timingFunction=[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionEaseIn];
- [item.layeraddAnimation:animationgroupforKey:@"Expand"];
- item.center=item.endPoint;
- _flag++;
- }
- -(void)_close
- {
- if(_flag==-1)
- {
- [_timerinvalidate];
- [_timerrelease];
- _timer=nil;
- return;
- }
- inttag=1000+_flag;
- QuadCurveMenuItem*item=(QuadCurveMenuItem*)[selfviewWithTag:tag];
- CAKeyframeAnimation*rotateAnimation=[CAKeyframeAnimationanimationWithKeyPath:@"transform.rotation.z"];
- rotateAnimation.values=[NSArrayarrayWithObjects:[NSNumbernumberWithFloat:0.0f],[NSNumbernumberWithFloat:M_PI*2],[NSNumbernumberWithFloat:0.0f],nil];
- rotateAnimation.duration=0.5f;
- rotateAnimation.keyTimes=[NSArrayarrayWithObjects:
- [NSNumbernumberWithFloat:.0],
- [NSNumbernumberWithFloat:.4],
- [NSNumbernumberWithFloat:.5],nil];
- CAKeyframeAnimation*positionAnimation=[CAKeyframeAnimationanimationWithKeyPath:@"position"];
- positionAnimation.duration=0.5f;
- CGMutablePathRefpath=CGPathCreateMutable();
- CGPathMoveToPoint(path,NULL,item.endPoint.x,item.endPoint.y);
- CGPathAddLineToPoint(path,NULL,item.farPoint.x,item.farPoint.y);
- CGPathAddLineToPoint(path,NULL,item.startPoint.x,item.startPoint.y);
- positionAnimation.path=path;
- CGPathRelease(path);
- CAAnimationGroup*animationgroup=[CAAnimationGroupanimation];
- animationgroup.animations=[NSArrayarrayWithObjects:positionAnimation,rotateAnimation,nil];
- animationgroup.duration=0.5f;
- animationgroup.fillMode=kCAFillModeForwards;
- animationgroup.timingFunction=[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionEaseIn];
- [item.layeraddAnimation:animationgroupforKey:@"Close"];
- item.center=item.startPoint;
- _flag--;
- }
- -(CAAnimationGroup*)_blowupAnimationAtPoint:(CGPoint)p
- {
- CAKeyframeAnimation*positionAnimation=[CAKeyframeAnimationanimationWithKeyPath:@"position"];
- positionAnimation.values=[NSArrayarrayWithObjects:[NSValuevalueWithCGPoint:p],nil];
- positionAnimation.keyTimes=[NSArrayarrayWithObjects:[NSNumbernumberWithFloat:.3],nil];
- CABasicAnimation*scaleAnimation=[CABasicAnimationanimationWithKeyPath:@"transform"];
- scaleAnimation.toValue=[NSValuevalueWithCATransform3D:CATransform3DMakeScale(3,3,1)];
- CABasicAnimation*opacityAnimation=[CABasicAnimationanimationWithKeyPath:@"opacity"];
- opacityAnimation.toValue=[NSNumbernumberWithFloat:0.0f];
- CAAnimationGroup*animationgroup=[CAAnimationGroupanimation];
- animationgroup.animations=[NSArrayarrayWithObjects:positionAnimation,scaleAnimation,opacityAnimation,nil];
- animationgroup.duration=0.3f;
- animationgroup.fillMode=kCAFillModeForwards;
- returnanimationgroup;
- }
- -(CAAnimationGroup*)_shrinkAnimationAtPoint:(CGPoint)p
- {
- CAKeyframeAnimation*positionAnimation=[CAKeyframeAnimationanimationWithKeyPath:@"position"];
- positionAnimation.values=[NSArrayarrayWithObjects:[NSValuevalueWithCGPoint:p],nil];
- positionAnimation.keyTimes=[NSArrayarrayWithObjects:[NSNumbernumberWithFloat:.3],nil];
- CABasicAnimation*scaleAnimation=[CABasicAnimationanimationWithKeyPath:@"transform"];
- scaleAnimation.toValue=[NSValuevalueWithCATransform3D:CATransform3DMakeScale(.01,.01,1)];
- CABasicAnimation*opacityAnimation=[CABasicAnimationanimationWithKeyPath:@"opacity"];
- opacityAnimation.toValue=[NSNumbernumberWithFloat:0.0f];
- CAAnimationGroup*animationgroup=[CAAnimationGroupanimation];
- animationgroup.animations=[NSArrayarrayWithObjects:positionAnimation,scaleAnimation,opacityAnimation,nil];
- animationgroup.duration=0.3f;
- animationgroup.fillMode=kCAFillModeForwards;
- returnanimationgroup;
- }
- @end
运行截图:
DEMO下载地址:http://download.****.net/detail/toss156/4164935