Autolayoutで可変高さのビューをアニメーション

2014年1月5日日曜日 | Published in | 0 コメント

このエントリーをはてなブックマークに追加

制約の追加・削除でアニメーションを制御するTips

例えば下図のような緑色のビュー(以下、緑ビュー)があるとする。

最初は赤いビュー(以下、赤ビュー)は隠れていてOpenボタンを押すと下から上へせり出てくるようなアニメーションをやってみる。



固定高さの場合は簡単で赤ビューの上の制約のconstant値を変えてやればいい。ただ今回のように出現位置(緑ビューの上辺)が可変の場合は少し工夫がいる。試行錯誤してみたところあらかじめ2つの制約(上辺と高さ)を用意しておき、それを操作することで実現できることがわかった。

順を追ってみてみる。

1. 赤ビューの制約を設定
まず赤ビューを緑ビューの上へ配置する。

次に制約を追加する。上下左右の制約をconstatn=0とした上で同時に Height=0とする。上下制約で高さを可変にしつつ、隠す時には高さを0にしておくという意図でこうする。
ただXcodeは警告を出す。

frame.size.heightが非0なのに(目で見て分かるように赤ビューは高さがある)制約height=0にしているので制約とframe設定が不一致という警告。ここでframe.height=0とすると今度は上制約(constatn=0)と矛盾して別の警告が出る。これは2つの矛盾する制約を課しているからこれは当たり前。
制約1:上辺は superviewとのオフセット0(プライオリティ 1,000)
制約2:高さは0(プライオリティ 1,000)
フレーム:高さは(ここでは282)

矛盾する制約がある場合はプライオリティに差をつけてやれば良い。今回は高さの制約のプライオリティを下げてやる。ここでは 500にしてみた。

すると警告が消えて代わりに高さの制約が点線表示になる。制約1の方が優先されるので赤ビューは見えたまま。

2. 制約の制御
次に赤ビューをアニメーションさせるコードを書く。
まず赤ビューの上の制約のアウトレット topConstraint を作っておく。

後での操作の為に ARCはweakではなくstrongにしておく。

初期表示時には赤ビューは隠しておきたい。そこで初期処理で制約1(上辺の制約)を削除してしまう。
- (void)viewDidLoad
{
    [super viewDidLoad];
    [self.view removeConstraint:self.topConstraint];
}
こうすると制約2(高さ0)の制約が残るので最初は何も表示されない。

次に赤ビューを表示させる。openボタンのアクションで取っておいた上の制約を加えてやる。
- (IBAction)open:(id)sender {
    [self.view addConstraint:self.topConstraint];
    [UIView animateWithDuration:0.5
                     animations:^{
                         [self.view layoutIfNeeded];
                     }];
}
こうすると制約1(上辺の制約)が復活し、かつ制約2(高さ0)よりもプライオリティが高いので優先され、画面上部まで上辺が移動する。
赤ビューが上へせり出してきて
アニメーション完了。制約1(上辺の制約=0)が適用された状態で終わる。

なおアニメーションの layoutIfNeededは制約ベースのアニメーションの定石(これをやらないとアニメーションしない)。

逆に閉じたい時は制約1(上辺の制約)を削除してやればいい。
- (IBAction)close:(id)sender {
    [self.view removeConstraint:self.topConstraint];
    [UIView animateWithDuration:0.5
                     animations:^{
                         [self.view layoutIfNeeded];
                     }];
}

Autolayoutを活用しているのでもちろん4インチディスプレイでも意図通りに動く。


なおアウトレットを作る代わりにコードで制約のインスタンスを作る方法もある。ただ今回のようにInterfaceBuilderを使った方が見た目わかりやすいのと制約をIB側でまとめられるメリットがあると思う。

- - - -
Autolayout以前のアニメーションは frameに対する操作が基本だったが、
Autolayoutでアニメーションを行う時の基本は
『制約に対して操作する』
これを理解すると難しくない(...いや凝ったことは難しいが)。ちょっとしたパズルみたい。

今回の方法がベストかは良くわからないがうまくいった。Autolayoutはとっつきにくいが慣れてくるとかなり強力。


サンプルのソースコードはこちら
AutolayoutSample1


[100min]

Responses

Leave a Response

人気の投稿(過去 30日間)