[iOS 8] iPhone 5s / iPhone 6 でも Landscape で iPad のように2画面表示にする

iPhone 6 Plus の Landscape が iPad っぽいワケ

iPhone 6 Plus の発表を見ていると、Landscape 表示が iPad のように2画面表示になっていることに驚かれたかたも多かったと思います。

iphone-split01

その理由はこちらの記事でも触れているように、Size Class で iPhone 6 Plus の Landscape の Width が iPad 同様に Regular になっているためです。

Portrait - Width Portrait - Height Landscape - Width Landscape - Height
iPhone 5s
iPhone 6
Compact Regular Compact Compact
iPhone 6 Plus Compact Regular Regular Compact
iPad Regular Regular Regular Regular

iPhone 5s や iPhone 6 などでも行いたい場合、画面構成を少し調整すれば同様に2画面表示にすることが可能です。

Split View Controller を2画面構成にする

Split View Controller を2画面構成にするには、横表示(Landscape)で Regular と判定されれば良いわけです。iPhone 5s / iPhone 6 は Landscape の Width は Compact なので、ここを書き換える必要があります。そのため、Split View Controller の親の View Controller を作成し、その親クラスで setOverrideTraitCollection:forChildViewController: を呼んであげる必要があります。 このメソッドは子の View Controller の Trait Collection を上書きするメソッドです。

ということで、下図のように新しく View Controller を作成し、Split View Controller を Container View の中に入れます。

iphone-split02

あとは View Controller を下記のように実装します。viewWillTransitionToSize: は Size Classes が変更されたとき、つまり Portrait - Landscape 切替時に呼ばれるメソッドです。

import UIKit

class ContainerViewController: UIViewController, UISplitViewControllerDelegate {
    
    // MARK: Lifecycle
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // TraitCollectionの更新
        performTraitCollectionOverrideForSize(view.bounds.size)
        
        // Navigation Controllerの調整
        let splitViewController = self.childViewControllers[0] as UISplitViewController
        let navigationController = splitViewController.viewControllers[splitViewController.viewControllers.count-1] as UINavigationController
        navigationController.topViewController.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem()
        splitViewController.delegate = self
    }
    
    // MARK: Trait Collection
    
    override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
        performTraitCollectionOverrideForSize(size)
    }
    
    private func performTraitCollectionOverrideForSize(size: CGSize) {
        var overrideTraitCollection: UITraitCollection? = nil
        // widthが480以上の場合はRegularを設定
        if size.width >= 480 {
            overrideTraitCollection = UITraitCollection(horizontalSizeClass: .Regular)
        }
        for vc in self.childViewControllers as [UIViewController] {
            setOverrideTraitCollection(overrideTraitCollection, forChildViewController: vc)
        }
    }
    
    // MARK: - Split view
    
    func splitViewController(splitViewController: UISplitViewController, collapseSecondaryViewController secondaryViewController:UIViewController!, ontoPrimaryViewController primaryViewController:UIViewController!) -> Bool {
        if let secondaryAsNavController = secondaryViewController as? UINavigationController {
            if let topAsDetailController = secondaryAsNavController.topViewController as? DetailViewController {
                if topAsDetailController.detailItem == nil {
                    // Return true to indicate that we have handled the collapse by doing nothing; the secondary controller will be discarded.
                    return true
                }
            }
        }
        return false
    }

}

実行して横画面表示にすると、2画面構成で表示されます。

iphone-split03

まとめ

ということで、アプリ側の対応次第で iPhone 5s / iPhone 6 でも Split View Controller を2画面構成にできることがお分かりいただけたかと思います。iOS 8 からは Landscape 表示でステータスバーが消えてスペースが広くなっているので、今まで以上に使う機会が多いかもしれません。ぜひ参考にしてください。

参考