iPhoneリングメニュー

クルクルまわせるメニューボタンを作ってみます。0から7までの8つのボタンを配置して、タップすると画面上にタップした数字の棒を表示するようにしました。


動作イメージ
XcodeからiOS6 iPhone Simulatorで動かすとこんな感じになります。

サンプルコード

#import “ViewController.h”

#import <QuartzCore/QuartzCore.h>

@interface ViewController () {

    UIView *ringMenu;

    NSMutableArray *menuItems;

    float velocity;

    float angle;

    

    UIView *barView;

}

@end

@implementation ViewController

– (void)viewDidLoad

{

    [super viewDidLoad];

    self.view.backgroundColor = [self color:3];

    

    [self createRingMenu];

    [self createMenuItems];

    

    velocity = 1;

    

    [self start];

}

– (void)createRingMenu

{

    ringMenu = [[UIView alloc] initWithFrame:CGRectMake(-140, 10, 280, 280)];

    ringMenu.layer.cornerRadius = 140;

    ringMenu.backgroundColor = [self color:0];

    [self.view addSubview:ringMenu];

    

    CALayer *hole = [CALayer layer];

    hole.frame = CGRectMake(0, 0, 120, 120);

    hole.cornerRadius = 60;

    hole.position = CGPointMake(140, 140);

    hole.backgroundColor = [self.view.backgroundColor CGColor];

    [ringMenu.layer addSublayer:hole];

    

    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(turn:)];

    [ringMenu addGestureRecognizer:pan];

    

    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap:)];

    [ringMenu addGestureRecognizer:tap];

}

– (void)turn:(UIPanGestureRecognizer*)gr

{

    static float startAngel;

    

    // touch & move

    CGPoint p = [gr locationInView:ringMenu];

    if (gr.state == UIGestureRecognizerStateBegan) {

        startAngel = angle + atan2f(p.x140, p.y140);

    } else {

        angle = –atan2f(p.x140, p.y140) + startAngel;

    }

    

    // swipe

    if (gr.state == UIGestureRecognizerStateEnded) {

        CGPoint v = [gr velocityInView:ringMenu];

        velocity = v.y;

    }

}

– (void)tap:(UITapGestureRecognizer*)gr

{

    CGPoint p = [gr locationInView:self.view];

    

    for (UILabel *item in menuItems) {

        if (CGRectContainsPoint(item.frame, p)) {

            item.layer.borderColor = [self color:4].CGColor;

            item.textColor = [self color:4];

            item.transform = CGAffineTransformMakeScale(1.1, 1.1);

            [self showDetail:[item.text intValue]];

        } else {

            item.layer.borderColor = [self color:2].CGColor;

            item.textColor = [self color:3];

            item.transform = CGAffineTransformIdentity;

        }

    }

}

– (void)createMenuItems

{

    menuItems = [[NSMutableArray alloc] init];

    for (int i=0; i<8; i++) {

        UILabel *item = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 40, 40)];

        item.text = [NSString stringWithFormat:@”%d”, i];

        item.textAlignment = NSTextAlignmentCenter;

        item.font = [UIFont fontWithName:@”MarkerFelt-Thin” size:25];

        item.backgroundColor = [UIColor clearColor];

        item.layer.borderColor = [self color:2].CGColor;

        item.layer.borderWidth = 5;

        item.layer.cornerRadius = 4;

        item.textColor = [self color:3];

        

        float x = 100 * cos(M_PI/4.0 * i);

        float y = 100 * sin(M_PI/4.0 * i) + 150;

        item.center = CGPointMake(x, y);

        [self.view addSubview:item];

        

        [menuItems addObject:item];

    }

}

– (void)start

{

    [NSTimer scheduledTimerWithTimeInterval:1.0/60.0 target:self selector:@selector(tick:) userInfo:nil repeats:YES];

}

– (void)tick:(NSTimer*)sender

{

    for (int i=0; i<8; i++) {

        UIView *v = [menuItems objectAtIndex:i];

        float x = 100 * cos(M_PI/4.0 * i + angle);

        float y = 100 * sin(M_PI/4.0 * i + angle) + 150;

        v.center = CGPointMake(x, y);

    }

    

    // turn speed setting

    angle += velocity * 0.00015;

    velocity = velocity * 0.9;

}

– (void)showDetail:(int)count

{

    // init

    [UIView animateWithDuration:0.3 animations:^{

        barView.transform = CGAffineTransformMakeTranslation(568, 0);

    } completion:^(BOOL finished) {

        

        [barView removeFromSuperview];

        barView = [[UIView alloc] initWithFrame:self.view.bounds];

        barView.userInteractionEnabled = NO;

        [self.view addSubview:barView];

        

        for (int i=0; i< count + 1; i++) {

            float w = 50 * i;

            UIView *bar = [[UIView alloc] initWithFrame:CGRectMake(568, 35 * i, w, 30)];

            [barView addSubview:bar];

            bar.backgroundColor = [self color:2];

            

            [self performSelector:@selector(showBar:) withObject:bar afterDelay:0.22 * i];

        }

    }];

}

– (void)showBar:(UIView*)bar

{

    [UIView animateWithDuration:0.2 animations:^{

        bar.transform = CGAffineTransformMakeTranslation(-bar.frame.size.width, 0);

    }];

}

#define UIColorHex(rgbValue) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 green:((float)((rgbValue & 0xFF00) >> 8))/255.0 blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0]

– (UIColor*)color:(int)i

{

    switch (i) {

        case 0:

            return UIColorHex(0xB9BCC4);

        case 1:

            return UIColorHex(0x868C96);

        case 2:

            return UIColorHex(0xEFEBFF);

        case 3:

            return UIColorHex(0x43453B);

        case 4:

            return UIColorHex(0xFF492A);

        default:

            break;

    }

    return nil;

}

– (void)didReceiveMemoryWarning

{

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}

@end