ダイアル式の鍵に使えそうなかんじで作ってみた。
(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