【问题标题】:UIScrollview with Autolayout Content Size in LandscapeUIScrollview 与横向自动布局内容大小
【发布时间】:2014-04-08 01:03:52
【问题描述】:

我正在尝试在我的应用中显示一个简单的设置屏幕,并且我正在使用自动布局。由于我的应用程序支持横向,并且当手机横向时设置控件不太适合垂直,所以我添加了一个 UIScrollview。

UIScrollview 和 Autolayout 的结合似乎是这里和其他地方的常见问题。我已经阅读了几篇关于它的文章,从它可以看出的情况来看,我想要做的一个好方法是将我的各种控件放在一个视图中,比如带有约束的“contentView”在该视图中对齐。然后让 contentView 成为 UIScrollView 的唯一子视图。我有与 UIScrollView 边缘相关的约束的 contentView。

UINavigationView -> UIScrollview -> contentView (UIView) -> Control Subviews

即使我在 contentView 中添加需要滚动查看的内容,它在纵向上也能正常工作,但是当我转到横向时,它并没有让我向下滚动足够远。这就像我旋转时内容大小被重置为可见区域的框架(或导航控制器超级视图的框架)一样。

我想知道是否需要检查旋转然后在那时再次设置内容大小?如果是这样,有没有办法从视图(contentView)中动态获取该大小?

感谢您提供的任何帮助! 吉姆

【问题讨论】:

    标签: ios xcode uiscrollview uinavigationcontroller autolayout


    【解决方案1】:

    让自动布局正确处理滚动视图有两个组成部分:

    1. 滚动视图子视图的约束:滚动视图的contentSize 将由滚动视图的子视图的约束决定。因此,您需要对滚动视图中的最后一个控件(即第二个开关)到其父视图(即滚动视图)有一个底部约束。看起来你确实有这个。滚动视图的子视图的这些约束将根据需要自动调整滚动视图的contentSize

      顺便说一下,第二个开关底部约束的constant 通常默认为与纵向布局相对应的较大值。您可能希望为最后一个控件选择和编辑此底部约束并将其更改为“标准”值。

    2. 滚动视图本身的约束:您需要确保滚动视图本身对其父视图具有底部约束(并确保您对滚动视图)。这将在屏幕旋转时调整滚动视图的frame。我想知道您的项目中是否可能缺少此功能。

      您可以通过在调试器中运行您的应用并点击“暂停”按钮来确认这一点:

      然后在(lldb) 提示符下,输入po [[UIWindow keyWindow] recursiveDescription],您应该会看到如下内容:

      (lldb) po [[UIWindow keyWindow] recursiveDescription]
      <UIWindow: 0x8b97ff0; frame = (0 0; 320 480); autoresize = W+H; gestureRecognizers = <NSArray: 0x8b98450>; layer = <UIWindowLayer: 0x8b97af0>>
         | <UIView: 0x8b9a830; frame = (0 0; 320 480); transform = [0, -1, 1, 0, 0, 0]; autoresize = RM+BM; layer = <CALayer: 0x8b9a240>>
         |    | <UIScrollView: 0x8b9aa50; frame = (0 0; 480 320); clipsToBounds = YES; autoresize = RM+TM; gestureRecognizers = <NSArray: 0x8b9a6c0>; layer = <CALayer: 0x8b9a130>; contentOffset: {0, 0}>
         |    |    | <UILabel: 0x8b9ade0; frame = (20 20; 63 21); text = 'Settings'; clipsToBounds = YES; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <CALayer: 0x8b9aec0>>
         |    |    | <UILabel: 0x8b9d590; frame = (20 49; 51 21); text = 'View 1'; clipsToBounds = YES; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <CALayer: 0x8b9d6b0>>
         |    |    | <UILabel: 0x8b9db70; frame = (408 49; 51 21); text = 'View 2'; clipsToBounds = YES; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <CALayer: 0x8b9dc10>>
         |    |    | <UIView: 0x8b9de60; frame = (335 78; 124 53); autoresize = RM+BM; layer = <CALayer: 0x8b9dec0>>
         |    |    | <UIView: 0x8b9e000; frame = (20 78; 284 53); autoresize = RM+BM; layer = <CALayer: 0x8b9e060>>
         |    |    | <UILabel: 0x8b9e250; frame = (20 139; 59 21); text = 'Slider 1'; clipsToBounds = YES; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <CALayer: 0x8b9e2f0>>
         |    |    | <UISlider: 0x8b9e460; frame = (18 238; 444 34); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x8b9e5c0>; value: 0.500000>
         |    |    |    | <UIView: 0x8ace410; frame = (2 16; 440 2); userInteractionEnabled = NO; layer = <CALayer: 0x8ace470>>
         |    |    |    |    | <UIView: 0x8ace610; frame = (221 0; 219 2); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x8ace670>>
         |    |    |    |    |    | <UIView: 0x8ace6e0; frame = (-221 0; 440 2); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x8ace740>>
         |    |    |    |    |    |    | <CAGradientLayer: 0x8ace7b0> (layer)
         |    |    |    |    | <UIView: 0x8ace7e0; frame = (0 0; 221 2); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x8ace840>>
         |    |    |    | <UIImageView: 0x8ace9d0; frame = (207 1; 31 31); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x8acea60>>
         |    |    |    |    | <UIImageView: 0x8ace8b0; frame = (-13 -6.5; 57 43.5); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x8ace940>>
         |    |    | <UISlider: 0x8b9e850; frame = (17 168; 444 34); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x8b9e930>; value: 0.500000>
         |    |    |    | <UIView: 0x8ba5430; frame = (2 16; 440 2); userInteractionEnabled = NO; layer = <CALayer: 0x8ba5490>>
         |    |    |    |    | <UIView: 0x8acc190; frame = (221 0; 219 2); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x8acae30>>
         |    |    |    |    |    | <UIView: 0x8acc3f0; frame = (-221 0; 440 2); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x8ac84d0>>
         |    |    |    |    |    |    | <CAGradientLayer: 0x8accb90> (layer)
         |    |    |    |    | <UIView: 0x8acdf50; frame = (0 0; 221 2); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x8acdfb0>>
         |    |    |    | <UIImageView: 0x8ace070; frame = (207 1; 31 31); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x8ace100>>
         |    |    |    |    | <UIImageView: 0x8acdfe0; frame = (-13 -6.5; 57 43.5); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x8acdc80>>
         |    |    | <UILabel: 0x8b9e9c0; frame = (20 209; 59 21); text = 'Slider 2'; clipsToBounds = YES; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <CALayer: 0x8b9ea60>>
         |    |    | <UISwitch: 0x8b9ece0; frame = (411 279; 51 31); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x8b9edd0>>
         |    |    |    | <_UISwitchInternalViewNeueStyle1: 0x8b9f0c0; frame = (0 0; 51 31); gestureRecognizers = <NSArray: 0x8b723f0>; layer = <CALayer: 0x8b9f1c0>>
         |    |    |    |    | <UIView: 0x8b9f750; frame = (35.5 0; 15.5 31); clipsToBounds = YES; layer = <CALayer: 0x8b9f7b0>>
         |    |    |    |    |    | <UIView: 0x8b9f3b0; frame = (-35.5 0; 51 31); layer = <CALayer: 0x8b9f410>>
         |    |    |    |    | <UIView: 0x8b9f6c0; frame = (0 0; 35.5 31); clipsToBounds = YES; layer = <CALayer: 0x8b9f720>>
         |    |    |    |    |    | <UIView: 0x8b9f440; frame = (0 0; 51 31); layer = <CALayer: 0x8b9f4a0>>
         |    |    |    |    | <UIView: 0x8ba11e0; frame = (0 0; 51 31); layer = <CALayer: 0x8ba1240>>
         |    |    |    |    |    | <UIImageView: 0x8ba0f10; frame = (39 16; 0 0); alpha = 0; userInteractionEnabled = NO; layer = <CALayer: 0x8ba10f0>>
         |    |    |    |    |    | <UIImageView: 0x8ba1120; frame = (12 16; 0 0); userInteractionEnabled = NO; layer = <CALayer: 0x8ba11b0>>
         |    |    |    |    | <UIImageView: 0x8b9fab0; frame = (7 -6; 57 43.5); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x8ba0a40>>
         |    |    | <UISwitch: 0x8b974b0; frame = (411 318; 51 31); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x8b75570>>
         |    |    |    | <_UISwitchInternalViewNeueStyle1: 0x8b7d6a0; frame = (0 0; 51 31); gestureRecognizers = <NSArray: 0x8b845e0>; layer = <CALayer: 0x8b78750>>
         |    |    |    |    | <UIView: 0x8b7df70; frame = (35.5 0; 15.5 31); clipsToBounds = YES; layer = <CALayer: 0x8b7be00>>
         |    |    |    |    |    | <UIView: 0x8b72410; frame = (-35.5 0; 51 31); layer = <CALayer: 0x8b7a660>>
         |    |    |    |    | <UIView: 0x8b7ba80; frame = (0 0; 35.5 31); clipsToBounds = YES; layer = <CALayer: 0x8b7bd00>>
         |    |    |    |    |    | <UIView: 0x8b78dd0; frame = (0 0; 51 31); layer = <CALayer: 0x8b7ba20>>
         |    |    |    |    | <UIView: 0x8b81580; frame = (0 0; 51 31); layer = <CALayer: 0x8b77ee0>>
         |    |    |    |    |    | <UIImageView: 0x8b97880; frame = (39 16; 0 0); alpha = 0; userInteractionEnabled = NO; layer = <CALayer: 0x8b7e1a0>>
         |    |    |    |    |    | <UIImageView: 0x8b77460; frame = (12 16; 0 0); userInteractionEnabled = NO; layer = <CALayer: 0x8b7e350>>
         |    |    |    |    | <UIImageView: 0x8b80670; frame = (7 -6; 57 43.5); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x8b80700>>
         |    |    | <UILabel: 0x8b97cf0; frame = (335 284; 67 21); text = 'Switch 1'; clipsToBounds = YES; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <CALayer: 0x8b808b0>>
         |    |    | <UILabel: 0x8b79d60; frame = (335 323; 67 21); text = 'Switch 2'; clipsToBounds = YES; opaque = NO; autoresize = RM+BM; userInteractionEnabled = NO; layer = <CALayer: 0x8b77b90>>
         |    |    | <UIImageView: 0x8ac44f0; frame = (476 473; 3 7); alpha = 0; opaque = NO; autoresize = LM; userInteractionEnabled = NO; layer = <CALayer: 0x8a89130>>
         |    |    | <UIImageView: 0x8ac2be0; frame = (313 316; 7 3); alpha = 0; opaque = NO; autoresize = TM; userInteractionEnabled = NO; layer = <CALayer: 0x8ac2c70>>
         |    | <_UILayoutGuide: 0x8b9cb20; frame = (0 0; 0 20); hidden = YES; layer = <CALayer: 0x8b9e5f0>>
         |    | <_UILayoutGuide: 0x8ac4440; frame = (0 320; 0 0); hidden = YES; layer = <CALayer: 0x8a90370>>
      

      检查UIScrollViewframe (例如上面是iPhone 上的横向),并确保它对应于屏幕尺寸。如果你没有定义滚动视图和它的父视图之间的约束,这个frame可能是不正确的。

    【讨论】:

    • 感谢您的信息。我之前没有尝试过调试器的递归输出提示,所以这是一个很酷的技巧。您的示例与我的不同之处在于,我的 UIScrollView 与滑块和开关等之间有一个中间 UIView(我称之为“contentView”)。也就是说,大提示似乎是从滚动视图中删除高度约束.一旦我删除它,我就可以在肖像中一直向下滚动。事实上它超出了内容(也许仍然是肖像的大小),但至少我可以得到内容!谢谢...
    • 我的意思是在移除滚动视图的垂直高度约束后,我能够在 Landscape 模式下一直滚动(甚至超过)内容。当方向改变以使内容大小完全匹配时,我可能需要在“contentView”上强制进行某种刷新,但太高总比太短好。再次感谢您的帮助。
    • @Jim “它超出了内容”问题可能是该开关的底部约束对容器视图的作用,以及从容器视图底部到底部的约束的滚动视图。没有看到项目很难说。最重要的是,如果你的约束条件正确,你绝对不需要在方向变化上搞乱contentSize
    • 谢谢 Rob- 我会检查的。你有关于删除垂直高度约束的关键,看起来其余的将与其他约束的一些调整一起工作。也感谢@Marcelo Gobetti 提供有关对变化做出反应的提示。以后可能会派上用场。另外,Rob 我现在要去寻找有关某些命令行调试的更多信息,以查看框架和布局。如果您知道好的资源,请告诉我,再次感谢。
    【解决方案2】:

    也许其他人对此会有更好的解决方案,但在当前版本上不做太多更改的最快方法就是完全按照您说的做:检查旋转,然后再次设置内容大小 . 在你的 Settings View Controller 实现文件中会这样做:

    - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
    {
        self.scrollView.contentSize = self.contentView.bounds.size;
    }
    

    ...假设您已将相同的文件出口添加到您的UIScrollView 和您的UIView,分别命名为scrollViewcontentView

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-24
      • 1970-01-01
      • 2012-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多