From b85e8ee88f1c9d63913793e6ca3c79574f302122 Mon Sep 17 00:00:00 2001 From: Olive Date: Fri, 8 Apr 2016 13:23:50 +0800 Subject: [PATCH 1/2] 1. support multi-menus; 2. change the function; --- .gitignore | 6 + .../xcdebugger/Breakpoints_v2.xcbkptlist | 5 + SphereMenu/Base.lproj/Main_iPhone.storyboard | 36 +- .../AppIcon.appiconset/Contents.json | 20 + SphereMenu/Images.xcassets/Contents.json | 6 + .../icon-email.imageset/Contents.json | 8 +- .../icon-facebook.imageset/Contents.json | 8 +- .../icon-twitter.imageset/Contents.json | 8 +- .../picked.imageset/Contents.json | 21 + .../picked.imageset/start_selected@2x.png | Bin 0 -> 6543 bytes .../start.imageset/Contents.json | 8 +- SphereMenu/Launch Screen.xib | 5 +- SphereMenu/SphereMenu/SphereMenu.h | 24 +- SphereMenu/SphereMenu/SphereMenu.m | 396 ++++++++++++------ SphereMenu/ViewController.m | 60 ++- 15 files changed, 434 insertions(+), 177 deletions(-) create mode 100644 .gitignore create mode 100644 SphereMenu.xcodeproj/xcuserdata/YH.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist create mode 100644 SphereMenu/Images.xcassets/Contents.json create mode 100644 SphereMenu/Images.xcassets/picked.imageset/Contents.json create mode 100644 SphereMenu/Images.xcassets/picked.imageset/start_selected@2x.png diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..611cf85 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ + +SphereMenu.xcodeproj/project.xcworkspace/xcuserdata/YH.xcuserdatad/UserInterfaceState.xcuserstate + +SphereMenu.xcodeproj/xcuserdata/YH.xcuserdatad/xcschemes/SphereMenu.xcscheme + +SphereMenu.xcodeproj/xcuserdata/YH.xcuserdatad/xcschemes/xcschememanagement.plist diff --git a/SphereMenu.xcodeproj/xcuserdata/YH.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/SphereMenu.xcodeproj/xcuserdata/YH.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist new file mode 100644 index 0000000..fe2b454 --- /dev/null +++ b/SphereMenu.xcodeproj/xcuserdata/YH.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -0,0 +1,5 @@ + + + diff --git a/SphereMenu/Base.lproj/Main_iPhone.storyboard b/SphereMenu/Base.lproj/Main_iPhone.storyboard index ce2c658..ecaa900 100644 --- a/SphereMenu/Base.lproj/Main_iPhone.storyboard +++ b/SphereMenu/Base.lproj/Main_iPhone.storyboard @@ -1,10 +1,11 @@ - + - + + - + @@ -15,16 +16,35 @@ + + + + + + + + + + + - - - - - + + + diff --git a/SphereMenu/Images.xcassets/AppIcon.appiconset/Contents.json b/SphereMenu/Images.xcassets/AppIcon.appiconset/Contents.json index 91bf9c1..eeea76c 100644 --- a/SphereMenu/Images.xcassets/AppIcon.appiconset/Contents.json +++ b/SphereMenu/Images.xcassets/AppIcon.appiconset/Contents.json @@ -5,16 +5,31 @@ "size" : "29x29", "scale" : "2x" }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, { "idiom" : "iphone", "size" : "40x40", "scale" : "2x" }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, { "idiom" : "iphone", "size" : "60x60", "scale" : "2x" }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + }, { "idiom" : "ipad", "size" : "29x29", @@ -44,6 +59,11 @@ "idiom" : "ipad", "size" : "76x76", "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" } ], "info" : { diff --git a/SphereMenu/Images.xcassets/Contents.json b/SphereMenu/Images.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/SphereMenu/Images.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/SphereMenu/Images.xcassets/icon-email.imageset/Contents.json b/SphereMenu/Images.xcassets/icon-email.imageset/Contents.json index 693931a..a0fa129 100644 --- a/SphereMenu/Images.xcassets/icon-email.imageset/Contents.json +++ b/SphereMenu/Images.xcassets/icon-email.imageset/Contents.json @@ -6,8 +6,12 @@ }, { "idiom" : "universal", - "scale" : "2x", - "filename" : "icon-email@2x.png" + "filename" : "icon-email@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" } ], "info" : { diff --git a/SphereMenu/Images.xcassets/icon-facebook.imageset/Contents.json b/SphereMenu/Images.xcassets/icon-facebook.imageset/Contents.json index 6d932b5..3a7244e 100644 --- a/SphereMenu/Images.xcassets/icon-facebook.imageset/Contents.json +++ b/SphereMenu/Images.xcassets/icon-facebook.imageset/Contents.json @@ -6,8 +6,12 @@ }, { "idiom" : "universal", - "scale" : "2x", - "filename" : "icon-facebook@2x.png" + "filename" : "icon-facebook@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" } ], "info" : { diff --git a/SphereMenu/Images.xcassets/icon-twitter.imageset/Contents.json b/SphereMenu/Images.xcassets/icon-twitter.imageset/Contents.json index 9c0072c..1ae5211 100644 --- a/SphereMenu/Images.xcassets/icon-twitter.imageset/Contents.json +++ b/SphereMenu/Images.xcassets/icon-twitter.imageset/Contents.json @@ -6,8 +6,12 @@ }, { "idiom" : "universal", - "scale" : "2x", - "filename" : "icon-twitter@2x.png" + "filename" : "icon-twitter@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" } ], "info" : { diff --git a/SphereMenu/Images.xcassets/picked.imageset/Contents.json b/SphereMenu/Images.xcassets/picked.imageset/Contents.json new file mode 100644 index 0000000..4d5649d --- /dev/null +++ b/SphereMenu/Images.xcassets/picked.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "start_selected@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/SphereMenu/Images.xcassets/picked.imageset/start_selected@2x.png b/SphereMenu/Images.xcassets/picked.imageset/start_selected@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..739931a81c7dbd46fa4ad31d8531e8f0f0df943f GIT binary patch literal 6543 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 literal 0 HcmV?d00001 diff --git a/SphereMenu/Images.xcassets/start.imageset/Contents.json b/SphereMenu/Images.xcassets/start.imageset/Contents.json index 4244c00..5b01f6b 100644 --- a/SphereMenu/Images.xcassets/start.imageset/Contents.json +++ b/SphereMenu/Images.xcassets/start.imageset/Contents.json @@ -6,8 +6,12 @@ }, { "idiom" : "universal", - "scale" : "2x", - "filename" : "start@2x.png" + "filename" : "start@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" } ], "info" : { diff --git a/SphereMenu/Launch Screen.xib b/SphereMenu/Launch Screen.xib index ba322fc..7556d9f 100644 --- a/SphereMenu/Launch Screen.xib +++ b/SphereMenu/Launch Screen.xib @@ -1,7 +1,8 @@ - + - + + diff --git a/SphereMenu/SphereMenu/SphereMenu.h b/SphereMenu/SphereMenu/SphereMenu.h index e2e362d..93e5a1d 100644 --- a/SphereMenu/SphereMenu/SphereMenu.h +++ b/SphereMenu/SphereMenu/SphereMenu.h @@ -2,29 +2,21 @@ // SphereMenu.h // SphereMenu // -// Created by Tu You on 14-8-24. -// Copyright (c) 2014年 TU YOU. All rights reserved. -// #import -@protocol SphereMenuDelegate - -- (void)sphereDidSelected:(int)index; - -@end -@interface SphereMenu : UIView +typedef void (^SpherePickedMenu)(NSInteger index, UIView *menu); -- (instancetype)initWithStartPoint:(CGPoint)startPoint - startImage:(UIImage *)startImage - submenuImages:(NSArray *)images; +#define key_sphere_menu_image @"img" +#define key_sphere_menu_title @"title" -@property (nonatomic, weak) id delegate; -@property (nonatomic, assign) CGFloat angle; -@property (nonatomic, assign) CGFloat sphereDamping; -@property (nonatomic, assign) CGFloat sphereLength; +@interface SphereMenu : UIView ++ (instancetype)showSphereMenuWithAnchorView:(UIView *)anchorView + anchorImage:(UIImage *)anchorImg + sphereMenus:(NSArray *(^)())menus + pickedMenu:(SpherePickedMenu)completion; @end diff --git a/SphereMenu/SphereMenu/SphereMenu.m b/SphereMenu/SphereMenu/SphereMenu.m index 334f9dc..101fbe5 100644 --- a/SphereMenu/SphereMenu/SphereMenu.m +++ b/SphereMenu/SphereMenu/SphereMenu.m @@ -2,22 +2,63 @@ // SphereMenu.m // SphereMenu // -// Created by Tu You on 14-8-24. -// Copyright (c) 2014年 TU YOU. All rights reserved. -// #import "SphereMenu.h" -static const int kItemInitTag = 1001; static const CGFloat kAngleOffset = M_PI_2 / 2; -static const CGFloat kSphereLength = 80; +static const CGFloat kSphereLength = 150; static const float kSphereDamping = 0.3; -@interface SphereMenu () -@property (nonatomic, assign) NSUInteger count ; -@property (nonatomic, strong) UIImageView *start; -@property (nonatomic, strong) NSArray *images; + +@protocol SphereModelViewDelegate + +@optional +- (void)modelMenuViewDidTouchEnd:(id)menuView; + +@end + + +@interface SphereModelView : UIView + +@property (nonatomic) id delegate; + +@end + + +@implementation SphereModelView + +- (id)initWithFrame:(CGRect)frame +{ + self = [super initWithFrame:frame]; + if (self) { + + self.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.3]; + } + + return self; +} + +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event +{ + if ([self.delegate respondsToSelector:@selector(modelMenuViewDidTouchEnd:)]) { + + [self.delegate modelMenuViewDidTouchEnd:self]; + } +} + +@end + + + + +@interface SphereMenu () + + +@property (nonatomic, assign) CGFloat angle; +@property (nonatomic, assign) CGFloat sphereDamping; +@property (nonatomic, assign) CGFloat sphereLength; + @property (nonatomic, strong) NSMutableArray *items; @property (nonatomic, strong) NSMutableArray *positions; @@ -27,63 +68,190 @@ @interface SphereMenu () @property (nonatomic, strong) UIDynamicItemBehavior *itemBehavior; @property (nonatomic, strong) NSMutableArray *snaps; -@property (nonatomic, strong) UITapGestureRecognizer *tapOnStart; - @property (nonatomic, strong) id bumper; @property (nonatomic, assign) BOOL expanded; + + +// -- add by Olive + +@property (nonatomic, strong) UIView *anchorView; + +@property (nonatomic, strong) UIImage *normalImage; + +@property (nonatomic, strong) UIButton *anchorBtn; + +@property (nonatomic, strong) SphereModelView *modelView; + +@property (nonatomic, strong) NSArray *menusViewArray; + +@property (nonatomic, strong) SpherePickedMenu pickedCompletion; + +// -- end by Olive + @end @implementation SphereMenu -- (instancetype)initWithStartPoint:(CGPoint)startPoint startImage:(UIImage *)startImage submenuImages:(NSArray *)images + ++ (instancetype)showSphereMenuWithAnchorView:(UIView *)anchorView + anchorImage:(UIImage *)anchorImg + sphereMenus:(NSArray *(^)())menus + pickedMenu:(SpherePickedMenu)completion { - if (self = [super init]) { - - self.bounds = CGRectMake(0, 0, startImage.size.width, startImage.size.height); - self.center = startPoint; + SphereMenu *menu = [[SphereMenu alloc] init]; + menu.menusViewArray = menus(); + menu.anchorView = anchorView; + menu.pickedCompletion = completion; + + menu.normalImage = anchorImg; + + [menu show]; + + + return menu; +} + +- (instancetype)initWithFrame:(CGRect)frame +{ + self = [super initWithFrame:frame]; + if (self) { _angle = kAngleOffset; _sphereLength = kSphereLength; _sphereDamping = kSphereDamping; - - _images = images; - _count = self.images.count; - _start = [[UIImageView alloc] initWithImage:startImage]; - _start.userInteractionEnabled = YES; - _tapOnStart = [[UITapGestureRecognizer alloc] initWithTarget:self - action:@selector(startTapped:)]; - [_start addGestureRecognizer:_tapOnStart]; - [self addSubview:_start]; } + return self; } +- (UIWindow *)window +{ + return [[UIApplication sharedApplication] keyWindow]; +} + +- (SphereModelView *)modelView +{ + if (!_modelView) { + + _modelView = [[SphereModelView alloc] initWithFrame:self.window.bounds]; + _modelView.delegate = self; + } + + return _modelView; +} + +- (void)show +{ + //self.anchorView.hidden = YES; + + _angle = M_PI / (self.menusViewArray.count+1); + + [self.window addSubview:self.modelView]; + + self.modelView.frame = CGRectMake(0, self.modelView.bounds.size.height, self.modelView.bounds.size.width, 0); + [UIView animateWithDuration:_sphereDamping + animations:^{ + + self.modelView.frame = self.window.bounds; + } + completion:^(BOOL finished) { + + + }]; + + //NSLog(@"anchor ori frame = %@", NSStringFromCGRect(self.anchorView.frame)); + CGRect rect = [self.anchorView.superview convertRect:self.anchorView.frame toView:self.window]; + //NSLog(@"rect = %@", NSStringFromCGRect(rect)); + + self.frame = rect; + + + UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom]; + btn.frame = self.bounds; + [btn setImage:self.normalImage forState:UIControlStateNormal]; + [btn addTarget:self action:@selector(anchorBtnAction:) forControlEvents:UIControlEventTouchUpInside]; + [self addSubview:btn]; + + [self.window addSubview:self]; + + + [self commonSetup]; + + [self expandSubmenu]; +} + +#pragma mark -Action +- (void)anchorBtnAction:(UIButton *)sender +{ + [self shrinkSubmenu:^{ + + }]; +} + +- (void)menuItemPickedAction:(UIControl *)sender +{ + [self shrinkSubmenu:^{ + + if (self.pickedCompletion) { + + NSInteger i = sender.tag; + self.pickedCompletion(i, sender); + } + }]; +} + +#pragma mark -Private Methods +#define SPHERE_TITLE_LABEL_HEIGHT 30 - (void)commonSetup { self.items = [NSMutableArray array]; self.positions = [NSMutableArray array]; self.snaps = [NSMutableArray array]; + CGRect rect = CGRectZero; + + NSInteger count = self.menusViewArray.count; // setup the items - for (int i = 0; i < self.count; i++) { - UIImageView *item = [[UIImageView alloc] initWithImage:self.images[i]]; - item.tag = kItemInitTag + i; - item.userInteractionEnabled = YES; - [self.superview addSubview:item]; + for (int i = 0; i < count; i++) { - CGPoint position = [self centerForSphereAtIndex:i]; - item.center = self.center; - [self.positions addObject:[NSValue valueWithCGPoint:position]]; + UIImage *img = self.menusViewArray[i][key_sphere_menu_image]; + NSString *title = self.menusViewArray[i][key_sphere_menu_title]; + + rect.size.width = img.size.width; + rect.size.height = img.size.height + SPHERE_TITLE_LABEL_HEIGHT; - UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapped:)]; - [item addGestureRecognizer:tap]; + UIControl *view = [[UIControl alloc] initWithFrame:rect]; + view.tag = i; + view.backgroundColor = [UIColor clearColor]; + [view addTarget:self action:@selector(menuItemPickedAction:) forControlEvents:UIControlEventTouchUpInside]; - UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panned:)]; - [item addGestureRecognizer:pan]; + UIImageView *imgView = [[UIImageView alloc] initWithImage:img]; + imgView.frame = CGRectMake(0, 0, img.size.width, img.size.height); + [view addSubview:imgView]; - [self.items addObject:item]; + UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, img.size.height, img.size.width, SPHERE_TITLE_LABEL_HEIGHT)]; + label.backgroundColor = [UIColor clearColor]; + label.text = title; + label.font = [UIFont systemFontOfSize:11]; + label.textAlignment = NSTextAlignmentCenter; + label.textColor = [UIColor whiteColor]; +// label.adjustsFontSizeToFitWidth = YES; + [view addSubview:label]; + + view.center = self.center; + + [self.superview addSubview:view]; + + CGPoint position = [self centerForSphereAtIndex:i]; + view.center = self.center; + [self.positions addObject:[NSValue valueWithCGPoint:position]]; + + // UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panned:)]; + // [view addGestureRecognizer:pan]; + + [self.items addObject:view]; } [self.superview bringSubviewToFront:self]; @@ -95,7 +263,7 @@ - (void)commonSetup self.collision.translatesReferenceBoundsIntoBoundary = YES; self.collision.collisionDelegate = self; - for (int i = 0; i < self.count; i++) { + for (int i = 0; i < count; i++) { UISnapBehavior *snap = [[UISnapBehavior alloc] initWithItem:self.items[i] snapToPoint:self.center]; snap.damping = self.sphereDamping; [self.snaps addObject:snap]; @@ -111,111 +279,83 @@ - (void)commonSetup self.itemBehavior.friction = 0.5; } -- (void)didMoveToSuperview +- (void)removeAllSubViews:(void (^)())completion { - [self commonSetup]; -} - -- (void)removeFromSuperview -{ - for (int i = 0; i < self.count; i++) { - [self.items[i] removeFromSuperview]; - } - - [super removeFromSuperview]; + [UIView animateWithDuration:_sphereDamping + animations:^{ + + self.modelView.frame = CGRectMake(0, self.modelView.bounds.size.height, self.modelView.bounds.size.width, 0); + } + completion:^(BOOL finished) { + + [self.modelView removeFromSuperview]; + + for (UIView *view in self.items) { + [view removeFromSuperview]; + } + [self removeFromSuperview]; + + completion(); + }]; } - (CGPoint)centerForSphereAtIndex:(int)index { - CGFloat firstAngle = M_PI + (M_PI_2 - self.angle) + index * self.angle; + CGFloat cosAngle = 0; + if (index*self.angle > M_PI_4) + cosAngle = M_PI - (index+1)*self.angle; + else + cosAngle = M_PI_2 + (M_PI_2 - (index+1)*self.angle); + + CGFloat sinAngle = (index+1)*self.angle; + +// CGFloat firstAngle = M_PI + (M_PI_4 - self.angle) + index * self.angle; CGPoint startPoint = self.center; - CGFloat x = startPoint.x + cos(firstAngle) * self.sphereLength; - CGFloat y = startPoint.y + sin(firstAngle) * self.sphereLength; + CGFloat x = startPoint.x + cos(cosAngle) * self.sphereLength; + //NSLog(@"start x = %f, index = %d, x = %f", startPoint.x, index, x); + CGFloat y = startPoint.y - sin(sinAngle) * self.sphereLength; + //NSLog(@"start y = %f, index = %d, y = %f", startPoint.y, index, y); CGPoint position = CGPointMake(x, y); return position; } -- (void)tapped:(UITapGestureRecognizer *)gesture -{ - if ([self.delegate respondsToSelector:@selector(sphereDidSelected:)]) { - int tag = (int)gesture.view.tag; - tag -= kItemInitTag; - [self.delegate sphereDidSelected:tag]; - } - - [self shrinkSubmenu]; -} - -- (void)startTapped:(UITapGestureRecognizer *)gesture -{ - [self.animator removeBehavior:self.collision]; - [self.animator removeBehavior:self.itemBehavior]; - [self removeSnapBehaviors]; - - if (self.expanded) { - [self shrinkSubmenu]; - } else { - [self expandSubmenu]; - } -} - +// TODO: --展开menu - (void)expandSubmenu { - for (int i = 0; i < self.count; i++) { + for (int i = 0; i < self.items.count; i++) { [self snapToPostionsWithIndex:i]; } self.expanded = YES; } -- (void)shrinkSubmenu +- (void)snapToPostionsWithIndex:(NSUInteger)index +{ + id positionValue = self.positions[index]; + CGPoint position = [positionValue CGPointValue]; + UISnapBehavior *snap = [[UISnapBehavior alloc] initWithItem:self.items[index] snapToPoint:position]; + snap.damping = self.sphereDamping; + UISnapBehavior *snapToRemove = self.snaps[index]; + self.snaps[index] = snap; + [self.animator removeBehavior:snapToRemove]; + [self.animator addBehavior:snap]; +} + +// TODO: --关闭menu +- (void)shrinkSubmenu:(void (^)())completion { [self.animator removeBehavior:self.collision]; - for (int i = 0; i < self.count; i++) { + for (int i = 0; i < self.items.count; i++) { [self snapToStartWithIndex:i]; } - self.expanded = NO; -} - -- (void)panned:(UIPanGestureRecognizer *)gesture -{ - UIView *touchedView = gesture.view; - if (gesture.state == UIGestureRecognizerStateBegan) { - [self.animator removeBehavior:self.itemBehavior]; - [self.animator removeBehavior:self.collision]; - [self removeSnapBehaviors]; - } else if (gesture.state == UIGestureRecognizerStateChanged) { - touchedView.center = [gesture locationInView:self.superview]; - } else if (gesture.state == UIGestureRecognizerStateEnded) { - self.bumper = touchedView; - [self.animator addBehavior:self.collision]; - NSUInteger index = [self.items indexOfObject:touchedView]; - - if (index != NSNotFound) { - [self snapToPostionsWithIndex:index]; - } - } -} - -- (void)collisionBehavior:(UICollisionBehavior *)behavior endedContactForItem:(id)item1 withItem:(id)item2 -{ - [self.animator addBehavior:self.itemBehavior]; - if (item1 != self.bumper) { - NSUInteger index = (int)[self.items indexOfObject:item1]; - if (index != NSNotFound) { - [self snapToPostionsWithIndex:index]; - } - } - if (item2 != self.bumper) { - NSUInteger index = (int)[self.items indexOfObject:item2]; - if (index != NSNotFound) { - [self snapToPostionsWithIndex:index]; - } - } + [self removeAllSubViews:^{ + + completion(); + }]; } - (void)snapToStartWithIndex:(NSUInteger)index @@ -228,18 +368,6 @@ - (void)snapToStartWithIndex:(NSUInteger)index [self.animator addBehavior:snap]; } -- (void)snapToPostionsWithIndex:(NSUInteger)index -{ - id positionValue = self.positions[index]; - CGPoint position = [positionValue CGPointValue]; - UISnapBehavior *snap = [[UISnapBehavior alloc] initWithItem:self.items[index] snapToPoint:position]; - snap.damping = self.sphereDamping; - UISnapBehavior *snapToRemove = self.snaps[index]; - self.snaps[index] = snap; - [self.animator removeBehavior:snapToRemove]; - [self.animator addBehavior:snap]; -} - - (void)removeSnapBehaviors { [self.snaps enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { @@ -247,4 +375,12 @@ - (void)removeSnapBehaviors }]; } +#pragma mark -SphereModelViewDelegate +- (void)modelMenuViewDidTouchEnd:(id)menuView +{ + [self shrinkSubmenu:^{ + + }]; +} + @end diff --git a/SphereMenu/ViewController.m b/SphereMenu/ViewController.m index ea54b1b..b63111a 100644 --- a/SphereMenu/ViewController.m +++ b/SphereMenu/ViewController.m @@ -9,7 +9,9 @@ #import "ViewController.h" #import "SphereMenu.h" -@interface ViewController () +@interface ViewController () + +@property (nonatomic, weak) IBOutlet UIButton *btn; @end @@ -21,18 +23,18 @@ - (void)viewDidLoad self.view.backgroundColor = [UIColor colorWithRed:1 green:0.58 blue:0.27 alpha:1]; - UIImage *startImage = [UIImage imageNamed:@"start"]; - UIImage *image1 = [UIImage imageNamed:@"icon-twitter"]; - UIImage *image2 = [UIImage imageNamed:@"icon-email"]; - UIImage *image3 = [UIImage imageNamed:@"icon-facebook"]; - NSArray *images = @[image1, image2, image3]; - SphereMenu *sphereMenu = [[SphereMenu alloc] initWithStartPoint:CGPointMake(CGRectGetWidth(self.view.frame) / 2, 320) - startImage:startImage - submenuImages:images]; - sphereMenu.sphereDamping = 0.3; - sphereMenu.sphereLength = 85; - sphereMenu.delegate = self; - [self.view addSubview:sphereMenu]; +// UIImage *startImage = [UIImage imageNamed:@"start"]; +// UIImage *image1 = [UIImage imageNamed:@"icon-twitter"]; +// UIImage *image2 = [UIImage imageNamed:@"icon-email"]; +// UIImage *image3 = [UIImage imageNamed:@"icon-facebook"]; +// NSArray *images = @[image1, image2, image3]; +// SphereMenu *sphereMenu = [[SphereMenu alloc] initWithStartPoint:CGPointMake(CGRectGetWidth(self.view.frame) / 2, 320) +// startImage:startImage +// submenuImages:images]; +// sphereMenu.sphereDamping = 0.3; +// sphereMenu.sphereLength = 85; +// sphereMenu.delegate = self; +// [self.view addSubview:sphereMenu]; } - (void)sphereDidSelected:(int)index @@ -50,4 +52,36 @@ - (UIStatusBarStyle)preferredStatusBarStyle return UIStatusBarStyleLightContent; } +- (IBAction)startBtnAction:(id)sender +{ + [SphereMenu showSphereMenuWithAnchorView:self.btn + anchorImage:[UIImage imageNamed:@"picked"] + sphereMenus:^NSArray *{ + + UIImage *image1 = [UIImage imageNamed:@"icon-twitter"]; + UIImage *image2 = [UIImage imageNamed:@"icon-email"]; + UIImage *image3 = [UIImage imageNamed:@"icon-facebook"]; + + UIImage *image4 = [UIImage imageNamed:@"icon-twitter"]; + UIImage *image5 = [UIImage imageNamed:@"icon-email"]; + UIImage *image6 = [UIImage imageNamed:@"icon-facebook"]; + + NSArray *images = @[@{key_sphere_menu_image:image1, key_sphere_menu_title:@"我想买"}, + @{key_sphere_menu_image:image2, key_sphere_menu_title:@"大规模有"}, + @{key_sphere_menu_image:image3, key_sphere_menu_title:@"暗黑破神"}, + @{key_sphere_menu_image:image4, key_sphere_menu_title:@"大规木有"}, + @{key_sphere_menu_image:image5, key_sphere_menu_title:@"大规木有"}, + @{key_sphere_menu_image:image6, key_sphere_menu_title:@"模有木有"}]; + + return images; + } + pickedMenu:^(NSInteger index, UIView *menu) { + + NSLog(@"picked index = %ld", index); + }]; + + + +} + @end From 870cfaee01eb0880f835a1f0178950367811c5b0 Mon Sep 17 00:00:00 2001 From: Olive Date: Fri, 8 Apr 2016 13:27:47 +0800 Subject: [PATCH 2/2] update readme --- README.md | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 2d84794..97a665d 100644 --- a/README.md +++ b/README.md @@ -6,14 +6,31 @@ SphereMenu is a fun menu powered by `UIDynamicAnimator`. Inspired by [Sphere](ht To use SpereMenu, create a `SpereMenu` like this ```objective-c -UIImage *startImage = [UIImage imageNamed:@"start"]; +[SphereMenu showSphereMenuWithAnchorView:self.btn +anchorImage:[UIImage imageNamed:@"picked"] +sphereMenus:^NSArray *{ + UIImage *image1 = [UIImage imageNamed:@"icon-twitter"]; UIImage *image2 = [UIImage imageNamed:@"icon-email"]; UIImage *image3 = [UIImage imageNamed:@"icon-facebook"]; -NSArray *images = @[image1, image2, image3]; -SphereMenu *sphereMenu = [[SphereMenu alloc] initWithStartPoint:CGPointMake(160, 320) startImage:startImage submenuImages:images]; -sphereMenu.delegate = self; -[self.view addSubview:sphereMenu]; + +UIImage *image4 = [UIImage imageNamed:@"icon-twitter"]; +UIImage *image5 = [UIImage imageNamed:@"icon-email"]; +UIImage *image6 = [UIImage imageNamed:@"icon-facebook"]; + +NSArray *images = @[@{key_sphere_menu_image:image1, key_sphere_menu_title:@"我想买"}, +@{key_sphere_menu_image:image2, key_sphere_menu_title:@"大规模有"}, +@{key_sphere_menu_image:image3, key_sphere_menu_title:@"暗黑破神"}, +@{key_sphere_menu_image:image4, key_sphere_menu_title:@"大规木有"}, +@{key_sphere_menu_image:image5, key_sphere_menu_title:@"大规木有"}, +@{key_sphere_menu_image:image6, key_sphere_menu_title:@"模有木有"}]; + +return images; +} +pickedMenu:^(NSInteger index, UIView *menu) { + +NSLog(@"picked index = %ld", index); +}]; ``` ## A Quick Peek