带有 UILabel 模糊布局的 UIScrollView

UIScrollView with UILabel ambiguous layout

我正在尝试用代码设置所有内容。在我的 viewController 中,我声明了这些属性:

var scrollView: UIScrollView!
var font: UIFont?
var label: UILabel!
var fontSize: CGFloat = 50

我的 viewDidLoad 看起来像:

override func viewDidLoad() {
    super.viewDidLoad()

    font = UIFont(name: "HelveticaNeue-UltraLight", size: fontSize)!

    scrollView = UIScrollView()
    scrollView.translatesAutoresizingMaskIntoConstraints = false
    scrollView.backgroundColor = UIColor.lightGray
    view.addSubview(scrollView)

    scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
    scrollView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor).isActive = true
    scrollView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor).isActive = true
    scrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true

    label = UILabel(frame: CGRect.zero)
    label.font = font
    label.lineBreakMode = .byWordWrapping
    label.translatesAutoresizingMaskIntoConstraints = false
    label.numberOfLines = 0
    label.text = """
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam rutrum urna nec risus dapibus, nec sagittis risus vulputate. Nullam volutpat eros nec sagittis eleifend. Nam sit amet convallis sem, quis tempus quam. Cras egestas est at ipsum tincidunt maximus. Vivamus suscipit justo vel sapien blandit, sed vehicula ipsum euismod. Etiam faucibus tortor at augue ullamcorper, at feugiat lorem varius. Quisque at purus vestibulum, varius ex quis, viverra nibh. Nulla ac porta enim. Nulla egestas mauris a pretium rutrum. Interdum et malesuada fames ac ante ipsum primis in faucibus. Etiam lacinia augue nec augue dictum condimentum. Ut aliquam ac lacus a venenatis. Pellentesque egestas libero sed sem rutrum tempus. Duis posuere turpis at lacinia varius.
"""
    scrollView.addSubview(label)
    label.setContentHuggingPriority(UILayoutPriority(rawValue: 249.0), for: .vertical)
    label.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 751.0), for: .horizontal)
    label.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 48.0).isActive = true
    label.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16.0).isActive = true
    label.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16.0).isActive = true
    label.centerXAnchor.constraint(equalTo: scrollView.centerXAnchor)
    label.bottomAnchor.constraint(equalTo: scrollView.contentLayoutGuide.bottomAnchor, constant: -48.0).isActive = true
}

因此,如果我在模拟器中 运行 它,它会按我预期的那样工作,控制台中没有模糊的布局。但是有几件事不起作用。

如果我将 label.text 增加到更多这样的段落:

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam rutrum urna nec risus dapibus, nec sagittis risus vulputate. Nullam volutpat eros nec sagittis eleifend. Nam sit amet convallis sem, quis tempus quam. Cras egestas est at ipsum tincidunt maximus. Vivamus suscipit justo vel sapien blandit, sed vehicula ipsum euismod. Etiam faucibus tortor at augue ullamcorper, at feugiat lorem varius. Quisque at purus vestibulum, varius ex quis, viverra nibh. Nulla ac porta enim. Nulla egestas mauris a pretium rutrum. Interdum et malesuada fames ac ante ipsum primis in faucibus. Etiam lacinia augue nec augue dictum condimentum. Ut aliquam ac lacus a venenatis. Pellentesque egestas libero sed sem rutrum tempus. Duis posuere turpis at lacinia varius.

Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Pellentesque vitae ligula mollis, vehicula mi at, venenatis justo. Nullam id imperdiet odio. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Aenean arcu est, venenatis at sem commodo, condimentum feugiat arcu.

Suspendisse quis malesuada ipsum. Quisque lobortis est in dapibus fermentum. Sed lacinia lacus leo, ac euismod metus faucibus vitae. Curabitur fermentum vulputate vestibulum. Nullam quis turpis ac tortor pharetra accumsan. Aenean finibus lacus quis orci accumsan, iaculis dignissim purus lacinia. Maecenas convallis risus in pulvinar pharetra. Curabitur eu maximus risus. Nunc convallis finibus venenatis. Phasellus nec posuere est, at blandit magna. Nulla rutrum mi id sapien vestibulum eleifend. Nullam sapien nunc, feugiat ut elementum vitae, ultrices in tortor. Integer massa leo, mollis vitae mattis vel, sagittis eu libero. Cras tellus lacus, sodales at nisi ut, dictum mattis risus.

Curabitur at euismod purus, quis posuere nulla. Donec quam mauris, faucibus sed tellus sed, finibus convallis nulla. Ut vehicula consectetur ultricies. Morbi malesuada lorem eget cursus pharetra. Curabitur vitae convallis lacus, in aliquet arcu. Sed interdum ut mauris bibendum tincidunt. Proin consectetur elit diam, eget mattis augue euismod et. Nullam et iaculis dolor, ac scelerisque erat. In non volutpat velit, vitae vulputate augue. Quisque sollicitudin nunc erat, a cursus lorem faucibus sit amet. Suspendisse id augue non nisl congue tincidunt. Duis vulputate massa eu finibus semper. Integer tristique, massa a efficitur accumsan, ligula libero imperdiet enim, quis semper quam risus in sapien. Suspendisse potenti.

Aliquam magna elit, euismod non egestas id, sollicitudin vitae metus. Cras enim magna, placerat sit amet vestibulum non, pellentesque ac lacus. Aenean ut eros auctor diam tincidunt egestas et ac enim. Nunc tempor lorem eget purus eleifend, facilisis efficitur dui feugiat. Sed viverra suscipit luctus. Donec dignissim lorem a urna elementum, id efficitur turpis vestibulum. Praesent laoreet faucibus orci, vel dictum neque ullamcorper in.

标签不再呈现。

或者如果我只使用一个段落,但将字体大小增加到 100,标签也不会 呈现。

最后,即使标签只有一个段落,字体大小为 50,即使看起来 运行 没问题,但如果我单击“查看调试器”,我会得到 "Scrollable content size is ambiguous for UIScrollView"。

我是否遗漏了 UILabels 和 UIScrollViews 的某些内容?是否还有其他事件,属性,或我缺少的约束?

稍微研究一下您的代码后,我发现您遇到了几个问题。

字体未在模拟器中呈现:

这显然是模拟器错误。我在 Xcode 10.2.1/Mojave 10.14.4 上看到它。文本未呈现,但标签大小正确,因此您可以滚动视图并看到垂直指示器移动 down/up。即使您指定的系统字体大于 32,也会出现此问题。在真实设备上(在 iPhone XS 上测试 iOS 12.2),文本呈现正确。

请在 https://bugreport.apple.com 提交错误报告,提供问题的示例代码。

UIScrollView 的可滚动内容大小不明确:

滚动视图的内容需要固定到滚动视图的每个边缘。您要嵌入的标签的前导和尾随约束受限于根视图,而不是滚动视图。它们应该像这样被限制在滚动视图中:

label.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 48.0).isActive = true
label.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 16.0).isActive = true
label.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: -16.0).isActive = true
label.centerXAnchor.constraint(equalTo: scrollView.centerXAnchor).isActive = true
label.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: -48.0).isActive = true

虽然上述更改将解决不明确的内容大小问题,但我建议您一次激活所有约束,因为这样效率更高:

NSLayoutConstraint.activate([
  scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
  scrollView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
  scrollView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
  scrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
  label.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 48.0),
  label.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 16.0),
  label.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: -16.0),
  label.centerXAnchor.constraint(equalTo: scrollView.centerXAnchor),
  label.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: -48.0)
])

我没有发现 contentHuggingPrioritycontentCompressionResistancePriority 行是必需的,但也许您有理由包含这些行。

通过这些更改,模棱两可的内容警告消失了。在我的 iPhone XS 上,纵向和横向布局看起来都正确。

如果您只需要可滚动的文本,为什么不使用 uitextview 并废弃 uilabel 和 uiscrollview 层次结构