【问题标题】:Design UIView so that it can dynamically change its height based on the content height设计 UIView 使其可以根据内容高度动态改变其高度
【发布时间】:2019-07-16 08:16:42
【问题描述】:

XIB 文件中,我有一个与同名类相关的CustomView

视图内容非常简单。

有一个垂直的stackview,在stackview里面有两个labelsstackview 与包含它的视图垂直对齐:

第一个标签(标题)包含一个静态文本(总是几个字符)。 第二个标签(字幕)可以有可变长度的文本。

我将此CustomView 与其他类似视图添加为Content View 的子视图,因为它是一个“行”。

for i in 0...aViews.count {

   var v = CustomView(frame: CGRect(x: 0, y: _y, width: 320, height: 100))
   v.labelText = "my long label text ..."
   contentView.addSubview(v)
   // ...
}

你可以想象,标题标签应该有一个固定的位置(顶部和左侧),即不能有一个标题从10点开始,另一个从14点开始。

我必须承认,我天真地认为标签的位置会由我垂直对齐 stackview 的相同事实自动管理。我错了,我没有发现任何问题,直到他们告诉我第二个标签,即字幕,可以包含多行。

我直接在storyboard的标签里加了几行,发现:

  1. stackview 的容器不会根据其内容的height 更改其height

  2. “固定”元素的位置可能垂直居中但不固定;

我需要的是:

  • 标签应“分组”并垂直对齐:从第一个标签的顶部到容器的上边框和从第二个标签的底部到底部边框的间距应该相同;
  • 当第二个标签必须显示多于一行时,容器视图应相应更改其高度;

这可能吗?我应该如何设计我的视图?

【问题讨论】:

  • 这是什么contentView.addSubview(v)??它有什么作用?
  • 您的contentViewCustomView 没有任何限制。
  • @dahiya_boy:正如我所解释的,我向 contentView 添加了许多相似的视图(想象它像一个 tableview,但任何单元格的高度不同,标题和副标题的参数也不同)
  • @CerlinBoss:当前使用框架定位单个自定义视图。你在想什么样的约束?
  • @3000 这是非常糟糕的做法。开发人员避免使用滚动视图并在这种情况下使用表格视图。以后管理scrollview及其内容会很头疼。

标签: ios swift uiview autolayout storyboard


【解决方案1】:

好的 - 看看你的项目,你离得不远了......只是几个关键项目。

  1. 在您的 CustomView.xib 中,Fixed LabelDate Label 之间没有约束。结果是Date Label 从视图底部向上增长,没有任何东西可以阻止它。

  2. 同样在您的 CustomView.xib 中,您将 Fixed Label 限制在后沿...我假设您希望它与 Date Label 左对齐

  3. 在创建自定义视图时,您将高度限制设置为 100 - 这违背了允许内容确定大小的目的。

  4. 在 CustomView 类中,您已将 contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight] 注释掉。那条线应该在那里。

  5. 在您的视图控制器中,您向contentView 添加了一个低优先级的高度约束。最好的选择是使其成为占位符约束(双击约束,然后选择占位符复选框)。这样,约束在运行时被移除,但在设计期间就存在(Storyboard 不会抱怨)。

  6. 您正在做一些其他不必要的事情 - 可能您正在尝试不同的东西来让它发挥作用。

  7. 视图设置(添加视图)最好在 viewDidLoad() 中完成 -- 绝对不是viewDidLayoutSubviews()

  8. 我猜想,在您的 CustomView 中,您可能想要限制 Date Label 的前导和尾随,而不是显式宽度 200,允许它基于水平拉伸设备宽度...但我将其设置为 200。

如果您可以遵循该信息,您应该能够解决问题。但是,我将项目作为 GitHub 存储库为您提供,因此您可以使其处于“工作”状态,这样您就可以看到更改。

这里是回购链接:https://github.com/DonMag/ATester2

结果如下:

然后向上滚动了一下:

【讨论】:

  • 首先谢谢,我还没有机会下载你的项目,但图像清楚地显示了我正在搜索的结果。我试图回答你的一个观点:(3)我设置它是因为我错误地认为有必要给视图框架一个起始高度:在我的测试中,我发现如果我删除了那条线,“图形”结果是100(嗯...也许!),但视图高度的输出打印为 25(可能是标签的固有内容大小?)
  • 我试过了,这正是我想要做的。 :-) 我看到你删除了很多东西。确实(第 6 点)我在尝试,但我很确定我需要滚动视图的约束(例如 contentLayoutGuideheightAnchor),你的版本更简单(当然也更干净)跨度>
【解决方案2】:

我认为您正在混合外部视图的绝对定位(即手动设置框架)并对其内部组件使用自动布局约束,并且错误地期望动态自动布局部分以某种方式“一直向上”到外部视图。要让自动布局做到这一点,您需要一直使用自动布局,包括CustomViews 在您的contentView 中的定位方式。

如果出于某种原因您不想为此使用 TableView 或 CollectionView,例如,您也可以尝试将您的 CustomViews 作为排列的子视图添加到具有顶部/底部/前导/尾随约束的垂直堆栈视图到contentView,然后将CustomView 的“Align Center Y”约束替换为“Align Top”和“Align Bottom”约束,如果它们需要更多垂直空间,则实际上允许标签从内部“推动”。

编辑这里有一个简单的草图来说明该设置:

编辑 2 这里有几个屏幕截图可以进一步澄清。使用这样的基本布局:

运行时的结果将如下所示:

请注意,UIStackView 在此示例中使用“等间距”分布。如果您想以编程方式创建和添加您的CustomViews,请使用 StackView 的func addArrangedSubview(_ view: UIView)

祝你好运!

【讨论】:

  • 至于您的第一段,是与否,即:我想我可以这样做:stackoverflow.com/questions/39526929/… 并获得视图的“新”高度以在设计中使用它帧。你的草图很酷,但我不明白为什么我需要一个stackview(我目前使用一个简单的视图。如果我必须添加带有自动布局的子视图,我不能为子视图添加约束吗?)
  • 您完全可以自己将约束添加到您的子视图中,没问题。使用“StackView”只是为您节省了一些时间,无需手动管理约束(如果您只想“堆叠”子视图)。
  • 我们谈论的观点有点复杂:在我的问题中,我必须去除很多“噪音”以避免人们迷失在不重要的细节上。例如:在 contentView 的顶部,有一个直接创建到情节提要中的 imageview,具有复杂的自动布局约束。因此,stackview 应该放在该视图下方并固定在其底部。下周一可以试试,谢谢
  • 我做了一点尝试,但它不起作用:当您将安排的子视图添加到堆栈视图时,您必须提供这样的约束:aView.heightAnchor.constraint(equalToConstant: 100)。现在,即使您添加了很多文本(除了该文本似乎在各个方向流动的事实),标签中的文本也无法在视图实例化时调整视图大小:视图显然保持相同的高度
  • 关于equalToConstant: 100 部分:不要给视图明确的静态高度约束!这正是我们不想要的。我们想要的是系统在运行时动态计算高度。因此,只需给它足够的约束,布局引擎就可以计算出每个组件实际需要多少空间。请参阅我的答案中的示例以了解实现此目的的一种方法。
猜你喜欢
  • 1970-01-01
  • 2023-04-10
  • 1970-01-01
  • 1970-01-01
  • 2015-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多