您好我有工作的collectionview自定义布局代码,但有些单元格我需要更改单元格中的单元格宽度来自json的动态变换。
我的CustomCollectionViewLayout
import UIKit
public var CELL_HEIGHT = 22.0
public var CELL_WIDTH = 40.0 // HERE WIDTH SOME CELLS MUST BE 80
class CustomCollectionViewLayout: UICollectionViewLayout {
// Used for calculating each cells CGRect on screen.
// CGRect will define the Origin and Size of the cell.
let STATUS_BAR = UIApplication.sharedApplication().statusBarFrame.height
// Dictionary to hold the UICollectionViewLayoutAttributes for
// each cell. The layout attribtues will define the cell's size
// and position (x, y, and z index). I have found this process
// to be one of the heavier parts of the layout. I recommend
// holding onto this data after it has been calculated in either
// a dictionary or data store of some kind for a smooth performance.
var cellAttrsDictionary = Dictionary<NSIndexPath, UICollectionViewLayoutAttributes>()
// Defines the size of the area the user can move around in
// within the collection view.
var contentSize = CGSize.zero
// Used to determine if a data source update has occured.
// Note: The data source would be responsible for updating
// this value if an update was performed.
var dataSourceDidUpdate = true
override func collectionViewContentSize() -> CGSize {
return self.contentSize
}
override func prepareLayout() {
// Only update header cells.
if !dataSourceDidUpdate {
// Determine current content offsets.
let xOffset = collectionView!.contentOffset.x
let yOffset = collectionView!.contentOffset.y
if collectionView?.numberOfSections() > 0 {
for section in 0...collectionView!.numberOfSections()-1 {
// Confirm the section has items.
if collectionView?.numberOfItemsInSection(section) > 0 {
// Update all items in the first row.
if section == 0 {
for item in 0...collectionView!.numberOfItemsInSection(section)-1 {
// Build indexPath to get attributes from dictionary.
let indexPath = NSIndexPath(forItem: item, inSection: section)
// Update y-position to follow user.
if let attrs = cellAttrsDictionary[indexPath] {
var frame = attrs.frame
// Also update x-position for corner cell.
if item == 0 {
frame.origin.x = xOffset
}
frame.origin.y = yOffset
attrs.frame = frame
}
}
// For all other sections, we only need to update
// the x-position for the fist item.
} else {
// Build indexPath to get attributes from dictionary.
let indexPath = NSIndexPath(forItem: 0, inSection: section)
// Update y-position to follow user.
if let attrs = cellAttrsDictionary[indexPath] {
var frame = attrs.frame
frame.origin.x = xOffset
attrs.frame = frame
}
}
}
}
}
// Do not run attribute generation code
// unless data source has been updated.
return
}
// Acknowledge data source change, and disable for next time.
dataSourceDidUpdate = false
var maxItemInASection: Int?
// Cycle through each section of the data source.
if collectionView?.numberOfSections() > 0 {
for section in 0...collectionView!.numberOfSections()-1 {
// Cycle through each item in the section.
if collectionView?.numberOfItemsInSection(section) > 0 {
for item in 0...collectionView!.numberOfItemsInSection(section)-1 {
// Build the UICollectionVieLayoutAttributes for the cell.
let cellIndex = NSIndexPath(forItem: item, inSection: section)
let xPos = Double(item) * CELL_WIDTH
let yPos = Double(section) * CELL_HEIGHT
let cellAttributes = UICollectionViewLayoutAttributes(forCellWithIndexPath: cellIndex)
cellAttributes.frame = CGRect(x: xPos, y: yPos, width: CELL_WIDTH, height: CELL_HEIGHT)
// Determine zIndex based on cell type.
if section == 0 && item == 0 {
cellAttributes.zIndex = 4
} else if section == 0 {
cellAttributes.zIndex = 3
} else if item == 0 {
cellAttributes.zIndex = 2
} else {
cellAttributes.zIndex = 1
}
// Save the attributes.
cellAttrsDictionary[cellIndex] = cellAttributes
if maxItemInASection < item {
maxItemInASection = item
}
}
}
}
}
// Update content size.
let contentWidth = Double(maxItemInASection ?? 0) * CELL_WIDTH
let contentHeight = Double(collectionView!.numberOfSections()) * CELL_HEIGHT
self.contentSize = CGSize(width: contentWidth, height: contentHeight)
}
override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
// Create an array to hold all elements found in our current view.
var attributesInRect = [UICollectionViewLayoutAttributes]()
// Check each element to see if it should be returned.
for cellAttributes in cellAttrsDictionary.values.elements {
if CGRectIntersectsRect(rect, cellAttributes.frame) {
attributesInRect.append(cellAttributes)
}
}
// Return list of elements.
return attributesInRect
}
override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? {
return cellAttrsDictionary[indexPath]!
}
override func shouldInvalidateLayoutForBoundsChange(newBounds: CGRect) -> Bool {
return true
}
}
这是我的手机密码。
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("customCell", forIndexPath: indexPath) as! CustomCollectionViewCell
if items[indexPath.section].base == 2 {
cell.label.text = items[indexPath.section].base
cell.frame.size.width = 80
cell.layer.frame.size.width = 80
CELL_WIDTH = 80.0 // HERE I CHANGED SOME CELLS WIDTH 80 BUT DONT CHANGE THEM !!
}else{
cell.label.text = items[indexPath.section].base
}
你可以看到上方
CELL_WIDTH = 80.0 //在这里我改变了一些细胞宽度80,但不要改变它们!
答案 0 :(得分:3)
您可以实现collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath)
而不是子类化UICollectionViewLayout - 除非您有其他理由这样做。
有点像:
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
if indexPath.item % 3 == 0 { // <-- your condition here
return CGSize(width: 40, height: 22)
}
return CGSize(width: 80, height: 22)
}
顺便说一句,不要忘记设置collectionView的委托以便调用此方法。
的修订版强> 的
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
if items[indexPath.section].base == 2 {
return CGSize(width: 80, height: 22)
} else {
return CGSize(width: 44, height: 22)
}
}
这就是我认为你的方法应该是这样的。
在cellForItem
,您只需要担心设置标签,让上面的代码处理单元格的大小。
答案 1 :(得分:2)
sizeForItemAtIndexPath
不存在 UICollectionViewLayout
。因此,从CustomCollectionViewLayout
继承的UICollectionViewLayout
没有协议。您可以创建protocol
widthForItemAtIndexPath
方法。
protocol CustomCollectionViewDelegateLayout: NSObjectProtocol {
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, widthForItemAtIndexPath indexPath: NSIndexPath) -> CGFloat
}
在viewController
实施此协议方法中。返回值将是给定indexPath
extension CustomCollectionViewController: CustomCollectionViewDelegateLayout {
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, widthForItemAtIndexPath indexPath: NSIndexPath) -> CGFloat {
//from indexPath.section and indexPath.item identify double width item
if sirano == 2 && satimdurum == 0 {
return regularWidth * 2
}
return regularWidth
}
}
在prepareLayout()
的{{1}}方法中,您可以计算每个项目的位置,以确定哪个项目应该加倍。
CustomCollectionViewLayout
处制作了一个带有xcode 7.2的演示项目
答案 2 :(得分:1)
不要在cellForItemAtIndexPath方法中更改单元格大小。在dequeueReusableCellWithReuseIdentifier之后已经设置了单元格布局。
在sizeForItemAtIndexPath中更改它。这是在上面的委托方法之前调用的。