悪あがきプログラマー

悪あがきを続けていきたい技術と書評なブログです。トレタでiOSエンジニアやってます。

Auto Layoutでsubviewを動的に非表示にしたときのマージンをどうにかする

やりたいこと

こんな画面があります。各ラベルにheightのconstraintは指定していません。
f:id:y_koh:20131202214350p:plain

この画面のLabel Bは値があったりなかったりで、無いときはトルツメしたいとします。
※トルツメとは不要箇所を除いた後の空いた部分を詰めることです。トルツメとは : - IT用語辞典バイナリ

何がうまくいかない?

Label Bの値を空にしてみます。

self.labelB.text = nil;

すると、lable自体は消えたのですが、マージンがおかしいです。
f:id:y_koh:20131202215419p:plain

なんでうまくいかない?

何が起きているのかAuto LayoutのVisual Format Languageっぽく書いてみます。

オリジナル:
"V:[labelA]-20-[labelB]-20-[labelC]"

-20-がマージンです。

期待するレイアウト:
"V:[labelA]-20-[labelC]"

実際のレイアウト:
"V:[labelA]-20--20-[labelC]"

Label Bは消えたものの、マージンが両方共残ってしまっています。
(Label Bは実際に消えてるわけではなく、高さが0になっているはずです。)

どうすればよい?

これを解消するにはconstraintsのconstantを0.fにすると良いらしいです。

I then update the constant value to 0.f to hide, or whatever the value should be to show.

ios - AutoLayout with hidden UIViews? - Stack Overflow

が、実際にこのconstantをどうやって変更するのか分からずかなりハマりました。。
まぁ分かってしまえば簡単でした。


真ん中の青い四角が対象のconstraintです。これを操作できるようにするためにStoryboardのconstraintからヘッダーファイルにプロパティを作って紐付けます。
(このconstraintをヘッダーファイルに紐付けられることに気付くまでにめっちゃ時間かかりました。。)
f:id:y_koh:20131202223530p:plain

これが出来れば後は簡単。
プロパティに追加したconstraintのconstantにおもむろに0.fを代入するだけです。

self.labelABottomConstraint.constant = 0.f;

これでlabel Aの下のマージンが無くなって(0.fになって)期待するレイアウトになりました!

f:id:y_koh:20131202224546p:plain

他のconstraintについて

なお、他のconstarintはこんな感じで指定していました。
f:id:y_koh:20131202230341p:plain

まとめ

ポイントはこんな感じです。

  • constraintのheightを指定しない
  • constraintをヘッダーファイルに紐付ける
  • constraintのconstantを0.fにする

めっちゃハマったのでお役に立てば幸いです。