基于视图大小的自适应 UIPresentationController
Posted
技术标签:
【中文标题】基于视图大小的自适应 UIPresentationController【英文标题】:Adaptive UIPresentationController Based on View Size 【发布时间】:2015-04-09 13:28:30 【问题描述】:我正在为我的视图控制器转移到基于 UIPresentationController
的演示文稿,但我遇到了一些与 API 混淆的问题。
我有一个自定义的侧边栏样式视图控制器演示文稿(类似于LookInside
WWDC 2014 演示代码)。
此类集群(UIPresentationController
、UIViewControllerTransitioningDelegate
和 UIViewControllerAnimatedTransitioning
)在常规大小的类视图中将视图控制器作为侧边栏从屏幕边缘呈现,并在紧凑型视图中呈现与全屏相同的视图控制器大小类视图。
在 Resizable iPad 目标上进行测试显示了正确的行为:我将水平尺寸类设置为“紧凑”,并且我的视图控制器从侧边栏切换到全屏。
但是,我想要更多的粒度。当设备处于横向时,我想在 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
的文档指出:
使用这个属性来指定你想要应用到呈现和呈现视图控制器的任何特征。您指定的特征会覆盖当前对视图控制器有效的任何现有特征。此属性的默认值为 nil。
为此属性分配一个新值会导致演示控制器转换到新的特征集,这可能会导致呈现界面的动画。
为呈现控制器分配新值不会导致我呈现的界面发生任何变化。 (即使我在从 UIViewControllerTransitioningDelegate
对象中创建 UIPresentationController
时分配了 overrideTraitCollection
。)
我错过了什么?是否可以使用UIPresentationController
进行更精细的自适应演示?
【问题讨论】:
【参考方案1】:是否可以使用
UIPresentationController
在更精细的级别上执行自适应演示?
不容易。
我建议以下选项之一:
放弃控制并接受 UIKit 有限的适应性:您可以更改为全屏演示或为特定的 trait 集合呈现不同的视图控制器。使用它可以更快地发布您的应用。
使用演示文稿,但要针对 UIKit。一种方法是覆盖viewWillTransitionToSize:withTransitionCoordinator:
并关闭然后重新呈现呈现的视图控制器,进行任何您想要的更改,例如提供不同的呈现样式或呈现控制器。这可以在不花费太多时间的情况下给出好的结果。
使用视图控制器包含。这是你在坚持 UIKit 最佳实践时可以达到的最低水平。您的主视图控制器成为容器视图控制器的子视图,而不是呈现您要求容器显示另一个视图控制器。如果应用程序应该是定制的和精致的,那就去吧,你可以花时间把它做得恰到好处。
【讨论】:
【参考方案2】:用途:
- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller
traitCollection:(UITraitCollection *)traitCollection NS_AVAILABLE_ios(8_3);
即使尺寸等级没有改变,它也会在旋转时被调用,所以它是进行习惯用法/方向特定适应的好地方。请记住,iPhone 6 可以在放大模式下运行。
【讨论】:
【参考方案3】:我遇到了同样的问题。可以从尺寸类中解释设备方向,尽管并非完全明确,但以下内容适用于我的目的。
来自Programming iOS 9: Dive Deep into Views, View Controllers and Frameworks,一本很好的书,里面包含了这样的重要细节:
horizontalSizeClass
,verticalSizeClass
UIUserInterfaceSizeClass
值,.Regular
或.Compact
。这些被称为大小类。 尺寸等级组合起来具有以下含义:垂直和水平尺寸类都是
.Regular
:我们在 iPad 上运行垂直尺寸等级是
.Regular
,但水平尺寸等级是.Compact
:我们在iPhone 上运行,应用程序是纵向的。 (或者,我们可能会在 iPad 上以分屏 iPad 多任务配置运行;请参阅第 9 章)。垂直和水平尺寸类别均为
.Compact
:我们在 iPhone(iPhone 6 plus 除外)上运行,应用为横向。垂直尺寸类别为
.Compact
,水平尺寸类别为.Regular
:我们在iPhone 6 plus 上运行横向。
例如在视图控制器中:
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
【讨论】:
以上是关于基于视图大小的自适应 UIPresentationController的主要内容,如果未能解决你的问题,请参考以下文章