LoginSignup
22
20

More than 5 years have passed since last update.

タイル状のUIViewを動かしてみる

Last updated at Posted at 2013-01-19

Letterpressという英単語陣取りゲームがおもしろいです。
こんな風な「タイルのドラッグ移動」をやったこと無かったので試し書きしてみました。

ZEViewController

#import "ZEViewController.h"
#import <QuartzCore/QuartzCore.h> // layer.shadowXXXを使うために。

@interface ZEViewController ()

@end

@implementation ZEViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    // 25個のUILabelを作る
    NSMutableArray *tiles = [NSMutableArray array];
    for( int i=0; i<25; i++ ){
        float tileSize = self.view.bounds.size.width/5;
        int indexX = i%5;      // 横方向 0-4
        int indexY = (int)i/5; // 縦方向 0-4
        float centerX = tileSize*indexX+(tileSize/2);
        float centerY = tileSize*indexY+(tileSize/2);

        UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(0,0, tileSize,tileSize)];
        label.center=CGPointMake(centerX,centerY);
        label.textAlignment=NSTextAlignmentCenter;
        label.text=[NSString stringWithFormat:@"%d",i];
        if( i%2 == 0 ){
            label.backgroundColor = [UIColor whiteColor];
        }else{
            label.backgroundColor = [UIColor grayColor];
        }
        [tiles addObject:label];
        [self.view addSubview:label];

        // ホールドした際の挙動
        label.userInteractionEnabled = YES;
        UIPanGestureRecognizer* panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGesture:)];
        [label addGestureRecognizer:panGesture];

    }
    //
}
- (void) handlePanGesture:(UIPanGestureRecognizer*) sender {
    UIPanGestureRecognizer* pan = (UIPanGestureRecognizer*) sender;
    UILabel *label = (UILabel *)pan.view;
    CGPoint location = [pan translationInView:label];
    NSLog(@"pan x=%f, y=%f", location.x, location.y);
    if ([sender state] == UIGestureRecognizerStateEnded){
        // 指を放したとき
        CGContextRef context = UIGraphicsGetCurrentContext();
        [UIView beginAnimations:nil context:context];
        // 元の場所に移動
        int i = [label.text intValue];
        float tileSize = self.view.bounds.size.width/5;
        int indexX = i%5;      // 横方向 0-4
        int indexY = (int)i/5; // 縦方向 0-4
        float centerX = tileSize*indexX+(tileSize/2);
        float centerY = tileSize*indexY+(tileSize/2);
        label.center = CGPointMake(centerX,centerY);
        // 影を隠す
        label.clipsToBounds=YES;
        // 元のサイズに戻す
        label.transform = CGAffineTransformIdentity;
        [UIView commitAnimations];

    }else{
        // 前面に持ってくる
        [self.view bringSubviewToFront:label];
        // ちょっと大きくする&傾ける
        label.transform = CGAffineTransformMakeScale(1.3, 1.3);
//        label.transform = CGAffineTransformMakeRotation(M_PI*10.0/360.0);
        // ↑ここをコメントアウトすると、拡大しなくなる
        // 影を付ける
        label.clipsToBounds=NO;
        CALayer *layer = label.layer;
        layer.shadowRadius = 3;
        layer.shadowColor = [UIColor blackColor].CGColor;
        layer.shadowOpacity = 0.5;
        layer.shadowOffset = CGSizeMake(10, 10);
        // めちゃくちゃ速くなるらしい方法
        // http://7gano.tumblr.com/post/4379956470/calayer-shadow
//        layer.shadowPath = [UIBezierPath bezierPathWithRect:self.bounds].CGPath;
        // UIViewを移動
        double x = sender.view.center.x + location.x;
        double y = sender.view.center.y + location.y;
        sender.view.center=CGPointMake(x, y);
        [pan setTranslation:CGPointZero inView:label];
    }
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end
  • layer.shadowXXXをそのまま使うと遅いらしい。このサンプル程度だと違いは分からない。
  • -label.transformに複数の値を渡していて、後の値で上書きしているように見えてるけど、setterの中で値を個別に持っていれば問題ないのだろう、けど紛らわしい。- ここ間違い。後の値で上書きされている。

youtube

22
20
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
20