UIStackView、自动布局、Table 个单元格

UIStackView, Autolayout, Table Cells

我正在用自定义 UIControl 中的图像和标签创建一个 UIStackView,它将在自定义 UITableViewCell 中,除了我的 UIStackView 有0 和 XCode 的高度和宽度抱怨打破约束。只有当我明确设置高度和宽度时,它才能正确显示,这是我不想要的,因为标签文本因单元格而异。 (这一切都是以编程方式发生的。)

设置 在我的 UITableViewCell 中,我有以下内容:

override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
  super.init(style: style, reuseIdentifier: reuseIdentifier)
  contentView.addSubview(control)

  NSLayoutConstraint.activate([
    control.bottomAnchor.constraint(equalTo: contentView.bottomAnchor),
    control.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
    control.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
    control.topAnchor.constraint(equalTo: contentView.topAnchor),
  ])
}

// empty coder init as well

private let control: MyControl = {
  let control: MyControl = MyControl()
  control.translatesAutoresizingMaskIntoConstraints = false
  return control
}()

MyControl中,我只有UIStackView、一个UIImageView和一个UILabel。为了不让您厌烦代码...只有 UIStackView(水平轴)使用约束,将其固定到四个边。 UIImageView(以图像启动)是一个排列的子视图,UILabel 是另一个(以默认文本启动)。

如果你想看代码:

class MyControl: UIControl {

  override init(frame: CGRect) {
    super.init(frame: frame)
    addSubview(stackView)
    stackView.addArrangedSubview(icon)
    stackView.addArrangedSubview(contentLabel)

    NSLayoutConstraint.activate([
      stackView.bottomAnchor.constraint(equalTo: bottomAnchor),
      stackView.leadingAnchor.constraint(equalTo: leadingAnchor),
      stackView.trailingAnchor.constraint(equalTo: trailingAnchor),
      stackView.topAnchor.constraint(equalTo: topAnchor),
    ])
  }

// empty coder init as well

  private let contentLabel: UILabel = {
    let label: UILabel = UILabel()
    label.text = "Initial text"
    return label
  }()

  private let icon: UIImageView = {
    let iv: UIImageView = UIImageView(image: UIImage(named: "placeholder_image")!)
    iv.contentMode = .scaleAspectFit
    return iv
  }()

  private let stackView: UIStackView = {
    let stackView: UIStackView = UIStackView()
    stackView.axis = .horizontal
    stackView.translatesAutoresizingMaskIntoConstraints = false
    return control
  }()
}

我期待什么 期望 UIControl 是图像的高度(因为它比标签文本高),以及图像的宽度 + 标签文本。 (然后由于该约束固定而显示完整的 table 单元格宽度)。而且因为这些是在这些组件的初始化时设置的,所以我希望它们具有固有的高度和宽度以传递给 UIStackView.

我得到了什么 高度和宽度为零,XCode 投诉破坏约束。如果我删除所有约束,我不会收到任何投诉,但什么也不会出现(好像高度和宽度为零但 XCode 不在乎,因为我没有设置任何约束)。

我试过的 从字面上看,布局约束的每种组合,包括对所有内容的 none 以及对所有内容的尽可能多的限制。我 喜欢 的是图像 + 标签文本设置 UIStackView 的高度和宽度,然后设置 UIControl 的高度和宽度,然后在 UITableViewCell 中设置高度(我知道我的宽度为 100% - 稍后会更改)。

其他注意事项 我的 UITableViewCell 没有什么特别之处会在这里引起任何问题,除了在我的实际代码中,我在 MyControl 上方有一个多行标签,它应该(并且确实)导致我的 UITableViewCell扩展高度。

您问题的问题在于,您展示的代码中有太多是伪造的,因此很难猜测您实际上在做什么。您声称在您的 table 视图单元格中(我假设它是一个 table 视图单元格子类)您说的是

override init(frame: CGRect) {
    super.init(frame: frame)

但这永远不会编译,因为 init(frame:) 不是 UITableViewCell 的指定初始化程序。您有这样的代码:

private let contentLabel: UILabel = {
    let label: UILabel = UILabel()
    label.text = "Initial text"
    return label
}

但这永远不会编译,因为函数不是标签。

如果我们考虑到所有这些并修复您的代码,就很难看出您会做错什么。我更正了您的代码以便它可以编译,并且在我的 table 视图中得到了这个:

这可能不是您想要的,但图像视图肯定会根据自己的高度调整单元格的大小。

您所做的根本不是制作和配置 table 视图单元格的方式(您应该在 cellForRowAt 中完成工作,而不是对单元格的图像视图和标签内容进行硬编码在单元格的初始值设定项中),但鉴于您所显示的内容,图像视图确实调整了堆栈视图的大小,而堆栈视图确实调整了单元格的大小(与我自己的初始预期相反)。

另一个问题是,如果不解决哪个应该占主导地位的歧义,就不能将图像视图和标签放入自动布局情况。我添加了这一行来做到这一点:

    iv.setContentHuggingPriority(.defaultLow+1, for: .horizontal)