如何使用 UICollectionView 在单元格左侧创建部分以及标题?
Posted
技术标签:
【中文标题】如何使用 UICollectionView 在单元格左侧创建部分以及标题?【英文标题】:How to create sections along with headers on the left of cells with UICollectionView? 【发布时间】:2016-04-29 05:33:51 【问题描述】:我不确定我的问题是否写得很好。如果您考虑改进它,那就去做吧:) 但我的意思是:
每个橙色框都是新节框的标题(宽度和高度是静态的)。 这将链接到带有部分的获取结果控制器 黄色单元格始终占据屏幕其余部分的宽度,并具有自动高度标注(取决于文本长度)。请告诉我:
-
使用
UICollectionView
是否可以做到这一点?
如何为黄色单元格设置自动高度尺寸?
如何像在图像上一样浮动黄色?
【问题讨论】:
【参考方案1】:我认为你可以使用 UITableViewController 来做类似的事情。
这个想法是:
将单元格自定义为左右两部分。 section第一项的左边用于section header,注意CellView
和ContentView
的Clip Subviews
不要勾选。
section最后一项的高度需要调整,不重叠。
这里是示例代码:
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)
更新: 其实上面的解决方案有一个bug,当滚动到顶部直到第一部分消失,然后你会看到它被重新渲染并且布局会被破坏。
有更好的方法来做到这一点。
在 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
【讨论】:
如果我理解得很好......当我尝试估计部分中单元格的高度以确定部分中最后一个单元格的高度时,我会遇到唯一的麻烦。我说的对吗? 实际上这种方式有一个我不知道如何处理的错误,当滚动到顶部时,您会看到第一部分被重新渲染并且第一项被覆盖,这不是你的想。我想出一个更好的解决方案给你。查看编辑。【参考方案2】:我不认为你可以做那个部分的标题。但是你可以用 collectionview 单元格来做。相应地调整其他单元格的大小。
【讨论】:
使用 fetched results controller 会不太舒服。以上是关于如何使用 UICollectionView 在单元格左侧创建部分以及标题?的主要内容,如果未能解决你的问题,请参考以下文章
如何快速在uicollectionview中动态访问单元格属性
如何使用 UICollectionView 在单元格左侧创建部分以及标题?
如何使用 UICollectionView 的 selectItem 在 collectionView 单元格上绘图?