覆盖表单大小类

时间:2016-03-03 15:33:16

标签: ios iphone ipad modalviewcontroller size-classes

有问题的ViewController嵌入在UINavigationController中,并显示为.FormSheet,如下所示:

class PLViewController:UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        navigationController?.navigationBar.translucent = false
    }

    /// Embeds self into a UINavigationController, adds a "done" button to the navVC and uses the passed ViewController to present self embedded in the NavigationController.
    /// - Parameters:
    ///     - presentingVC: ViewController which will present the formSheet.
    ///     - animated: If TRUE, the presentation of the formsheet will be animated.
    func presentAsFormSheet (presentingVC:UIViewController, animated:Bool, completion:(() -> Void)?) {
        let navVC = UINavigationController(rootViewController: self)
        navVC.modalPresentationStyle = .FormSheet
        let doneButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Done, target: self, action: Selector("dismissFormSheet"))
        doneButton.tintColor = GlobalVars.cautionColor
        navigationItem.setLeftBarButtonItem(doneButton, animated: false)
        presentingVC.presentViewController(navVC, animated: true, completion: completion)
    }

    /// Dismisses this ViewController with animation from a modal state.
    func dismissFormSheet () {
        dismissViewControllerAnimated(true, completion: nil)
    }

}

当VC以“浮动”表格方式(非全屏模式)呈现时,它需要基本上如下所示:

enter image description here

此外,如果应用程序处于1/3分屏(但不是2/3)或iPhone上,则需要进一步操作布局。 iPhone部分很容易理解,基本上检查设备类型并在代码中做出相应的响应。

有没有可以知道,在iPad上,a)在分屏模式下和b)使用1 / 3,1 / 2或2/3?

1 个答案:

答案 0 :(得分:0)

成功!通过子类化UIViewController,我能够创建一些方法来以编程方式调整.FormSheet模态以响应呈现的VC的特征变化。

UIViewController子类:

class MyViewControllerSubclass: UIViewController {
private func deviceOrientation () -> UIDeviceOrientation {
        return UIDevice.currentDevice().orientation
    }

    private func getScreenSize () -> (description:String, size:CGRect) {
        let size = UIScreen.mainScreen().bounds
        let str = "SCREEN SIZE:\nwidth: \(size.width)\nheight: \(size.height)"
        return (str, size)
    }

    private func getApplicationSize () -> (description:String, size:CGRect) {
        let size = UIApplication.sharedApplication().windows[0].bounds
        let str = "\n\nAPPLICATION SIZE:\nwidth: \(size.width)\nheight: \(size.height)"
        return (str, size)
    }

    /// Called when the UIViewController's traitCollection has changed.
    /// - Description:
    /// Include any changes that need to be made when the trait collection changes.
    func respondToSizeChange (layoutStyle:LayoutStyle) {

    }


    enum LayoutStyle: String {
        case iPadFullscreen         = "iPad Full Screen"
        case iPadHalfScreen         = "iPad 1/2 Screen"
        case iPadTwoThirdScreen     = "iPad 2/3 Screen"
        case iPadOneThirdScreen     = "iPad 1/3 Screen"
        case iPhoneFullScreen       = "iPhone"
    }

    /// - Returns: a `LayoutStyle` value containing information about what portion of the screen the application is consuming.
    internal func determineLayout () -> LayoutStyle {
        if UIDevice.currentDevice().userInterfaceIdiom == .Phone {
            return .iPhoneFullScreen
        }
        let screenSize = getScreenSize().size
        let appSize = getApplicationSize().size
        //let orientation = deviceOrientation()
        let screenWidth = screenSize.width
        let appWidth = appSize.width
        if screenSize == appSize {
            return .iPadFullscreen
        }

        if deviceOrientation() == .Portrait && screenSize != appSize {
            return .iPadOneThirdScreen
        }
        // In case the math isn't exact, set a range.
        let lowRange = screenWidth - 15
        let highRange = screenWidth + 15

        if lowRange / 2 <= appWidth && appWidth <= highRange / 2 {
            return .iPadHalfScreen
        } else if appWidth <= highRange / 3 {
            return .iPadOneThirdScreen
        } else {
            return .iPadTwoThirdScreen
        }

    }

    override func traitCollectionDidChange(previousTraitCollection: UITraitCollection?) {
        super.traitCollectionDidChange(previousTraitCollection)
        respondToSizeChange(determineLayout())
    }
}

在呈现模态的ViewController上:

class MainViewController:UIViewController {

    /// The modally-presented formSheet.
    var presentedFormSheet:MyViewControllerSubclass?

    /// Modally presents the VC in `.FormSheet` style and sets the local `presentedFormSheet` variable to the VC.
    func showContentRequirementVC() {
        let vc = MyViewControllerSubclass(nibName: "myCustomViewController", bundle: nil)
        vc.modalPresentationStyle = .FormSheet
        presentedFormSheet = vc
        presentViewController(vc, animated: true, completion: nil)
    }

    // When the trait collection changes, tell the presentedFormSheet about it.
    override func traitCollectionDidChange(previousTraitCollection: UITraitCollection?) {
        presentedFormSheet?.respondToSizeChange(determineLayout())
    }
}

<强>结果: 如下面的屏幕截图所示,现在只有当表单占用应用程序的整个区域时,才会显示纯红色条。传递的数据中有足够的信息,您可以单独响应完整,2 / 3,1 / 2和1/3。即使在呈现之后,模态也将对变化做出响应。

下面的屏幕截图也证明了这个问题的相关性。正如您所看到的,并排表格很有效,直到我们达到1/3或iPhone。此时,它们需要位于标签栏控制器上或使用其他方法,以便一次只显示一个表,用户可以在它们之间切换。这个特定的VC是使用UIStackViews构建的,因此可以通过编程方式轻松调整行为以适应UI布局。

全屏 full-screen

** 2/3屏幕** 2/3 screen

1/2屏幕 1/2 screen

1/3屏幕 1/3 screen

<强>幻灯片-超过 slide-over