最近まで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:
を入れ替えれば大丈夫です。