Swift - StackView 和添加约束,以编程方式添加视图到堆栈 - 加载后调整单元格高度?
Posted
技术标签:
【中文标题】Swift - StackView 和添加约束,以编程方式添加视图到堆栈 - 加载后调整单元格高度?【英文标题】:Swift - StackView and Adding Constraints With Programmatically Added Views To Stack - Adjust Cell Hight After Load? 【发布时间】:2020-06-27 22:00:31 【问题描述】:我正在尝试制作一个自定义 tableView 单元格,该单元格具有来自数组图像的 stackView。
我使用了界面生成器并添加了一个水平stackView: 中心 X 中心 Y 最高 +12 底部+12
我正在使用循环来添加 Arranged Subview,它工作正常。但是图像非常小,即使它们不应该是由于它们的 CGRect。但是它们正在被 stackView 调整。
这个想法是保持堆栈居中,同时还使用顶部/底部来调整单元格的高度。
我推断我面临的图像很小的问题是因为 stackView 被初始化为空。所以 stackViews 的高度非常小。并且因为 imageViews 被添加到其中,所以它们会被调整大小以适应。
如何让单元格/stackView 在显示后调整它们的高度?
注意:我在尝试以编程方式向 imageView 添加顶部和底部约束时也遇到了问题。
for pictogram in pictograms
let imageView = UIImageView()
let size = self.bounds.width / CGFloat(pictograms.count + 1)
print("size: ", size)
imageView.frame = CGRect(x: 0, y: 0, width: size, height: size)
imageView.contentMode = .scaleAspectFit
imageView.image = pictogram.image
pictogramStack.addArrangedSubview(imageView)
【问题讨论】:
将 Arranged Subviews 添加到开始为空的堆栈视图中没有问题。您对约束所做的其他事情导致了问题。您需要显示单元原型的图像(确保它显示所有约束),并包含您用于添加排列的子视图的代码。 嘿,唐,将视图添加到堆栈中没有问题。问题是设置单元格的高度。 - 单元格仅包含堆栈视图,其中提到了 4 个约束。 如果你实例化一个UIImageView
,给它的.frame
一个CGRect
,然后将它添加为一个堆栈视图的arrangedSubview
,那个CGRect
将被忽略。这就是为什么我建议你展示你用来添加排列的子视图的代码。
嘿,唐,我就是这样做的。 - 添加代码。
好的 - 再澄清一点...您是否将 imageViews 添加到 horizontal 堆栈视图?你想让它们宽度相等吗?你想要高度 = 宽度(1:1 的比例)?
【参考方案1】:
您以错误的方式使用UIStackView
。堆栈视图将为您安排子视图 - 无需计算宽度和设置框架。
像这样布置你的细胞原型:
请注意,底部约束具有Priority: 999
。自动布局需要进行多次“通过”来布局堆栈视图(特别是在表格视图单元格中)。为底部约束使用 999 的优先级将避免约束冲突错误/警告消息。
像这样设置堆栈视图属性:
使用Distribution: Fill Equally
,我们不必进行任何let size = self.bounds.width / CGFloat(pictograms.count + 1)
类型的计算。
另外,为了让设计时更容易,给堆栈视图一个 Placeholder
固有高度:
这将在运行时没有影响,但可以让您在设计时清楚地看到您的单元格元素。
现在,当您使用图像视图“填充”堆栈视图时,没有 .frame =
设置,您需要添加的唯一约束是高度 == 宽度:
NSLayoutConstraint.activate([
// image view should have 1:1 ratio
imageView.heightAnchor.constraint(equalTo: imageView.widthAnchor),
])
这是一个完整的例子:
class HorizontalImagesStackCell: UITableViewCell
@IBOutlet var theStack: UIStackView!
func addImages(_ pictograms: [String]) -> Void
// cells are reused, so remove any previously added image views
theStack.arrangedSubviews.forEach
$0.removeFromSuperview()
pictograms.forEach s in
// make sure we can load the image
if let img = UIImage(named: s)
// instantiate an image view
let imageView = UIImageView()
// give it a background color so we can see its frame
imageView.backgroundColor = .green
// scale aspect fit
imageView.contentMode = .scaleAspectFit
// set the image
imageView.image = img
NSLayoutConstraint.activate([
// image view should have 1:1 ratio
imageView.heightAnchor.constraint(equalTo: imageView.widthAnchor),
])
// add it to the stack
theStack.addArrangedSubview(imageView)
class ImagesInStackTableViewController: UITableViewController
// we'll display 5 rows of images
// going from 5 images to 4 images ... to 1 image
let myData: [Int] = [5, 4, 3, 2, 1]
let myImages: [String] = [
"img1", "img2", "img3", "img4", "img5"
]
override func viewDidLoad()
super.viewDidLoad()
override func numberOfSections(in tableView: UITableView) -> Int
return 1
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
return myData.count
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let cell = tableView.dequeueReusableCell(withIdentifier: "HCell", for: indexPath) as! HorizontalImagesStackCell
// get the first n number of images
let a: [String] = Array(myImages.prefix(myData[indexPath.row]))
cell.addImages(a)
return cell
使用这 5 张图片:
我们得到了这个结果(图像视图设置为.scaleAspectFit
并具有绿色背景,因此我们可以看到帧):
【讨论】:
嘿,唐,谢谢你写这篇文章。这是一个很棒的指南。 - 尽管我已经遵循了它,但我仍然无法让单元以大于标准单元高度的大小加载。 (无论高度是否设置为自动。) 更新:你的循环对我不起作用。出于某种原因,它两次添加图像。而且尺寸还是不对。回到我最初使用的循环,删除固有尺寸,并重新设置框架,最后,(底部@999 的主要道具)它的工作! :) 还有 - NSLayoutConstraint! 更新 2:看起来真的只是 NSLayoutConstraint 改变了游戏规则。随着@999以上是关于Swift - StackView 和添加约束,以编程方式添加视图到堆栈 - 加载后调整单元格高度?的主要内容,如果未能解决你的问题,请参考以下文章
在 Swift 中以编程方式将视图添加到 stackview