目前,我有一个日历网格系统。我正在尝试实现一个功能,我可以在日历中显示事件块。因此,我希望能够实现,用户可以通过点击单元格在网格系统中的任何位置添加“无标题”块。我的第一个想法是在UICollectionView之外添加一个视图,但是当我滚动日历时。 “Untitled”块仍然存在,并且仍然在屏幕上。我需要在集合布局中添加一个单元格,以使其保持在集合视图的流程中。要构建网格系统,我必须创建一个UICollectionViewLayout的自定义子类,所以我没有使用UICollectionViewFlowLayout。我仍然有点迷失如何在另一个单元格上方添加单元格,有关实现此功能的最佳方法的任何想法?
答案 0 :(得分:3)
我最终找到了自己问题的答案。而且,我能够做到这一点,而无需使用一堆内部滚动视图来破解collectionView。这就是我的所作所为。我已经有了我的网格系统,所以我不得不在我的集合视图中添加一个额外的部分。此部分的项目数取决于我的事件数据源数组:
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if section == Constants.numberOfSections {
//custom event section
return events.count
}
//calender grid items
return Constants.numberOfColumns
}
但是,我需要更新有关cellAttributes的集合视图的自定义布局。如果我没有告诉它添加了一个新的单元格,那么它会崩溃,因为它无法找到相应的网格成员或将单元格添加到网格中,就像它是网格的另一部分一样。因此,我必须更新自定义布局类中的cellAttributes,然后手动计算单元格在布局中的放置位置。因此,基本上每次添加事件单元格时,布局都必须手动计算该单元格在网格中的位置。这是我在自定义布局子类中手动计算事件坐标的函数(相关部分在自定义事件注释中):
fileprivate func setCellAttributes(item: Int, section: Int) {
// Build the UICollectionVieLayoutAttributes for the cell.
let cellIndex = IndexPath(item: item, section: section)
var cellWidth: Double = CELL_WIDTH
var cellHeight: Double = CELL_HEIGHT
var xPos: Double = 0
var yPos = Double(section) * CELL_HEIGHT
if section == collectionView!.numberOfSections - 1 {
//custom event items
let rect = getCustomEventRect(item: item)
xPos = Double(rect.x)
yPos = Double(rect.y)
cellHeight = Double(rect.height)
cellWidth = Double(rect.width)
} else if item == 0 {
//the y axis cells
cellWidth = yAxisCellWidth
} else {
//all other cells
xPos = calculateXPos(item: item)
}
let cellAttributes = UICollectionViewLayoutAttributes(forCellWith: cellIndex)
cellAttributes.frame = CGRect(x: xPos, y: yPos, width: cellWidth, height: cellHeight)
// Determine zIndex based on cell type.
if section == 0 && item == 0 {
//top left corner cell
cellAttributes.zIndex = 5
} else if section == 0 {
//y axis cells
cellAttributes.zIndex = 4
} else if section == collectionView!.numberOfSections - 1 {
//custom event cells
cellAttributes.zIndex = 2
} else if item == 0 {
//top x axis cells
cellAttributes.zIndex = 3
} else {
//all background schedule cells
cellAttributes.zIndex = 1
}
// Save the attributes.
cellAttrsDictionary[cellIndex] = cellAttributes
}
此外,每次我更新viewController中的事件时,我都必须更新布局中的事件。所以,我在viewController中实现了这个:
var events: [CustomEvent] = [] {
didSet {
if let layout = theCollectionView.collectionViewLayout as? ScheduleCollectionViewLayout {
layout.events = events
}
}
}
并且,当用户点击添加新事件时,我确保相应地更新布局:
func removeEventCell(at indexPath: IndexPath) {
let eventSection: Int = collectionView!.numberOfSections - 1
let totalEventItems: Int = collectionView!.numberOfItems(inSection: eventSection)
//decrementing all indexPaths above the deleted event cell, so the attribute dictionary will be up to date, when reloadSections is run by the collectionView.
for item in 0..<totalEventItems where item > indexPath.item {
let targetIndexPath = IndexPath(item: item - 1, section: eventSection)
let cellAttr = cellAttrsDictionary[IndexPath(item: item, section: eventSection)]
cellAttr?.indexPath = targetIndexPath
cellAttrsDictionary[targetIndexPath] = cellAttr
}
let lastIndexPath = IndexPath(item: totalEventItems - 1, section: eventSection)
cellAttrsDictionary.removeValue(forKey: lastIndexPath)
}
fileprivate func addEventCellAttributes(numOfEventsToAdd: Int) {
for num in 1...numOfEventsToAdd {
setCellAttributes(item: events.count - num, section: collectionView!.numberOfSections - 1)
}
}
这是计算放置单元格的位置的非常手动的过程,但它使collectionView保持平稳运行并允许将单元格放在单元格之上。我的答案总结是我为自定义事件添加了一个新的部分,我不得不手动计算这些单元格的位置应该是什么,而不是让它们与网格系统一起流动。我的互动日历现在完美无缺。如果您在尝试创建网格系统时遇到问题,我使用了本教程: https://www.credera.com/blog/mobile-applications-and-web/building-a-multi-directional-uicollectionview-in-swift/