美文网首页程序员iOS 开发 iOS进阶指南
浅析Split View Controller的collapse

浅析Split View Controller的collapse

作者: MapleMeowMeow | 来源:发表于2016-07-29 18:03 被阅读393次

    Xcode自带的Master-Detail模板应用,在iPad和iPhone上有着不同的展示方式。今天来浅要介绍下如何在横屏时,使得SplitView在iPhone中的表现与在iPad中的保持一致。


    iPad和iPhone中的不同

    准备工作

    打开Xcode,使用iOS->Application->Master-Detail Application模板创建一个App,取名随意。

    运行后界面比较

    以下分别是初始化的App在iPad、iPhone 6 Plus、iPhone 6中的横屏截图。

    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选项取消勾选,使其不影响原有视图表现形式。

    取消勾选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,横屏时的截图如下所示,说明修改成功。

    iPhone6横屏截图

    结语

    以上是我的一些经验与心得,若有不足之处,请予指正。希望这篇文章对你有所帮助_

    相关文章

      网友评论

        本文标题:浅析Split View Controller的collapse

        本文链接:https://www.haomeiwen.com/subject/udmzjttx.html