LoginSignup
55
54

More than 5 years have passed since last update.

AutoLayoutでアニメーションを設定する方法(Objective-C版)

Last updated at Posted at 2014-09-29

最近までxibのAutoLayoutの設定をしておらず、アニメーションを座標指定で動かしていました。
iPhone6/Plusが出てAutoLayoutの設定をするためようやく Use AutoLayoutにチェックを入れたのですが、座標指定のアニメーションがうまく動かなくなりました。

そこでAutoLayoutの制約を付けたり外したりする方法でアニメーションを設定しました。

以前のアニメーション

例えばsampleViewという名前のビューを(endX,endY)の位置にアニメーションで動かしたい場合


    CGRect rect = CGRectMake(endX,
                             endY,
                             sampleView.frame.size.width,
                             sampleView.frame.size.height);
    CGContextRef context = UIGraphicsGetCurrentContext();
    [UIView beginAnimations:nil context:context];
    [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
    [UIView setAnimationDelay:0.2];
    [UIView setAnimationDuration:0.5];
    sampleView.frame = rect;
    [UIView setAnimationDelegate:self];
    [UIView commitAnimations];

このアニメーションではxibにAutoLayoutを施すと、移動したあとにsampleViewにAutoLayoutが働いて
元に戻ったりします。原因は、AutoLayoutがxib上に設定されるタイミングが、viewWillAppearであるためで、この後にアニメーションを設定するという方法もあるのですが、今回はAutoLayoutの作用のみでアニメーションを設定します。

AutoLayoutを用いたアニメーション

AutoLayoutの制約を外し、別の制約を付ける、という手段で位置を変更することにします。
まずはsampleViewに制約をInterfaceBuilderで追加します。ここでは直上のsampleLabelというビューに隙間0の制約を定義しました。
この制約をソースファイルに接続して定義しておきます。また追加する制約をコードで宣言しておきます。


@property (strong, nonatomic) IBOutlet NSLayoutConstraint *sampleViewTopZeroConstraint;
@property (nonatomic) NSLayoutConstraint *sampleViewTopConstraint;

新たに宣言した制約をセットします


    //ビューを列挙型に格納
    NSDictionary* views = [NSDictionary dictionaryWithObjectsAndKeys:
                           self.sampleView, @"sampleView",
                           self.sampleLabel, @"sampleLabel",
                           nil];
    //制約の数値をセット
    NSNumber *padding = sampleView.frame.size.height / 2;
    NSDictionary *metricsDictionary = NSDictionaryOfVariableBindings(padding);

    //sampleLabelの下部とsampleViewの上部の間をsampleViewの高さの1/2に設定
    self.sampleViewTopConstraint = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[sampleLabel]-padding-[sampleView]" 
                                                                         options:0
                                                                         metrics:metricsDictionary
                                                                           views:views];

あとは元々の制約を外し、新たにセットした制約に置き換えるだけです。


    //ネームラベルとの隙間ゼロの制約を外す
    [self.view removeConstraint:self.sampleViewTopZeroConstraint];
    //新しい制約を追加
    [self.view addConstraint:self.sampleViewTopConstraint];

    //アニメーション開始
    [UIView animateWithDuration:0.5
                          delay:0.2
                        options:UIViewAnimationCurveEaseInOut
                     animations:^{
                         [self.view layoutIfNeeded]; } 
                     completion:nil];

ここでlayoutIfNeeded を入れないと、アニメーションで位置が変更されません。
これでsampleLabelと接していたsampleViewが下に動きます。

もとに戻すときは、removeConstraint:addConstraint:を入れ替えれば大丈夫です。

55
54
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
55
54