【问题标题】:Nested Stack View won't respond to changing axis based on size class嵌套堆栈视图不会响应基于大小类的更改轴
【发布时间】:2025-12-07 20:35:02
【问题描述】:

我有 4 个简单的视图,我想在 iPhone 上以垂直 4x1(如果水平紧凑)或水平 2x2(如果采用任何其他组合)布局。我还将 wC+vC 添加为水平 2x2,因为 iPhone 横向是 wC+vC。

我的界面构建器布局如下所示:

当在助手中以横向和纵向显示 iPhone 4s 的预览时,我得到了我所期望的:

但是!当我将模拟器用于任何 iPhone 并将其放入横向时,我会得到:

无论我如何尝试,我都无法将 TopStack 和 BottomStack 都显示为水平。如果我删除底部堆栈,顶部变为水平。但是一旦底部堆栈开始发挥作用,顶部堆栈就不会响应。

我什至在 wC+vC 的代码中尝试过这个:

-(void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
if( self.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassCompact && self.traitCollection.verticalSizeClass == UIUserInterfaceSizeClassCompact ) {
    [self.TopStack setAxis:UILayoutConstraintAxisHorizontal];
    [self.BottomStack setAxis:UILayoutConstraintAxisHorizontal];
} else {
    [self.TopStack setAxis:UILayoutConstraintAxisVertical];
    [self.BottomStack setAxis:UILayoutConstraintAxisVertical];
}

}

调试时,我可以验证顶部堆栈实际上在UILayoutConstraintAxisHorizontal 中,但没有正确显示。

有人知道出了什么问题吗??

【问题讨论】:

  • 它在设备上是否正常工作?
  • 它在设备上的功能与模拟器相同。在最新的 iphone 6 上测试
  • 只是为了确认这是一个通用应用程序,而不仅仅是 iPhone?
  • 正确,我尝试了universal和iphone,没关系
  • 是的,我想知道这是否是 IB 中的错误。我尝试对其进行硬编码,并确认堆栈视图中的状态更改并且它没有更新显示。

标签: ios objective-c size-classes


【解决方案1】:

这可能是UIStackView 的一个持续错误。在 iOS 9.0 的 beta 版本中似乎存在类似的问题,并且可能仍然存在一些关于嵌入式 UIStackViews 的挥之不去的问题:

http://useyourloaf.com/blog/adapting-stack-views-with-size-classes/

按照上述文章中的说明添加以下代码确实可以解决此问题,但代价是与屏幕尺寸无关,并丢失了一些使尺寸类有用的东西:

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];

    if (size.width > size.height)
    {
        [self.topStack setAxis:UILayoutConstraintAxisHorizontal];
        [self.bottomStack setAxis:UILayoutConstraintAxisHorizontal];
    }
    else
    {
        [self.topStack setAxis:UILayoutConstraintAxisVertical];
        [self.bottomStack setAxis:UILayoutConstraintAxisVertical];
    }
}

演示 Xcode 项目可以下载from here

【讨论】:

  • 这确实按预期工作! Apple 是否提供了任何常量作为尺寸类的宽度或高度,而不是使用幻数作为设备宽度或宽度>高度?
  • 老实说,我怀疑它考虑到大小类的目的是为了防止这种确切的代码。如果是我,我可能会在 UIViewController+StackViewHack 类别或类似类别上实现此方法的核心,以便在 Apple 修复嵌套的 UIStackView 布局后更容易恢复/更新。为这个错误提交一个雷达并链接到这个 SO 问题也是一个好主意。
  • 好主意。听起来这是苹果修复问题之前的唯一解决方案。非常感谢你的帮助! :)
  • 您可以在此方法中检查self.traitCollection.horizontalSizeClass 的值,而不是使用高度/宽度检查。这不是我尝试过的东西,但我可以在下次我靠近笔记本电脑时试一试,然后报告我的发现/更新答案。
  • 对,我试过这样做,因为这是一个 viewWill...,它似乎在 traitCollection 更新大小类之前被调用。所以视图控制器仍然保留切换之前的旧尺寸类。最初我希望在 traitCollection 更新后使用traitCollectionDidChange: 获得一个钩子(成功工作),但随后setAxis: 似乎并没有在视觉上产生影响——即使我可以通过编程方式验证它具有新的轴。跨度>
最近更新 更多