在我的collectionView单元格中,我有一个在UIView内部的标签。因此单元格必须根据标签的宽度调整自己的大小,高度是固定的。以下是我如何设置固定高度的代码&动态宽度,只是以防万一,因为我已经看到了一些例子,约束可能导致奇怪的行为:
cvButtons.delegate = self
cvButtons.dataSource = self
cvButtons.contentInset = UIEdgeInsets(top: 0, left: 7, bottom: 0, right: 0)
这里是layoutConfig()
代码:
func layoutConfig() -> UICollectionViewCompositionalLayout {
return UICollectionViewCompositionalLayout { (sectionNumber, env) -> NSCollectionLayoutSection? in
let itemSize = NSCollectionLayoutSize(widthDimension: .estimated(44), heightDimension: .fractionalHeight(1))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
let groupSize = NSCollectionLayoutSize(widthDimension: .estimated(44), heightDimension: .absolute(40))
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
let section = NSCollectionLayoutSection(group: group)
section.orthogonalScrollingBehavior = .continuous
return section
}
}
所有这些都很好,单元格被完美地创建,就像每个单元格的宽度是动态的一样。然而,我的要求是,当视图加载时,视图在第一个单元应该有蓝色的背景。所以我写了这段代码:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if collectionView == cvButtons {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ButtonCategoriesCollectionViewCell", for: indexPath) as! ButtonCategoriesCollectionViewCell
let data = tableSctionHeader[indexPath.row]
cell.lblCategory.text = data
if indexPath.item == 0 {
cell.setBlueColor()
}
else {
cell.setDefault()
}
return cell
}
这是collectionView单元格类
import UIKit
class ButtonCategoriesCollectionViewCell: UICollectionViewCell {
@IBOutlet weak var viewCard: UIView!
@IBOutlet weak var lblCategory: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
setDefault()
}
override func prepareForReuse() {
super.prepareForReuse()
self.setDefault()
}
func setDefault() {
viewCard.layer.cornerRadius = 15
viewCard.layer.borderWidth = 1
viewCard.layer.borderColor = UIColor.lightGray.cgColor
viewCard.setviewShadowCustomInputs(shadowColor: UIColor.clear.cgColor, shadowOpacity: 0, shadowRadius: 0, shadowWidth: 0, shadowHeight: 0)
}
func setBlueColor() {
viewCard.backgroundColor = UIColor(named: "Color1")
viewCard.layer.borderWidth = 0
viewCard.layer.borderColor = UIColor.clear.cgColor
viewCard.setViewShadow()
lblCategory.textColor = UIColor.white
}
}
这段代码工作得很好,但是我通过使用另一个collectionView重新加载数据。所以,如果我选择一些项目在collectionView,数据刷新和以上的单元格应该重新加载新的数据,这很好,单元格的数量变化和标签,但在某些情况下,而不是索引== 0,其他一些项目也保留蓝色。在某些情况下,所有项目都显示蓝色,而不是在第一个索引的项目。这是我用来更新上面的collectionView的函数:
func updateCollectionView(index: Int) {
if index == 1 {
collectionViewArray = array1
}
else if index == 2 {
collectionViewArray = array2
}
else if index == 3 {
collectionViewArray = array3
}
else if index == 4 {
collectionViewArray = array4
}
else if index == 5 {
collectionViewArray = array5
}
else if index == 6 {
collectionViewArray = array6
}
else if index == 7 {
collectionViewArray = array7
}
else {
collectionViewArray = array8
}
collectionView.reloadData()
}
我只是在didSelectAnItem
中调用其他collectionView的这个函数,并从中传递indexPath。
这是正确使用prepareForReuse
的方法吗?
prepareForReuse()
方法将单元格恢复到初始状态。
如果您在cellForItem(at:)
中对单元格的外观进行了任何自定义,那么您通常希望在prepareForReuse()
中将这些更改恢复到默认状态。
在您共享的代码中,问题如下:
- 对于某个索引路径,调用
cell.setBlueColor()
。 setBlueColor()
改变viewCard.backgroundColor
- 当相同的单元被用于另一个索引路径时,UIKit调用单元的
prepareForReuse()
方法,该方法反过来调用setDefault()
方法。 - 然而,
setDefault()
方法永远不会将viewCard.backgroundColor
恢复到初始值。
如果您在setDefault()
中添加一行,将viewCard.backgroundColor
设置回您在storyboard/XIB中设置的原始值,它应该可以工作。您可能还需要将lblCategory.textColor
重置回其原始值。
但是,这段代码还可以进一步改进:
- 在
prepareForReuse()
中,不要设置你在cellForItem(at:)
中永远不会更改的属性。相反,只需在awakeFromNib()
中设置它们一次。例如,你永远不会改变角的半径,所以只需将该线移动到awakeFromNib()
。 - 因为
awakeFromNib()
和prepareForReuse
都调用setDefault()
方法,当你不做任何单元格的视觉定制时,你不需要从cellForItem(at:)
再次调用它。这只是浪费CPU时间,没有任何效果。