iPadOSでポートレートとランドスケープで異なるレイアウトを採用する
iPadのサイズクラスはポートレートでもランドスケープでもwR hRなのでサイズクラスでは表題の件を実現できません。
これについてググると、traitCollectionをoverrideする方法が出てきます。wR hRのサイズクラスを縦横比に従ってwC hRもしくはhCに変えてしまおうというアイデアです。
(wR hCではなくhCなのは、wC hCがiPhone 4などコンパクトな機種でのランドスケープだからです)
ところが、iOS 13/iPadOS 13ではtraitCollectionのoverrideがnot supportedになりました。
なんとかしないといけません。
色々方法はありますが、拡張性を重視して以下の方法を採用しました。
- wC hR, hCについてストーリボードで制約を設計
- wR hRについてポートレートとランドスケープそれぞれについてストーリボードで制約を設計。両方installedにすると衝突するので、メインと思われる片方のみinstalledにする。
- ルートビューコントローラにisPortraitというインスタンス変数を用意する
- ルートビューコントローラのupdateVIewConstraintsをoverrideしてwR hRの場合、isPortraitに応じて2で設計した制約のどちらかだけをactivateする。(wR hRでない場合には両方deactivateする)
- ルートビューコントローラのviewWillTransition(to:with:)をoverrideしてwR hRのときの縦横比からisPortraitの条件が変わった場合、isPortraitを設定してview.setNeedsUpdateConstraintsを呼び出す
これで色々な状況に対応できました。
色々とは、念頭にある回転だけでなく、例えば、アプリがフォワグランドに復帰するときとか、スプリットビューとか。
これだけ書くと当たり前っぽい処理ですが、ここに至る前にupdateVIewConstraintsをoverrideせずにviewWillTransition(to:with:)内で制約を切り替える方法を実装して嵌りました。updateVIewConstraintsはデフォルトでは色々な状況でストーリボードの制約を読み直す処理が入っているようで、viewWillTransition(to:with:)で設定しても有効にならないケースが複数ありました。
以上、ご参考になれば幸いです。
また、これに関してもっと常識のイデオムがあれば教えていただきたく。