将视图添加到将拉伸以填充可用宽度的滚动视图

Adding a view to a scroll view that will stretch to fill available width

我在故事板中使用自动布局,没有代码,并且很难让滚动视图的内容视图中的视图拉伸以填充设备宽度。我知道问题是滚动视图宽度不明确,但是当我希望它始终伸展以填充可用宽度(使用一些填充)时,我不确定如何使它不明确。

在视图控制器中,我添加了一个带有 4 个约束的滚动视图:顶部、底部、前导、尾随到超级视图。我在滚动视图中添加了一个视图,它将充当内容视图——所有子视图都将添加到内容视图中。它有 4 个约束:顶部、底部、前导、尾随滚动视图。然后,我将我希望可见的视图(一个简单的红色框,具有固定高度但会拉伸以填充屏幕宽度)添加到内容视图。它的约束是:拖到父视图(15),导致父视图(15),顶部到父视图(15),底部到父视图(15),高度等于60.

这导致滚动视图宽度不明确,并且框架错位 - 它想将框视图的宽度设置为 0。

我该如何设置才能使框视图伸展以填满设备屏幕,从而解决滚动视图内容大小宽度不明确的问题?

在 iOS 11 及更高版本中,滚动视图有两组布局指南,一组用于可滚动内容,contentLayoutGuide (which dictates the scrolling behavior), and one for its frame, frameLayoutGuide(指示子视图的大小)。

例如,添加一个子视图,向四周插入20个点,其宽度相对于滚动视图的框架设置,但具有固定的高度:

let subview = UIView()
subview.translatesAutoresizingMaskIntoConstraints = false
subview.backgroundColor = .red
scrollView.addSubview(subview)

NSLayoutConstraint.activate([
    subview.leadingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.leadingAnchor, constant: 20),
    subview.trailingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.trailingAnchor, constant: -20),
    subview.topAnchor.constraint(equalTo: scrollView.contentLayoutGuide.topAnchor, constant: 20),
    subview.bottomAnchor.constraint(equalTo: scrollView.contentLayoutGuide.bottomAnchor, constant: -20),

    subview.heightAnchor.constraint(equalToConstant: 1000),
    subview.widthAnchor.constraint(equalTo: scrollView.frameLayoutGuide.widthAnchor, constant: -40),
])

您也可以在 IB 中执行此操作,完全不需要任何编码:

在 iOS 11 之前,在没有 frameLayoutGuide 的情况下,您必须根据滚动视图的父视图设置子视图的约束,我在下面概述了该过程。但是由于iOS11,以上是比较直观的解决方案。


您在问题中描述的约束等同于以下 VFL:

  • 滚动视图占据整个视图

    H:|[scrollView]|
    V:|[scrollView]|
    
  • 红色视图的高度为 60 pt,与滚动视图的边缘的边距为 15 contentSize:

    H:|-(15)-[redView]-(15)-|
    V:|-(15)-[redView(60)]-(15)-|
    

红色视图不明确,因为没有定义它的宽度。 (红色视图和滚动视图之间的水平约束定义了滚动视图的 contentSize,而不是红色视图的宽度。参见 Apple Technical Note 2154。)

您通过添加一个表明红色视图比主视图窄 30pt 的约束来解决这个歧义。因此,通过 control 在红色视图和滚动视图的超级视图之间添加约束 - 从红色视图拖动到滚动视图(这可能是从文档大纲中最容易做到的):

然后选择"equal widths":

将红色视图定义为与主视图宽度相同后,您现在必须更改该约束以修改常量以调整您在红色视图和滚动视图之间提供的边距 contentSize.因此,select 您刚刚添加并编辑它的约束,将常量更改为 -30:

坦率地说,Interface Builder 技术有点麻烦。可能更容易说明如何以编程方式执行此操作:

view.addConstraint(NSLayoutConstraint(item: redView, attribute: .Width, relatedBy: .Equal, toItem: view, attribute: .Width, multiplier: 1.0, constant: -30))