- (UITraitCollection *)traitCollection {
// Distinguish portrait and landscape size traits for iPad, similar to iPhone 7 Plus.
// Be aware that `traitCollection` documentation advises against overriding it.
UITraitCollection *superTraits = [super traitCollection];
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
UITraitCollection *horizontalRegular = [UITraitCollection traitCollectionWithHorizontalSizeClass:UIUserInterfaceSizeClassRegular];
UITraitCollection *verticalRegular = [UITraitCollection traitCollectionWithVerticalSizeClass:UIUserInterfaceSizeClassRegular];
UITraitCollection *regular = [UITraitCollection traitCollectionWithTraitsFromCollections:@[horizontalRegular, verticalRegular]];
if ([superTraits containsTraitsInCollection:regular]) {
if (UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation])) {
// iPad in portrait orientation
UITraitCollection *horizontalCompact = [UITraitCollection traitCollectionWithHorizontalSizeClass:UIUserInterfaceSizeClassCompact];
return [UITraitCollection traitCollectionWithTraitsFromCollections:@[superTraits, horizontalCompact, verticalRegular]];
} else {
// iPad in landscape orientation
UITraitCollection *verticalCompact = [UITraitCollection traitCollectionWithVerticalSizeClass:UIUserInterfaceSizeClassCompact];
return [UITraitCollection traitCollectionWithTraitsFromCollections:@[superTraits, horizontalRegular, verticalCompact]];
}
}
}
return superTraits;
}
- (BOOL)prefersStatusBarHidden {
// Override to negate this documented special case, and avoid erratic hiding of status bar in conjunction with `traitCollection` override:
// For apps linked against iOS 8 or later, this method returns true if the view controller is in a vertically compact environment.
return NO;
}
6 回答
看起来苹果打算将两种iPad方向都视为一样 - 但正如我们中的许多人所发现的那样,有非常合理的设计理由想要改变iPad Portrait与iPad Landscape的UI布局 .
不幸的是,当前的操作系统似乎并没有为这种区别提供支持......这意味着我们又回到了在代码或类似的变通方法中操纵自动布局约束,以实现我们理想情况下可以使用Adaptive UI免费获得的内容 .
不是优雅的解决方案 .
已经内置到IB和UIKit中的Isn 't there a way to leverage the magic that Apple'使用我们选择的尺寸等级给定方向吗?
〜
在更一般地思考这个问题时,我意识到“大小类”只是解决存储在IB中的多个布局的简单方法,因此可以在运行时根据需要调用它们 .
事实上,'size class'实际上只是一对枚举值 . 从UIInterface.h:
因此,无论Apple决定命名这些不同的变体,从根本上说,它们只是一对整数,用作各种各样的标识符,以区分存储在IB中的一种布局 .
现在,假设我们在IB中创建了一个替代布局(使用未使用的大小类) - 例如,对于iPad Portrait ...有没有办法让设备在运行时根据需要使用我们选择的大小类(UI布局) ?
在尝试了几种不同(不太优雅)的问题后,我怀疑可能有一种方法可以通过编程方式覆盖默认的size类 . 还有(在UIViewController.h中):
因此,如果您可以将视图控制器层次结构打包为“子”视图控制器,并将其添加到顶级父视图控制器...那么您可以有条件地覆盖该子项,使其认为它与默认值不同来自操作系统 .
这是在“父”视图控制器中执行此操作的示例实现:
作为一个快速演示,看看它是否有效,我在IB中专门为子控制器布局的“常规/常规”和“紧凑/常规”版本添加了自定义标签:
当iPad处于两个方向时,这就是它的运行状态:
瞧!运行时自定义大小类配置 .
希望Apple能够在下一版操作系统中实现这一点 . 与此同时,这可能是一种更优雅和可扩展的方法,而不是以编程方式处理自动布局约束或在代码中进行其他操作 .
〜
EDIT (6/4/15):请记住,上面的示例代码基本上是证明该技术的概念证明 . 您可以根据自己的具体应用需求进行调整 .
〜
EDIT (7/24/15):它测试了它,mohamede1945 [下面]的代码看起来像是一个有用的优化用于实际目的 . 随意测试它,让我们知道你的想法 . (为了完整起见,我将保留上面的示例代码 . )
作为RonDiamond的长篇答案的摘要 . 您需要做的就是在根视图控制器中 .
Objective-C的
迅速:
然后在storyborad中使用紧凑宽度为纵向和常规宽度为横向 .
iPad具有水平和垂直尺寸的“常规”尺寸特性,不区分纵向和横向 .
可以通过方法
traitCollection
在自定义UIViewController
子类代码中覆盖这些大小特征,例如:这使iPad具有与iPhone 7 Plus相同的尺寸特性 . 请注意,其他iPhone型号通常具有“紧凑宽度”特征(而不是常规宽度),无论方向如何 .
以这种方式模仿iPhone 7 Plus允许该模型在Xcode的Interface Builder中用作iPad的替身,它不知道代码中的自定义 .
请注意,iPad上的分割视图可能会使用与普通全屏操作不同的大小特征 .
这个答案是基于采取的方法在this blog post,有一些改进 .
Update 2019-01-02: 更新以修复iPad版本中的间歇性隐藏状态栏,以及在
UITraitCollection
中潜在践踏(较新)的特征 . 另请注意,Apple文档实际上建议不要覆盖traitCollection
,因此将来可能会出现这种技术的问题 .RonDiamond的漫长而有用的答案是理解这些原则的良好开端,但是适用于我的代码(iOS 8)基于重写方法
(UITraitCollection *)traitCollection
因此,在InterfaceBuilder中添加约束Width - Compact的变体,例如对于约束的属性Installed . 所以宽度 - 任何都适用于风景,宽度 - 紧凑的肖像 .
要根据当前视图控制器大小切换代码中的约束,只需将以下内容添加到UIViewController类中:
您的横向模式与纵向模式有多大不同?如果它非常不同,那么创建另一个视图控制器并在设备处于横向时加载它可能是个好主意
例如
@RonDiamond解决方案的Swift 3.0代码