【问题标题】:UIStackView, Autolayout, Table CellsUIStackView,自动布局,表格单元格
【发布时间】:2020-01-21 01:34:45
【问题描述】:

我正在创建一个带有图像和标签的 UIStackView 自定义 UIControl 将在自定义 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 是图像的高度(因为它比标签文本高),以及图像的宽度 + 标签文本。 (然后由于该约束固定显示完整的表格单元格宽度)。而且因为这些是在这些组件的初始化时设置的,所以我希望它们具有固有的高度和宽度以传递给UIStackView。

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

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

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

【问题讨论】:

  • 是的,这就是我所期望的。与带有文本的标签相同。我希望我的 24x29 图像将堆栈视图的高度设置为 29,并将宽度设置为 24 + 标签的宽度。如果我只是固定堆栈视图的顶部和左侧,我可以看到图像和标签,但这不会影响我的控件尺寸。你知道我要去哪里或想错了吗?
  • 这就是我困惑的地方。文档说“没有额外的限制,系统会根据其内容计算堆栈视图的大小”。所以我的堆栈视图正在根据其内容进行扩展,但这并没有扩展超级视图,这就是为什么我看不到它?如果是这样,有没有办法在不设置特定高度/宽度的情况下实现我想要的流体尺寸?顺便说一句,感谢您的帮助!

标签: swift uitableview autolayout


【解决方案1】:

您的问题的问题在于,您显示的大部分代码都是伪造的,以至于很难猜测您实际上在做什么。你声称在你的表格视图单元格中(我认为它是一个表格视图单元格子类)你说的是

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
}

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

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

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

您所做的根本不是如何制作和配置表格视图单元格(您应该在cellForRowAt 中进行工作,而不是在单元格的初始化程序中硬编码单元格的图像视图和标签内容),但是给出你所展示的,图像视图确实调整了堆栈视图的大小,而堆栈视图也调整了单元格的大小(与我自己最初的预期相反)。

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

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

【讨论】:

  • 我认为你让我走上了正确的道路。我对伪造的代码进行了一些修复——我在 SO 中快速输入以将概念放在那里——对于拼写错误感到抱歉。我必须重新调整我的想法——这就是为什么我需要另一双眼睛。感谢您的帮助。
猜你喜欢
  • 2015-03-13
  • 1970-01-01
  • 1970-01-01
  • 2015-08-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-22
  • 2013-05-16
相关资源
最近更新 更多