iOSのアプリ開発では、Size Classを使って1つのStory boardでiPhoneやiPadの画面サイズに応じて異なるレイアウトを作成することができるようになりました。
Size Classは2018年5月現在、以下のように定義されています。
w:compact | w:regular | |
---|---|---|
h:compact | iPhone(横置き) | iPhone Plus(横置き) |
h:regular | iPhone(縦置き) | iPad(縦置き/横置き) |
参考 https://developer.apple.com/ios/human-interface-guidelines/visual-design/adaptivity-and-layout/
ここで問題になるのは、iPadは縦置き(portrait)も横置き(landscape)もwidth = regular, height = regularに割り当てられているので、縦置きと横置きでレイアウトを変えることができないということです。
これを以下のような割り当てに変えて、iPadの縦置きと横置きで異なるSize Classにする方法がわかったので書き残しておきます。
w:compact | w:regular | |
---|---|---|
h:compact | iPhone(横置き) | iPhone Plus(横置き)、iPad(横置き) |
h:regular | iPhone(縦置き) | iPad(縦置き) |
ただし、見てわかるようにiPhone Plus(横置き)とiPad(横置き)は同じSize Classが割り当たるので、同じレイアウトになってしまいます。
手順は以下の通りです。
-
対象となる画面にContainer Viewを配置する。この画面のView Controllerを
ContainerViewController
とします。 -
Container Viewに組み込まれたView(自動的にセグエで接続されているView)に表示したい内容を配置します。上記のSize Classに応じてレイアウトが変わるように作成してください。このView Controllerを
MyViewController
とします -
ContainerViewController
に以下の実装を行います。
class ContainerViewController.swift: UIViewController {
let traitCollectionsRC = UITraitCollection(traitsFrom: [UITraitCollection(horizontalSizeClass: .regular), UITraitCollection(verticalSizeClass: .compact)])
// 初期表示用
override func viewDidLoad() {
super.viewDidLoad()
setChildTrait(size: CGSize(width: self.view.bounds.width, height: self.view.bounds.height))
}
// 回転後用
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
setChildTrait(size: size)
}
func setChildTrait(size: CGSize) {
if ( self.traitCollection.horizontalSizeClass == .regular && self.traitCollection.verticalSizeClass == .regular ) {
// 両方ともregularの場合をiPadだと判断
if size.width > size.height {
// 幅の方が大きい場合は横置きだと判断し、w:regular,h:compactで上書きする
// なおchildViewController[0]がMyViewControllerになっている
self.setOverrideTraitCollection(traitCollectionsRC, forChildViewController: self.childViewControllers[0])
} else {
// それ以外の場合は縦置きになっているので上書きをnilで解除
// 上書きしなければ、本来のw:regular, h:regularが適用される
self.setOverrideTraitCollection(nil, forChildViewController: self.childViewControllers[0])
}
}
}
}
Container Viewを経由する必要があるので若干面倒ですが、これでiPad縦置きと横置きのレイアウトをSize Classで変えることができるようになります。
環境
- Xcode 9
- Swift 4
- iOS 11.3