Xcode自带的Master-Detail模板应用,在iPad和iPhone上有着不同的展示方式。今天来浅要介绍下如何在横屏时,使得SplitView在iPhone中的表现与在iPad中的保持一致。
iPad和iPhone中的不同
准备工作
打开Xcode,使用iOS->Application->Master-Detail Application模板创建一个App,取名随意。
运行后界面比较
以下分别是初始化的App在iPad、iPhone 6 Plus、iPhone 6中的横屏截图。
可以看到,App在iPad和Plus中的横屏表现几乎一致,除了Plus中没有显示最上面的状态栏和新增了Detail View左上角的按钮。但在其它iPhone中时,都只显示Master View,不同时显示Master和Detail View。这是由于什么原理造成的呢?
原理探究
Size Classes
想到iPhone 6 Plus、iPhone 6的屏幕尺寸不同,对应的Size Class也不尽相同,故找来各个iOS设备的Size Class做对比,如下表所示:
宽 | 高 | 设备与方向 |
---|---|---|
Compact | Compact | 除了Plus以外的所有横屏iPhone |
Compact | Regular | 所有的竖屏iPhone |
Regular | Compact | 横屏的Plus |
Regular | Regular | iPad,不管横竖屏 |
可以看到,在横屏状态,iPad的宽和高都是Regular,Plus的宽是Regular,高是Compact,其余iPhone的宽和高都是Compact。故有可能只有在设备宽是Regular时,SplitView才会默认同时显示Master和Detail View。因此只要在iOS设备的interface environment发生改变时,检测设备的长和宽,若都为Compact,则将宽设为Regular,即可改变SplitView的默认collapse做法。
traitCollectionDidChange
当interface environment发生改变时,traitCollectionDidChange方法会被调用,可以在这里进行相关设置。
首先在Storyboard中拖入一个Navigation Controller,将其设为Initial View Controller,并将原先为Initial View Controller的Split View Controller设为它的root view controller。这样做是为了用新加的Navigation Controller来控制Split View Controller的traitCollection change行为。同时将Navigation Controller的Shows Navigation Bar选项取消勾选,使其不影响原有视图表现形式。
创建基于UINavigationController的RootViewController类,将其与新添加的Navigation Controller相对应。在该类中实现traitCollectionDidChange方法:
override func traitCollectionDidChange(previousTraitCollection: UITraitCollection?) {
let splitViewController = self.viewControllers[0]
if self.traitCollection.verticalSizeClass == .Compact && self.traitCollection.horizontalSizeClass == .Compact {
let trait = UITraitCollection(horizontalSizeClass: .Regular)
self.setOverrideTraitCollection(trait, forChildViewController: splitViewController)
} else {
self.setOverrideTraitCollection(nil, forChildViewController: splitViewController)
}
}
以上代码的作用是,当检测到设备的长和宽都为Compact时,则这时候是在除了Plus以外的横屏iPhone中运行App,将其宽设为Regular,SplitView能够同时显示Master和Detail View;否则,不做任何重载。
AppDelegate微调
同时需要在AppDelegate.swift的didFinishLaunchingWithOptions函数进行微调,如下所示:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
let rootViewController = self.window!.rootViewController as! RootViewController
let splitViewController = rootViewController.viewControllers[0] as! UISplitViewController
// let splitViewController = self.window!.rootViewController as! UISplitViewController
let navigationController = splitViewController.viewControllers[splitViewController.viewControllers.count-1] as! UINavigationController
navigationController.topViewController!.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem()
splitViewController.delegate = self
return true
}
运行结果
在iPhone 6下重新运行App,横屏时的截图如下所示,说明修改成功。
结语
以上是我的一些经验与心得,若有不足之处,请予指正。希望这篇文章对你有所帮助_。