基于视图大小的自适应 UIPresentationController

Adaptive UIPresentationController Based on View Size

我正在为我的视图控制器转向基于 UIPresentationController 的演示文稿,但 运行 对 API.

感到有些困惑

我有一个自定义侧边栏样式的视图控制器演示(类似于 LookInside WWDC 2014 演示代码)。

此 class 集群(UIPresentationControllerUIViewControllerTransitioningDelegateUIViewControllerAnimatedTransitioning)将视图控制器呈现为常规尺寸屏幕边缘的侧边栏 class 视图,并在紧凑尺寸 class 视图上呈现与全屏相同的视图控制器。

在 Resizable iPad 目标上对此进行测试显示了正确的行为:我将水平大小 class 设置为 "Compact" 并且我的视图控制器从侧边栏切换到全屏。

但是,我想要更详细的信息。当设备处于横向时,我想在 iPhone 6 和 6+ 上使用侧边栏样式的视图控制器演示,并在纵向方向上对所有 iPhone 使用全屏样式演示。

所以在我的方法中

- (void) viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator

我实现了一些逻辑来检测侧边栏是否会占据太多屏幕,假设我使用以下条件:

//If my sidebar is going to occupy more than half the new width of the view...
if( self.sidebarTransitionController.width > size.width / 2.0 )
{
    //Override the presentation controller's trait collection with Compact horizontal size class
    sidebarPresentationController.overrideTraitCollection = [UITraitCollection traitCollectionWithHorizontalSizeClass:UIUserInterfaceSizeClassCompact];
}
else
{
    //Otherwise override the trait collection with Regular
    sidebarPresentationController.overrideTraitCollection = [UITraitCollection traitCollectionWithHorizontalSizeClass:UIUserInterfaceSizeClassRegular];

}

但是这没有任何作用。 UIPresentationController.overrideTraitCollection 的文档指出:

Use this property to specify any traits that you want to apply to the presented and presenting view controllers. The traits you specify override any existing traits currently in effect for the view controllers. The default value of this property is nil.

Assigning a new value to this property causes the presentation controller to transition to the new set of traits, which could result in animations to the presented interface.

将新值分配给呈现控制器不会导致我呈现的界面以任何方式发生变化。 (即使我在从 UIViewControllerTransitioningDelegate 对象中创建 UIPresentationController 时分配了 overrideTraitCollection。)

我错过了什么?是否可以在更精细的级别上使用 UIPresentationController 执行自适应呈现?

Is it possible to perform adaptive presentation with UIPresentationController on a more granular level?

不容易。

我建议以下选项之一:

  1. 放弃控制并接受 UIKit 的有限适应性:您可以更改为全屏显示或为特定特征集合显示不同的视图控制器。使用它可以更快地发布您的应用程序。

  2. 使用演示文稿但不支持 UIKit。一种方法是覆盖 viewWillTransitionToSize:withTransitionCoordinator: 并关闭然后重新呈现呈现的视图控制器,进行您想要的任何更改,例如提供不同的呈现样式或呈现控制器。这可以在不花费太多时间的情况下给出不错的结果。

  3. 使用视图控制器包含。这是坚持 UIKit 最佳实践时可以达到的最低级别。您的主视图控制器成为容器视图控制器的子级,而不是呈现您要求容器显示另一个视图控制器。如果应用程序要定制和精致,就用这个,你可以花时间把它做得恰到好处。

使用:

- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller
                                                               traitCollection:(UITraitCollection *)traitCollection NS_AVAILABLE_IOS(8_3);

即使大小 class 没有改变,它也会在旋转时被调用,所以是您进行 idiom/orientation 特定改编的好地方。请记住 iPhone 6 可以 运行 在放大模式下。

我 运行 遇到了同样的问题。可以从大小 类 解释设备方向,虽然不是完全明确,但以下内容对我的目的有用。

来自 Programming iOS 9: Dive Deep into Views, View Controllers and Frameworks,一本充满重要细节的优秀书籍,如下所示:

horizontalSizeClass, verticalSizeClass

A UIUserInterfaceSizeClass value, either .Regular or .Compact. These are called size classes. The size classes, in combination, have the following meanings:

Both vertical and horizontal size classes are .Regular: We're running on an iPad

The vertical size class is .Regular, but the horizontal size class is .Compact: We're running on an iPhone with the app in portrait orientation. (Alternatively we might be running on an iPad in a splitscreen iPad multitasking configuration; see Chapter 9).

Both the vertical and horizontal size classes are .Compact: We're running on an iPhone (except iPhone 6 plus) with the app in landscape orientation.

The vertical size class is .Compact and the horizontal size class is .Regular: We're running on an iPhone 6 plus in landscape orientation.

例如在视图控制器中:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "ShowComposeView" {
        segue.destinationViewController.presentationController!.delegate = self
        segue.destinationViewController.modalPresentationStyle = .PageSheet
    }
}

func adaptivePresentationStyleForPresentationController(controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
    // If we do an adaptive presentation, and adapt from Page Sheet to Form Sheet,
    // then on iPhone 6 we will get the nice rounded corners of the nav bar 
    // in both portrait and landscape. (From pg. 298 of Programming iOS 9)

    // We want this behaviour on iPhone in Portrait orientation only.
    if traitCollection.horizontalSizeClass == .Compact && traitCollection.verticalSizeClass == .Regular {
        return .FormSheet
    }
    else {
        return .PageSheet
    }
}