AutolayoutされたViewをアニメーション移動させるには

Xcode 5.1

今、以下のような単純な画面を作っていたとする。

ご覧のように、画面上にはラベルが1つとボタンが1つ存在するだけである。

Helloラベルには、以下のように4つのAutolayout制約があるものとする。

・Width(固定)
・Height(固定)
・Vertical Space(コンテナ上側に対する余白)
・Horizontal Center in Container


ここで、ボタンが押されるたびに、ラベルを下に100ピクセルずつ動かしたいとする。しかも、その移動をアニメーションさせたいとする。


まず、Autolayoutされたビューを動かすには、frameプロパティやcenterプロパティを変更する、というアプローチは通用しない。Autolayoutされたビューというのは、制約により配置されているのであり、動かすならば、レイアウト制約の値を変更すべきである。

幸いにも、レイアウト制約は、NSLayoutConstraint属性としてアウトレットすることができる。

たとえばこんなふうにする。

ViewController.h

@interface ViewController : UIViewController
{
    IBOutlet NSLayoutConstraint* _labelTopMargin;
}
@end

そして、ストーリーボード上で、目的の制約=今回の場合はVertical Spaceを_labelTopMargin属性にアウトレットしてやる。

できた。

さて、あとはボタンのイベントハンドラで制約の値を変更してやればよいのだが、以下のように単純にアニメーションさせようとしてもうまくいかなかった。

ViewController.m 内、一部

-(IBAction)moveLabel:(id)sender {
    [UIView animateWithDuration:4.4
                     animations:^{
                          _labelTopMargin.constant += 100.0;
                     }];
}

動くことは動くが、アニメーションしない。


以下のようにするとうまくいく。

-(IBAction)moveLabel:(id)sender {
    [self.view setNeedsUpdateConstraints];
    _labelTopMargin.constant += 100.0;

    [UIView animateWithDuration:4.4
                     animations:^{
                          [self.view layoutIfNeeded];
                     }];
}

【参考】
http://stackoverflow.com/questions/12926566/are-nslayoutconstraints-animatable