【问题标题】:iOS ScrollView needs constraint for y position or heightiOS ScrollView 需要约束 y 位置或高度
【发布时间】:2016-06-08 02:01:00
【问题描述】:
-ViewController
--View
---ScrollView (Top,Bottom,Leading,Trailing spaces to superview set to 0)
----ContentView (Top,Bottom,Leading,Trailing spaces to superview set to 0, Width equals with View (ViewController's child))
-----Label1
-----etc...

如果我为我的内容视图设置了特定的高度约束(例如 1000),则 ScrollView 工作正常,但我得到了 1000 的静态 ContentView,这不是我的目标,因为我的 contentView 有动态内容,所以它应该是内容需要的高度。

如果我删除 ContentView 的高度限制,Xcode 会说:

Missing Constraints:
ScrollView need constraints for: Y position or height

ScrollView 实际上是固定在顶部和底部的,所以我不知道为什么 Xcode 想要对 ScrollView 设置高度限制...

当我希望 ContentView 高度成为内容所需的高度时,正确的方法是什么?

【问题讨论】:

    标签: ios objective-c autolayout storyboard scrollview


    【解决方案1】:

    如果你有 UIScrollView with UITextView inside 抱怨:

    “ScrollView 需要约束 y 位置或高度”。或者“UIScrollView Scrollable Content Size Ambiguity”

    只需取消选中 IB 中 UITextView 上的默认“启用滚动”即可。 就像魔术一样工作 :)

    【讨论】:

      【解决方案2】:

      Xcode 11

      几个小时以来,我一直在关注这方面的几个教程,但它们似乎都不起作用。 Xcode 11 似乎有一些更新,改变了滚动视图与自动布局的工作方式。

      1. 向视图添加UIScrollView 并添加顶部、底部、前导和尾随约束。
      2. UIView 添加到滚动视图。我们将其称为内容视图。
      3. 从内容视图向滚动条添加顶部、底部、前导和尾随约束 视图的内容布局指南。将约束设置为 0。
      4. 内容视图滚动视图的框架布局指南之间添加等宽约束。 (不是滚动视图或主视图!)
      5. 暂时向内容视图添加高度限制,以便您可以添加内容。确保所有内容都有顶部、底部、前导和尾随约束。
      6. 删除内容视图的高度限制。

        I found an excellent tutorial at this link.

      【讨论】:

      • #6 中的教程是最新的 Xcode 11 并且有效!感谢 @bkSwifty 找到并分享这篇文章!
      【解决方案3】:

      每当使用带有自动布局的 ScrollView 时,请始终按照以下步骤操作,

      1. ScrollView 约束:leadingSpace、topSpace、TrailingSpace、bottomSpace 到 superView 并确保当您控制拖动添加约束时,通过按 alt 添加它,这样约束将被设置为无边距。

        李>
      2. 在滚动视图中添加 UIView 作为容器视图并设置其约束: leadingSpace、topSpace、trailingSpace、bottomSpace 到 ScrollView 而不按 alt 按钮,将 equalWidth 设置为 ScrollView

      3. 你在这个容器视图中添加的任何视图都必须有从上到下的约束,即所有视图都应该有垂直约束,所以 containerView 可以根据里面的内容来计算自己需要的高度。

        李>

      如果约束设置正确,则 scrollView 将根据其中的组件自动设置其内容大小,您无需手动设置内容大小,而且只有容器视图内的组件为不适合里面,否则它不会滚动。如果你想让它滚动,那么你需要检查情节提要中的 Bounces Vertically 属性以获得反弹效果。

      注意: 当你在 scrollView 中为组件设置约束时,你会看到约束警告,直到你将约束从顶部组件设置到底部组件,记住你的顶部组件应该对 superView 具有顶部约束(垂直约束),并且底部的组件应该对超级视图具有底部空间约束。当这个满足时,所有的警告最终都会消失。

      ScrollView 约束:

      ContainerView 约束:

      【讨论】:

      • 您添加了 3 次“leadingSpace to scrollView”。
      • 我的最后一个控件将是一个 MapView,它是我在运行时生成的,这样也可以吗?
      • 是的,它肯定会起作用。我可以建议你的是,不要以编程方式创建和添加 mapView,从 IB 添加它并将其高度约束设置为 0,因为你想在运行时显示它。制作 mapViews 高度约束的出口,当你想显示你的 mapView 时,只需执行此 mapViewHeightConstraint.constant = ; [self.view layoutIfNeeded];如果你想再次隐藏你的mapView,请将其设置为0。如果你想以动画方式增加mapView的高度,只需将布局设置为[UIView animateWithDuration:0.3 animations:^{ [self.view layoutIfNeeded]; }];
      • 这个答案太好了!!终于明白如何在ScrollView中正确设置约束了,非常感谢
      • 一直在寻找这样的答案 2 年,解释了设置 ScrollView 的机制是如何工作的。问候。
      【解决方案4】:

      确保滚动视图内内容视图内最底部的元素将底部空间约束设置为 0,并确保内容视图内的所有元素都设置了高度。

      这会使内容视图根据其中的元素调整大小,并且您的滚动视图/内容视图没有固定高度,并且您的滚动视图将根据手机的屏幕大小调整大小。

      【讨论】:

        【解决方案5】:
        1. 选择您的视图控制器
        2. 取消选中“调整滚动视图插图”

        【讨论】:

          【解决方案6】:

          Bharat Modi 的回答几乎解决了这个问题,但我(Xcode 8.3.2,iOS 10 SDK)还必须将 Content View 的高度和宽度与 UIScrollView 的高度和宽度相匹配。

          这会将内容大小固定到可见区域,但它让 IB 很高兴。然后(我认为)这只是正确计算内容大小并以编程方式设置它的问题。无论如何我都必须这样做,因为如果你有动态内容,你只能在运行时这样做。

          如果您有导航栏,您可能还需要调整视图控制器的“调整滚动视图插图”设置。

          这就是我所拥有的:

          请注意,这可能只是我的设置的一个特点,因为官方建议 (https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/AutolayoutPG/WorkingwithScrollViews.html) 也没有提到需要这样做。

          我尝试仅使用滚动视图、内容视图和另一个固定宽度和高度的虚拟视图来模仿内容,但似乎没有什么能让 IB 高兴。

          (对不起,我没有足够的代表将其作为对原始答案的评论)。


          更新:

          所以实际上我最终做的是在 IB 中将我的内容视图设置为固定高度,并在代码中为该高度约束创建一个出口。然后在视图加载了所有动态内容后,我只需像这样更新高度约束:

          self.uiContentViewHeightConstraint.constant = mapViewBottomY + 15
          

          一切正常。这里的关键基本上是当滚动视图中有一个视图时 - 该视图定义了滚动视图的内容大小。正如人们之前提到的,内容视图的大小必须在构建时完全定义,以使 IB 满意。您可以在运行时通过 outlet 随意操作这些值 - 这既简单又安全。

          在 IB 中以固定大小的内容视图的一个优点是,由于您已经固定了内容大小,现在可以像往常一样使用相对偏移量来定义内容视图内的视图。

          【讨论】:

            【解决方案7】:

            会有用的

            -ViewController
            --View
            ---ScrollView (Top,Bottom,Leading,Trailing spaces to superview set to 0)
            ----ContentView (Top,Leading,Trailing spaces to ScorllView set to 0 | Height to dynamic (1000))
            -----Label1
            -----etc...
            

            对您的 ContentView 做同样的事情,您自己的内容计算

            - (void)viewDidAppear:(BOOL)animated
            {
            [super viewDidAppear:YES];
            [self adjustHeightOfTableview];
            }
            
            - (void)adjustHeightOfTableview
            {
            CGFloat height = tblMainMenu.contentSize.height;
            CGFloat maxHeight = tblMainMenu.superview.frame.size.height - tblMainMenu.frame.origin.y;
            
            // if the height of the content is greater than the maxHeight of
            // total space on the screen, limit the height to the size of the
            // superview.
            
            if (height > maxHeight)
                height = maxHeight;
            
            // now set the height constraint accordingly
            self.tableViewHeightConstraint.constant = height;
            [UIView animateWithDuration:0.1 animations:^{
                [self.view setNeedsUpdateConstraints];
            }];
            }
            

            编辑 1

            - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
                {
                NSString *OptName_length = @" Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam";
                NSDictionary *attributes = @{NSFontAttributeName: [UIFont systemFontOfSize:17.0]};
                CGRect rect = [OptName_length boundingRectWithSize:CGSizeMake(tableView.bounds.size.width-150.0, MAXFLOAT)
                                                              options:NSStringDrawingUsesLineFragmentOrigin
                                                           attributes:attributes
                                                              context:nil];
            
                CGSize requiredSize = rect.size;
                return requiredSize.height +5.0f;
                }
            

            编辑 2

            检查网站,这将对您有所帮助... uitableviewcell-dynamic-height-with-autolayout-conclusion

            【讨论】:

            • 如果我将高度设置为1000,这不是动态的想法。
            • 我为 Table View 发布代码,为您的 UIView 执行此操作,更改 viewDidAppear 中的高度
            • 谢谢!我会试试这个。 tableViewHeightConstraint 是一个出口吗?
            • UIView 没有名为“contentSize”的属性。并且 contentView.frame.size.height 每次都给我 1000。
            • 你必须计算你的ContentView的内容大小,这是这里的关键。在这里查看我的答案http://stackoverflow.com/a/30522553/3177007
            【解决方案8】:

            使用滚动视图的内容视图设置标签左上角和下边距约束,并将 UILable 的行数设置为 0。它将根据内容的大小扩展您的内容视图

            【讨论】:

              猜你喜欢
              • 2017-10-14
              • 1970-01-01
              • 1970-01-01
              • 2018-09-11
              • 2014-08-22
              • 1970-01-01
              • 2016-11-04
              • 2017-12-21
              • 1970-01-01
              相关资源
              最近更新 更多