UIStackViewがAutoLayoutのエラーになったときの対応パターン
はじめに
初登場時は機能不足が否めなかったSwiftUIも、アップデートによりUIコンポーネントが追加され、世の中のアプリでも利用されるようになりました。
しかし従来から開発が続けられているiOSアプリやSwiftUIにまだ用意されていない機能が必要な場合には未だにUIKitが現役で利用されています。
UIKitではAutoLayoutを使ってViewの配置を行うのですが、シンプルに縦、横の直線的な配置をするのにもたくさんの制約を張る必要があります。
その手間を軽減してくれるのが UIStackView
で、非常によく使われるViewです。
しかし UIStackView
もサイズや設定値によってはAutoLayoutがエラーを表示することがあります。
その場合にネットで解決方法を検索すると Hugging Priority
や Compression Resistance Priority
という2種類のpriorityを使ったものが多いです。
どっちが何だっけ?上下どちらにすればいいんだっけ?と自分が毎回悩んでしまうため、よくある配置と発生するエラーの対応方法を以下にまとめます。
前提
表示サンプル
UIStackViewのサイズ未満の場合
要素のサイズの合計が UIStackView
のサイズ未満の場合、AutoLayoutが Content Priority Ambiguity
などのエラーを表示します。
たとえば以下のような2つのUILabelを配置した場合です。
一見正常に配置されているように見えますが、AutoLayoutはエラーになっています。
ShortAutoLayoutError.xib
いずれかの要素のサイズを固定可能な場合
要素のサイズを固定します。
次の図では左のLabelの width
を指定しました。
FixedSize.xib
要素のサイズが可変の場合
拡大を許可する要素の Content Hugging Priority
を下げます。
左のLabel: 251
右のLabel: 250
UseHuggingPriority1.xib
複数の要素を配置する場合も同じです。
左のLabel: 251
中央のLabel: 250
右のLabel: 251
UseHuggingPriority2.xib
要素のサイズは可変だが拡大は防ぎたい場合
UIViewなど、ダミーのViewを配置することで要素自体はコンテンツサイズを保ちます。
たとえば次の図のように中央に配置することで、両端に寄せたレイアウトを実現することができます。
UseSpacer.xib
UIStackView
のサイズより大きい場合
要素のサイズの合計が UIStackView
のサイズより大きい場合も同様に、AutoLayoutが Content Priority Ambiguity
などのエラーを表示します。
たとえば以下のような2つの長いテキストを持つUILabelを配置した場合です。
AutoLayoutはエラーになりますし、おそらく意図した表示ではないことも多いのではないかと思います。
LongAutoLayoutError.xib
縮小を許容できる要素が決まっている場合
縮小させる要素の Compression Resistance Priority
を下げます。
左のLabel: 750
右のLabel: 749
UseCompressionResistancePriority1.xib
UILabelの折り返しが必要な場合
UILabelは numberOfLines
の値を1以外に設定することで表示する行数を変更できます。
numberOfLines = 0
に設定したとき、 Compression Resistance Priority
の指定だけでは折返しが適用されず、 Hugging Priority
も同時に指定する必要がありました。
縮小させる要素の Compression Resistance Priority
、 Hugging Priority
の両方を下げます。
左のLabel
Compression Resistance Priority
: 749
Hugging Priority
: 250
右のLabel
Compression Resistance Priority
: 750
Hugging Priority
: 251
UseCompressionResistancePriority2.xib
参考記事
Discussion