Ich denke, Sie können UITableViewController verwenden, um etwas ähnliches zu tun.
![enter image description here](https://i.stack.imgur.com/tZOTk.png)
Die Idee ist:
- Passen Sie die Zelle als zwei Teile, links und rechts.
- Die linke des ersten Elements eines Abschnitts wird für Abschnittsüberschrift verwendet, beachten Sie, dass
Clip Subviews
von CellView
und ContentView
deaktiviert werden sollte.
- Die Höhe des letzten Elements eines Abschnitts muss angepasst werden, damit keine Überlappung entsteht. Hier
ist der Beispielcode:
class ViewController: UITableViewController {
struct Item {
var height: CGFloat = 0
}
var itemDic: [Int: [Item]]!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
itemDic = [0 : [Item(height: 10), Item(height: 30), Item(height: 50)],
1 : [Item(height: 20), Item(height: 10)],
2 : [Item(height: 40), Item(height: 30), Item(height: 20)]]
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return itemDic.count
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return itemDic[section]!.count
}
let sectionHeaderHeight: CGFloat = 100
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
let section = indexPath.section
let row = indexPath.row
let items = itemDic[section]!
var height = items[row].height
if (row == items.count - 1) {
var total: CGFloat = 0
for i in items {
total += i.height + 10
}
if(sectionHeaderHeight + 10 > total){
height += (sectionHeaderHeight + 10 - total)
}
}
return height + 10
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let section = indexPath.section
let row = indexPath.row
let items = itemDic[section]!
let cell = tableView.dequeueReusableCellWithIdentifier("Cell")!
let orangeView = cell.viewWithTag(100)!
let yellowView = cell.viewWithTag(101)!
if(row == 0){
let orangeFrame = orangeView.frame
orangeView.frame = CGRect(origin: orangeFrame.origin, size: CGSize(width: orangeFrame.width, height: sectionHeaderHeight))
}
let yellowFrame = yellowView.frame
let height = items[row].height
yellowView.frame = CGRect(origin: yellowFrame.origin, size: CGSize(width: yellowFrame.width, height: height))
return cell
}
override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
let orangeView = cell.viewWithTag(100)!
let yellowView = cell.viewWithTag(101)!
let orangeFrame = orangeView.frame
print(orangeFrame)
let yellowFrame = yellowView.frame
print(yellowFrame)
}
}
Update: Eigentlich gibt es einen Fehler in obigen Lösung, wenn bis der erste Abschnitt nach oben Scrollen verschwindet, und dann werden Sie es zu sehen bekommen neu gerendert und das Layout wird gebrochen.
Es gibt einen besseren Weg, dies zu tun.
Fügen Sie eine innere Ansicht (orange) in die headerView hinzu, die über die TableCells gerendert wird. Denken Sie daran, die Höhe der Kopfzeile> 0 festzulegen. In diesem Fall muss die Zelle nur den rechten Teil (gelb) enthalten. Noch müssen Sie die Höhe des letzten Artikels anpassen.
Beispielcode:
class ViewController: UITableViewController {
struct Item {
var height: CGFloat = 0
}
var itemDic: [Int: [Item]]!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
itemDic = [0 : [Item(height: 10), Item(height: 30), Item(height: 50), Item(height: 20)],
1 : [Item(height: 20), Item(height: 10)],
2 : [Item(height: 40), Item(height: 30), Item(height: 20), Item(height: 30)]]
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return itemDic.count
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return itemDic[section]!.count
}
let sectionHeaderHeight: CGFloat = 100
let innerViewOffset: CGFloat = 10
override func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
// Must > 0
return innerViewOffset
}
override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let view = UIView(frame: CGRect())
view.backgroundColor = UIColor.blueColor()
let innerView = UIView(frame: CGRect(x: 0, y: innerViewOffset, width: 100, height: 100))
innerView.backgroundColor = colorForSection(section)
view.addSubview(innerView)
return view
}
func colorForSection(section: Int) -> UIColor {
let colors = [UIColor.greenColor(), UIColor.redColor(), UIColor.purpleColor()]
return colors[section]
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
let section = indexPath.section
let row = indexPath.row
let items = itemDic[section]!
var height = items[row].height
if (row == items.count - 1) {
var total: CGFloat = 0
for i in items {
total += i.height + 10
}
if(sectionHeaderHeight + 10 > total){
height += (sectionHeaderHeight + 10 - total)
}
}
return height + 10
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell")!
return cell
}
}
Wenn ich gut verstehe ... das einzige Problem damit für mich wird entstehen, wenn ich versuche, Höhe der Zellen in Abschnitt zu schätzen, um die Höhe der letzten Zelle in Abschnitt zu bestimmen. Habe ich recht? –
Eigentlich gibt es einen Bug, mit dem ich nicht umgehen kann. Wenn man nach oben scrollt, sieht man, dass der erste Teil neu gerendert wird und der erste Teil abgedeckt wird, das ist nicht das was du willst. Ich finde eine bessere Lösung für Sie. Siehe die Änderung. – dichen