[英]iOS Swift - CollectionView or TableView with fixed height that expands horizontally .. Any Idea?
Hello dear developers!亲爱的开发者您好!
I hope somebody can help me.我希望有人能帮助我。
I'm looking for a way to create a TableView (ie a list with dynamic Sections and Rows) with a fixed height but dynamic width..我正在寻找一种方法来创建具有固定高度但动态宽度的 TableView(即具有动态部分和行的列表)。
Example: The TableView (or CollectionView) has a height of 600px, let's say 10 rows fit into the height.示例:TableView(或 CollectionView)的高度为 600px,假设 10 行适合该高度。 The 11th row should now not be below, but continue to the right..第 11 行现在不应该在下面,而是继续向右..
Below is a picture.下面是一张图片。
I really hope that someone can help me.. thank you in advance for reading.我真的希望有人能帮助我..提前感谢您的阅读。
PS: I invite the one with a solution for a coffee:b PS:我邀请有解决方案的人喝杯咖啡:b
->>> I think the picture shows clearly what I mean <<<- ->>> 我认为图片清楚地表达了我的意思<<<-
This could be done pretty straight-forward as a UICollectionView
with a horizontal flow layout.这可以非常简单地完成,如UICollectionView
和水平流布局。
Quick example:快速示例:
enum MyCellType: Int {
case header
case detail
}
struct MyStruct {
var type: MyCellType = .header
var headerString: String = ""
var detailString: String = ""
var detailValue: String = ""
}
class TestViewController: UIViewController {
var myData: [MyStruct] = []
var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .systemBlue
// some sample data
let headers: [String] = [
"SOFTWARE", "BATTERY", "DEVICE", "HARDWARE", "MLB", "USAGE",
]
let counts: [Int] = [
4, 2, 7, 5, 1, 8,
]
var val: Int = 1
for (i, s) in headers.enumerated() {
let t: MyStruct = MyStruct(type: .header, headerString: s, detailString: "", detailValue: "")
myData.append(t)
for j in 1...counts[i % counts.count] {
let t: MyStruct = MyStruct(type: .detail, headerString: "", detailString: "Detail \(i),\(j)", detailValue: "Val: \(val)")
myData.append(t)
val += 1
}
}
let fl = UICollectionViewFlowLayout()
fl.scrollDirection = .horizontal
fl.minimumLineSpacing = 12
fl.minimumInteritemSpacing = 0
fl.itemSize = CGSize(width: 200, height: 30)
collectionView = UICollectionView(frame: .zero, collectionViewLayout: fl)
collectionView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(collectionView)
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
collectionView.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
collectionView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
collectionView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
collectionView.heightAnchor.constraint(equalToConstant: 300.0),
])
collectionView.register(MyHeaderCell.self, forCellWithReuseIdentifier: "headerCell")
collectionView.register(MyDetailCell.self, forCellWithReuseIdentifier: "detailCell")
collectionView.dataSource = self
collectionView.delegate = self
}
}
extension TestViewController: UICollectionViewDataSource, UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let t = myData[indexPath.item]
if t.type == .header {
let c = collectionView.dequeueReusableCell(withReuseIdentifier: "headerCell", for: indexPath) as! MyHeaderCell
c.label.text = t.headerString
return c
}
let c = collectionView.dequeueReusableCell(withReuseIdentifier: "detailCell", for: indexPath) as! MyDetailCell
c.detailLabel.text = t.detailString
c.valueLabel.text = t.detailValue
// we don't want to show the "separator line" if the next
// item is a "header"
if indexPath.item < myData.count - 1 {
c.hideSepLine(myData[indexPath.item + 1].type == .header)
}
return c
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return myData.count
}
}
class MyHeaderCell: UICollectionViewCell {
let label = UILabel()
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func commonInit() {
label.translatesAutoresizingMaskIntoConstraints = false
label.font = .systemFont(ofSize: 10, weight: .bold)
contentView.addSubview(label)
contentView.backgroundColor = UIColor(white: 0.9, alpha: 1.0)
let g = contentView.layoutMarginsGuide
NSLayoutConstraint.activate([
label.topAnchor.constraint(equalTo: g.topAnchor, constant: 0.0),
label.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 0.0),
label.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: 0.0),
label.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: 0.0),
])
}
}
class MyDetailCell: UICollectionViewCell {
let detailLabel = UILabel()
let valueLabel = UILabel()
let sepLineView = UIView()
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func commonInit() {
detailLabel.font = .systemFont(ofSize: 12.0, weight: .light)
valueLabel.font = .systemFont(ofSize: 12.0, weight: .light)
valueLabel.textColor = .gray
sepLineView.backgroundColor = .lightGray
[detailLabel, valueLabel, sepLineView].forEach { v in
v.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(v)
}
let g = contentView.layoutMarginsGuide
NSLayoutConstraint.activate([
detailLabel.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 16.0),
detailLabel.centerYAnchor.constraint(equalTo: g.centerYAnchor),
valueLabel.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: 0.0),
valueLabel.centerYAnchor.constraint(equalTo: g.centerYAnchor),
sepLineView.leadingAnchor.constraint(equalTo: detailLabel.leadingAnchor),
sepLineView.trailingAnchor.constraint(equalTo: valueLabel.trailingAnchor),
sepLineView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor),
sepLineView.heightAnchor.constraint(equalToConstant: 1.0),
])
}
func hideSepLine(_ b: Bool) {
sepLineView.isHidden = b
}
}
Results:结果:
scrolled a little to the left:向左滚动一点:
scrolled all the way to the left:一直向左滚动:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.