ダイアル式の鍵に使えそうなかんじで作ってみた。

(XcodeのiOS6 Simulatorで試しています。)

ポイント

・x軸周りにViewを回転させることで、ダイアルっぽくする

・presentationLayerの現在のrotationを取得してダイアルの数字を取得する

サンプルコード

#import “ViewController.h”

#import <QuartzCore/QuartzCore.h>

@interface ViewController () 

@property (nonatomic, strong) UIView *dial;

@end

@implementation ViewController

@synthesize dial;

– (void)viewDidLoad

{

    [super viewDidLoad];

    

    // 奥行きを設定

    [self setBaseView];

    

    // ダイアル

    dial = [self createDial];

    dial.center = CGPointMake(180, 300);

    [self.view addSubview:dial];

    

    

    // check box

    UILabel *box = [[UILabel alloc] initWithFrame:CGRectMake(10, 400, 300, 50)];

    box.text = @”?”;

    box.textAlignment = 1; //center

    box.backgroundColor = [UIColor yellowColor];

    box.layer.cornerRadius = 20.0;

    box.userInteractionEnabled = YES;

    [self.view addSubview:box];

    

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

    [box addGestureRecognizer:tap];

    

}

– (void)setBaseView

{

    CATransform3D theTransform = self.view.layer.sublayerTransform;

    theTransform.m34 = 1.0 / 100;

    self.view.layer.sublayerTransform = theTransform;

}

– (UIView*)createDial

{

    UIView *v = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 120, 150)];

    

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

        UIView *ring = [self createRing];

        ring.center = CGPointMake(i*40, 150);

        UIPanGestureRecognizer *gr = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(slide:)];

        [ring addGestureRecognizer:gr];

        

        [v addSubview:ring];

        

    }

    

    return v;

}

– (UIView *)createRing

{

    // 結構、heightを大きくとらないと、pan gestureの範囲に入らない。。

    UIView *ring = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 30, 300)];

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

        // y を実際にダイアルをまわしてgestureが反応する位置に調整した。

        UILabel *panel = [[UILabel alloc] initWithFrame:CGRectMake(0, 60, 30, 40)];

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

        panel.textAlignment = 1; // center

        panel.font = [UIFont boldSystemFontOfSize:30];

        panel.textColor = [UIColor whiteColor];

        panel.backgroundColor = [UIColor blackColor];

        

        CATransform3D trans = CATransform3DIdentity;

        float rotate = i * (M_PI / 5.0);

        panel.layer.anchorPointZ = –60.0;

        trans = CATransform3DRotate(trans, rotate, 1.0f, 0.0, 0.0);

        panel.layer.transform = trans;

        panel.layer.borderWidth = 2.0;

        panel.layer.borderColor = [UIColor darkGrayColor].CGColor;

        

        [ring addSubview:panel];

    }

    

    return ring;

}

– (void)slide:(UIPanGestureRecognizer*)gr

{

    static NSMutableArray *origin;

    if (!origin) {

        origin = [[NSMutableArray alloc] init];

    }

    

    if (gr.state == UIGestureRecognizerStateBegan) {

        [origin removeAllObjects];

        for (UIView *v in gr.view.subviews) {

            [origin addObject:[NSValue valueWithCATransform3D:v.layer.transform]];

        }

    }

    

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

    

    // ダイアルの回転

    int value = p.y / 10;

    float rotate = – (M_PI / 20.0) * value;

    for (int i=0; i<[gr.view.subviews count]; i++) {

        UIView *v = [gr.view.subviews objectAtIndex:i];

        v.layer.transform = CATransform3DRotate([[origin objectAtIndex:i] CATransform3DValue], rotate, 1.0f, 0, 0);

    }

    

}

– (void)check:(UITapGestureRecognizer*)gr

{

    NSMutableArray *numbers = [[NSMutableArray alloc] init];

    

    for(UIView *ring in self.dial.subviews) {

        for (UIView *panel in ring.subviews) {

            

            // 一番前に来ている数字をゲット

            CALayer *layer = panel.layer.presentationLayer;

            float currentAngle = [[layer valueForKeyPath:@”transform.rotation.x”] floatValue];

            if (fabs(currentAngle) < 0.001f) {

                [numbers addObject:((UILabel*)panel).text];

            }

        }

    }

    

    // 3桁の数字に

    ((UILabel*)gr.view).text = [numbers componentsJoinedByString:@””];

}

– (void)didReceiveMemoryWarning

{

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}

@end