Swift - StackView 和通过以编程方式添加的视图添加约束到堆栈 - 加载后调整单元格高度?
Swift - StackView and Adding Constraints With Programmatically Added Views To Stack - Adjust Cell Hight After Load?
我正在尝试制作一个自定义 tableView 单元格,该单元格具有来自数组图像的 stackView。
我使用了界面生成器并添加了一个水平 stackView:
中心 X
Y中心
顶部+12
底部+12
我正在使用循环添加排列子视图,它工作正常。但是图像非常小,尽管它们不应该是由于它们的 CGRect。但是它们正在被 stackView 调整。
我们的想法是保持堆栈居中,同时还使用 top/bottom 调整单元格的高度。
我推断我面临的图像较小的问题是因为 stackView 初始化为空。所以 stackViews 的高度非常小。因为 imageViews 被添加到其中,所以它们会被调整大小以适应。
怎样才能让一个cell/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)
}
您使用 UIStackView
的方式有误。堆栈视图将为您安排子视图 - 无需计算宽度和设置框架。
像这样布局你的单元格原型:
请注意底部约束有 Priority: 999
。 Auto-layout 需要多次“通过”来布置堆栈视图(特别是在 table 视图单元格中)。对底部约束使用优先级 999 将避免约束冲突错误/警告消息。
像这样设置堆栈视图属性:
使用 Distribution: Fill Equally
我们不需要做任何 let size = self.bounds.width / CGFloat(pictograms.count + 1)
类型的计算。
此外,为了使 design-time 更容易一些,给堆栈视图一个 Placeholder
固有高度:
在 run-time 时 没有 效果,但可以让您在设计时清楚地看到您的单元格元素。
现在,当您用图像视图“填充”堆栈视图时,没有 .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 {
[=11=].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
并且有绿色背景所以我们可以看到框架):
我正在尝试制作一个自定义 tableView 单元格,该单元格具有来自数组图像的 stackView。
我使用了界面生成器并添加了一个水平 stackView: 中心 X Y中心 顶部+12 底部+12
我正在使用循环添加排列子视图,它工作正常。但是图像非常小,尽管它们不应该是由于它们的 CGRect。但是它们正在被 stackView 调整。
我们的想法是保持堆栈居中,同时还使用 top/bottom 调整单元格的高度。
我推断我面临的图像较小的问题是因为 stackView 初始化为空。所以 stackViews 的高度非常小。因为 imageViews 被添加到其中,所以它们会被调整大小以适应。
怎样才能让一个cell/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)
}
您使用 UIStackView
的方式有误。堆栈视图将为您安排子视图 - 无需计算宽度和设置框架。
像这样布局你的单元格原型:
请注意底部约束有 Priority: 999
。 Auto-layout 需要多次“通过”来布置堆栈视图(特别是在 table 视图单元格中)。对底部约束使用优先级 999 将避免约束冲突错误/警告消息。
像这样设置堆栈视图属性:
使用 Distribution: Fill Equally
我们不需要做任何 let size = self.bounds.width / CGFloat(pictograms.count + 1)
类型的计算。
此外,为了使 design-time 更容易一些,给堆栈视图一个 Placeholder
固有高度:
在 run-time 时 没有 效果,但可以让您在设计时清楚地看到您的单元格元素。
现在,当您用图像视图“填充”堆栈视图时,没有 .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 {
[=11=].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
并且有绿色背景所以我们可以看到框架):