更改和持久化 UICollectionView Cell Size on Tap
Changing and persisting UICollectionView Cell Size on Tap
我正在开发一个使用自定义 FlowLayout 的项目,我无法真正触摸它,但我确实需要扩展用户点击它的单元格的宽度,以便它占据 CollectionView 边界的整个宽度并且还在整个 viewController 的生命周期中坚持这种变化,不管 CollectionView 是如何滚动的。
现在我已经设法让单元格在点击时展开,但是如果你在集合视图中滚动足够多,如果你向后滚动,单元格会缩小到它的原始大小。现在我认为这是由于单元重用而发生的,但我不知道如何为这种行为建模。
这里有更多详细信息:
我有一个用于 Cell 的 XIB
在 sizeForItem 我有:
guard let cellViewModel = viewModel?.getCellViewModel(forIndexPath: indexPath) else {
return CGSize(width: collectionView.frame.width, height: 100)
}
var font = UIFont.systemFont(ofSize: 16, weight: .medium)
var fontAttributes = [NSAttributedString.Key.font: font]
let nameText = cellViewModel.variationName
let nameSize = (nameText as NSString).size(withAttributes: fontAttributes)
font = UIFont.systemFont(ofSize: 16)
fontAttributes = [NSAttributedString.Key.font: font]
let priceText = cellViewModel.priceString ?? ""
let priceSize = (priceText as NSString).size(withAttributes: fontAttributes)
let contentWidth = nameSize.width + priceSize.width + 38 + 1
let insetsTotal = collectionView.contentInset.left
+ collectionView.contentInset.right
+ collectionView.safeAreaInsets.right
+ collectionView.safeAreaInsets.left
var defaultWidth: CGFloat {
if contentWidth > collectionView.frame.width {
return collectionView.frame.width - insetsTotal
} else {
return contentWidth
}
}
guard let isCellSelected = collectionView.cellForItem(at: indexPath)?.isSelected else { return CGSize(width: defaultWidth, height: 33) }
var currentWidth = defaultWidth
if isCellSelected {
currentWidth = collectionView.frame.width - insetsTotal
} else {
currentWidth = defaultWidth
}
let size = CGSize(width: currentWidth, height: 33)
return size
}
然后我让 didSelectItemAt 和 didDeselectItemAt 对集合视图执行批量更新
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath){ collectionView.performBatchUpdates(nil, completion: nil)
}
func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath { collectionView.performBatchUpdates(nil, completion: nil)
}
我得到的行为是一个很好的扩展单元格,它实际上看起来是动画的,但宽度在滚动时没有保留。 collection-view 有多个部分,所以如果您向下滚动到不同的部分并在那里计时项目,那么上一部分的一些展开的单元格将按比例缩小。我认为这是由于单元重用位,我真的需要一些帮助!
你有这样一行:
let isCellSelected = collectionView.cellForItem(at: indexPath)?.isSelected
但是当单元格准备重用时,CollectionView
更新 isSelected
属性 使用存储在集合视图中的信息。
检查具有给定 indexPath
的单元格是否被选中的正确方法:
let isCellSelected = (collectionView.indexPathsForSelectedItems ?? []).contains(indexPath)
我正在开发一个使用自定义 FlowLayout 的项目,我无法真正触摸它,但我确实需要扩展用户点击它的单元格的宽度,以便它占据 CollectionView 边界的整个宽度并且还在整个 viewController 的生命周期中坚持这种变化,不管 CollectionView 是如何滚动的。
现在我已经设法让单元格在点击时展开,但是如果你在集合视图中滚动足够多,如果你向后滚动,单元格会缩小到它的原始大小。现在我认为这是由于单元重用而发生的,但我不知道如何为这种行为建模。
这里有更多详细信息:
我有一个用于 Cell 的 XIB
在 sizeForItem 我有:
guard let cellViewModel = viewModel?.getCellViewModel(forIndexPath: indexPath) else {
return CGSize(width: collectionView.frame.width, height: 100)
}
var font = UIFont.systemFont(ofSize: 16, weight: .medium)
var fontAttributes = [NSAttributedString.Key.font: font]
let nameText = cellViewModel.variationName
let nameSize = (nameText as NSString).size(withAttributes: fontAttributes)
font = UIFont.systemFont(ofSize: 16)
fontAttributes = [NSAttributedString.Key.font: font]
let priceText = cellViewModel.priceString ?? ""
let priceSize = (priceText as NSString).size(withAttributes: fontAttributes)
let contentWidth = nameSize.width + priceSize.width + 38 + 1
let insetsTotal = collectionView.contentInset.left
+ collectionView.contentInset.right
+ collectionView.safeAreaInsets.right
+ collectionView.safeAreaInsets.left
var defaultWidth: CGFloat {
if contentWidth > collectionView.frame.width {
return collectionView.frame.width - insetsTotal
} else {
return contentWidth
}
}
guard let isCellSelected = collectionView.cellForItem(at: indexPath)?.isSelected else { return CGSize(width: defaultWidth, height: 33) }
var currentWidth = defaultWidth
if isCellSelected {
currentWidth = collectionView.frame.width - insetsTotal
} else {
currentWidth = defaultWidth
}
let size = CGSize(width: currentWidth, height: 33)
return size
}
然后我让 didSelectItemAt 和 didDeselectItemAt 对集合视图执行批量更新
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath){ collectionView.performBatchUpdates(nil, completion: nil)
}
func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath { collectionView.performBatchUpdates(nil, completion: nil)
}
我得到的行为是一个很好的扩展单元格,它实际上看起来是动画的,但宽度在滚动时没有保留。 collection-view 有多个部分,所以如果您向下滚动到不同的部分并在那里计时项目,那么上一部分的一些展开的单元格将按比例缩小。我认为这是由于单元重用位,我真的需要一些帮助!
你有这样一行:
let isCellSelected = collectionView.cellForItem(at: indexPath)?.isSelected
但是当单元格准备重用时,CollectionView
更新 isSelected
属性 使用存储在集合视图中的信息。
检查具有给定 indexPath
的单元格是否被选中的正确方法:
let isCellSelected = (collectionView.indexPathsForSelectedItems ?? []).contains(indexPath)