如何使用 UICollectionView 在单元格左侧创建部分以及 headers?
How to create sections along with headers on the left of cells with UICollectionView?
我不确定我的问题是否很好。如果你考虑改进它,那就去做吧:) 但很快这就是我的意思:
- 每个orange框是新的section框header(宽度,高度是静态的)。
- 这将链接到包含部分的获取结果控制器
- 黄色 单元格的宽度始终占据屏幕的其余部分,并且具有自动的高度尺寸(取决于文本的长度)。
请告诉我:
- 是否可以用
UICollectionView
做到这一点?
- 如何为黄色单元格设置自动高度尺寸?
- 如何使黄色像图片上那样浮动?
我不认为你可以做那个部分 header.but 你用 collectionview cell.Adjust 相应地调整其他单元格的大小。
我想你可以使用 UITableViewController 做类似的事情。
想法是:
- 将单元格自定义为左右两部分。
- 节的第一项左边用于节header,注意
CellView
和ContentView
的Clip Subviews
不要勾选
- 需要调整部分最后一项的高度,以免重叠。
示例代码如下:
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)
}
}
更新:
实际上上面的解决方案有一个错误,当滚动到顶部直到第一部分消失,然后你会看到它得到 re-rendered 并且布局将被破坏。
有更好的方法。
将内部视图(橙色)添加到 headerView 中,它将在 tableCells 上呈现。记得设置高度 header > 0。在这种情况下,单元格只需要包含正确的部分(黄色)。
不过,您需要调整最后一项的高度。
示例代码:
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
}
}
我不确定我的问题是否很好。如果你考虑改进它,那就去做吧:) 但很快这就是我的意思:
- 每个orange框是新的section框header(宽度,高度是静态的)。
- 这将链接到包含部分的获取结果控制器
- 黄色 单元格的宽度始终占据屏幕的其余部分,并且具有自动的高度尺寸(取决于文本的长度)。
请告诉我:
- 是否可以用
UICollectionView
做到这一点? - 如何为黄色单元格设置自动高度尺寸?
- 如何使黄色像图片上那样浮动?
我不认为你可以做那个部分 header.but 你用 collectionview cell.Adjust 相应地调整其他单元格的大小。
我想你可以使用 UITableViewController 做类似的事情。
想法是:
- 将单元格自定义为左右两部分。
- 节的第一项左边用于节header,注意
CellView
和ContentView
的Clip Subviews
不要勾选 - 需要调整部分最后一项的高度,以免重叠。
示例代码如下:
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)
}
}
更新: 实际上上面的解决方案有一个错误,当滚动到顶部直到第一部分消失,然后你会看到它得到 re-rendered 并且布局将被破坏。
有更好的方法。
将内部视图(橙色)添加到 headerView 中,它将在 tableCells 上呈现。记得设置高度 header > 0。在这种情况下,单元格只需要包含正确的部分(黄色)。 不过,您需要调整最后一项的高度。
示例代码:
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
}
}