UITableViewCell 对齐列以适应内容
UITableViewCell aligning columns to fit content
我正在使用自动布局和原型单元创建一个 UITableView。我希望它表现得更像一个网络 HTML table。每个单元格有四个 "columns",每个都有一个标签,
see here。最终,每一列都应将其宽度调整为所有其他行中最宽的一列。这似乎是一个常见的案例,但我无法找到有关它的任何信息。我在这里遗漏了什么明显的东西吗?
我现在的结果是什么:
1|product name|11 xx|22 yy
1|longer product name|11 xxx|22 yy
1|short|1x|22 yy
我想要什么:
1|product name |11 xx |22 yy
1|longer product name|11 xxx|22 yy
1|short |1x |22 yy
我希望这有任何意义,否则请告诉我。谢谢!
创建二维 tables 一直是 iOS 上的 PiTA。我强烈建议您找到现有的解决方案并为自己节省很多时间。
除非你是为自己做的(又名学习),在这种情况下你需要:
- 在后台某处预先计算单元格大小并在任何地方使用它
- 或者在行中的第一个单元格上添加宽度限制(大于或等于)。让 UIKit 为您处理布局。每次 UIKit 更新单元格的宽度时,检查它是否与约束一样大,如果它更大,则需要更新具有新的最大宽度的所有行的约束。
第一种方法最简洁,可能也是唯一正确的解决方案,但如果您的应用可以用很少的性能换取开发时间,则可以尝试第二种方法。
编辑:我刚刚查看了您的图片。为什么你在这里需要 2d table?
您只需要:
|-amount-name-iDunnoWhatIsIt-price-|
其中:
name
标签左对齐
iDunnoWhatIsIt
标签右对齐
price
和 amount
具有固定宽度
现在您需要决定哪个更重要 name
或 iDunnoWhatIsIt
。并基于它更新它们的compression resistance
,所以重要的一个不会被修剪(我假设它会是iDunnoWhatIsIt
)
您可以使用嵌入式 UIStackView
s
构建 "grid" 个标签
使用一个 "outer" 水平堆栈视图来容纳 4 个 "inner" 堆栈视图,用作 4 "columns".
将外部堆栈视图嵌入 UIScrollView
以防内容超出可用区域。
结果如下所示:
前两个 "column" 堆栈视图有 .alignment = .leading
,第三个和第四个有 .alignment = .trailing
。如您所见,每个 "column" 堆栈视图都会拉伸其宽度以适应最宽的标签。
下面是生成该示例的一些代码:
class StackGridViewController: UIViewController {
var myData = [[String]]()
override func viewDidLoad() {
super.viewDidLoad()
// init 30 rows of data
for i in 1...30 {
myData.append(["\(i)", "Product Name", "12 xx", "34 xx"])
}
// make a few of the rows different
for i in [2, 15, 21] {
// longer "column B"
myData[i][1] = "Longer Product Name"
// longer "column C"
myData[i+2][2] = "1234 xx"
// longer "column D"
myData[i+4][3] = "3456 xx"
}
// and one row with the longest values
// longest "column B"
myData[9][1] = "The Longest Product Name"
// longest "column C"
myData[9][2] = "123456 xx"
// longest "column D"
myData[9][3] = "345678 xx"
// create a horizontal stack view
let outerSV = UIStackView()
outerSV.translatesAutoresizingMaskIntoConstraints = false
outerSV.axis = .horizontal
outerSV.distribution = .fill
// "column" spacing
outerSV.spacing = 12
// add 4 "column" vertical stack views
for col in 0..<4 {
let columnSV = UIStackView()
columnSV.translatesAutoresizingMaskIntoConstraints = false
columnSV.axis = .vertical
// align leading for first two columns, trailing for 3rd and 4th
columnSV.alignment = col < 2 ? .leading : .trailing
columnSV.distribution = .fill
// "row" spacing
columnSV.spacing = 8
// add a label for each data "row"
for row in 0..<myData.count {
let v = UILabel()
v.backgroundColor = UIColor(white: 0.9, alpha: 1.0)
v.font = UIFont.systemFont(ofSize: 13.0, weight: .light)
v.text = myData[row][col]
columnSV.addArrangedSubview(v)
}
// add the "column" stack view to the outer stack view
outerSV.addArrangedSubview(columnSV)
}
// create a scroll view
let scrollView = UIScrollView()
scrollView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(scrollView)
// constrain it to all four sides with 20-pt padding on top/bottom, 8-pt padding leading/trailing
NSLayoutConstraint.activate([
scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20.0),
scrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -20.0),
scrollView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 8.0),
scrollView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -8.0),
])
// add the outer stack view to the scroll view
scrollView.addSubview(outerSV)
// constrain it to all four sides (which will also define .contentSize (the "scrollable area")
NSLayoutConstraint.activate([
outerSV.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 0.0),
outerSV.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: 0.0),
outerSV.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 0.0),
outerSV.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: 0.0),
])
}
}
我正在使用自动布局和原型单元创建一个 UITableView。我希望它表现得更像一个网络 HTML table。每个单元格有四个 "columns",每个都有一个标签, see here。最终,每一列都应将其宽度调整为所有其他行中最宽的一列。这似乎是一个常见的案例,但我无法找到有关它的任何信息。我在这里遗漏了什么明显的东西吗?
我现在的结果是什么:
1|product name|11 xx|22 yy
1|longer product name|11 xxx|22 yy
1|short|1x|22 yy
我想要什么:
1|product name |11 xx |22 yy
1|longer product name|11 xxx|22 yy
1|short |1x |22 yy
我希望这有任何意义,否则请告诉我。谢谢!
创建二维 tables 一直是 iOS 上的 PiTA。我强烈建议您找到现有的解决方案并为自己节省很多时间。
除非你是为自己做的(又名学习),在这种情况下你需要:
- 在后台某处预先计算单元格大小并在任何地方使用它
- 或者在行中的第一个单元格上添加宽度限制(大于或等于)。让 UIKit 为您处理布局。每次 UIKit 更新单元格的宽度时,检查它是否与约束一样大,如果它更大,则需要更新具有新的最大宽度的所有行的约束。
第一种方法最简洁,可能也是唯一正确的解决方案,但如果您的应用可以用很少的性能换取开发时间,则可以尝试第二种方法。
编辑:我刚刚查看了您的图片。为什么你在这里需要 2d table?
您只需要:
|-amount-name-iDunnoWhatIsIt-price-|
其中:
name
标签左对齐
iDunnoWhatIsIt
标签右对齐
price
和 amount
具有固定宽度
现在您需要决定哪个更重要 name
或 iDunnoWhatIsIt
。并基于它更新它们的compression resistance
,所以重要的一个不会被修剪(我假设它会是iDunnoWhatIsIt
)
您可以使用嵌入式 UIStackView
s
使用一个 "outer" 水平堆栈视图来容纳 4 个 "inner" 堆栈视图,用作 4 "columns".
将外部堆栈视图嵌入 UIScrollView
以防内容超出可用区域。
结果如下所示:
前两个 "column" 堆栈视图有 .alignment = .leading
,第三个和第四个有 .alignment = .trailing
。如您所见,每个 "column" 堆栈视图都会拉伸其宽度以适应最宽的标签。
下面是生成该示例的一些代码:
class StackGridViewController: UIViewController {
var myData = [[String]]()
override func viewDidLoad() {
super.viewDidLoad()
// init 30 rows of data
for i in 1...30 {
myData.append(["\(i)", "Product Name", "12 xx", "34 xx"])
}
// make a few of the rows different
for i in [2, 15, 21] {
// longer "column B"
myData[i][1] = "Longer Product Name"
// longer "column C"
myData[i+2][2] = "1234 xx"
// longer "column D"
myData[i+4][3] = "3456 xx"
}
// and one row with the longest values
// longest "column B"
myData[9][1] = "The Longest Product Name"
// longest "column C"
myData[9][2] = "123456 xx"
// longest "column D"
myData[9][3] = "345678 xx"
// create a horizontal stack view
let outerSV = UIStackView()
outerSV.translatesAutoresizingMaskIntoConstraints = false
outerSV.axis = .horizontal
outerSV.distribution = .fill
// "column" spacing
outerSV.spacing = 12
// add 4 "column" vertical stack views
for col in 0..<4 {
let columnSV = UIStackView()
columnSV.translatesAutoresizingMaskIntoConstraints = false
columnSV.axis = .vertical
// align leading for first two columns, trailing for 3rd and 4th
columnSV.alignment = col < 2 ? .leading : .trailing
columnSV.distribution = .fill
// "row" spacing
columnSV.spacing = 8
// add a label for each data "row"
for row in 0..<myData.count {
let v = UILabel()
v.backgroundColor = UIColor(white: 0.9, alpha: 1.0)
v.font = UIFont.systemFont(ofSize: 13.0, weight: .light)
v.text = myData[row][col]
columnSV.addArrangedSubview(v)
}
// add the "column" stack view to the outer stack view
outerSV.addArrangedSubview(columnSV)
}
// create a scroll view
let scrollView = UIScrollView()
scrollView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(scrollView)
// constrain it to all four sides with 20-pt padding on top/bottom, 8-pt padding leading/trailing
NSLayoutConstraint.activate([
scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20.0),
scrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -20.0),
scrollView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 8.0),
scrollView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -8.0),
])
// add the outer stack view to the scroll view
scrollView.addSubview(outerSV)
// constrain it to all four sides (which will also define .contentSize (the "scrollable area")
NSLayoutConstraint.activate([
outerSV.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 0.0),
outerSV.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: 0.0),
outerSV.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 0.0),
outerSV.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: 0.0),
])
}
}