具有多个 CollectionViewLayout.why 布局的单个 CollectionView 是否一团糟?
Single CollectionView with multiple CollectionViewLayout.why Layout is mess up?
我有一个 UICollectionView
,我想动态应用两个不同的布局。
UICollectionViewFlowLayout
: 具有相同大小单元格和圆形图像的布局。
var flowLayout: UICollectionViewFlowLayout {
let flowLayout = UICollectionViewFlowLayout()
flowLayout.itemSize = CGSize(width: UIScreen.main.bounds.width/3, height: 140)
flowLayout.sectionInset = UIEdgeInsetsMake(0, 0, 0, 0)
flowLayout.scrollDirection = UICollectionViewScrollDirection.vertical
flowLayout.minimumInteritemSpacing = 0.0
return flowLayout
}
Pintrest Layout
:
https://www.raywenderlich.com/392-uicollectionview-custom-layout-tutorial-pinterest
例如:当用户单击配置文件按钮时,FlowLayout 将被应用并且单元格与图像一起出现在圆形中。当用户单击图片按钮时,将应用 pintrest 布局,并且单元格会以具有动态高度的矩形形状显示图像。
最初 CollectionView 有 1.flowLayout,当我点击图片按钮时它出现 perfectly.but Pintrest 布局与之前的布局混淆,如上图所示。
以下是更改布局的代码。
if isGrid {
let horizontal = flowLayout
recentCollectionView.setCollectionViewLayout(horizontal, animated: true)
recentCollectionView.reloadData()
}
else {
let horizontal = PinterestLayout()
horizontal.delegate = self
recentCollectionView.setCollectionViewLayout(horizontal, animated: true)
recentCollectionView.reloadData()
}
视图层次结构:
我有主要 Collection-view 包含 header 和一个底部 cell.cell 包含其他 Collection-view 我正在向其应用多个 layout.I 每个都有两个不同的单元格 layout.I 希望底部单元格大小等于内容 Collection-view 内容大小以便用户可以垂直滚动整个主 collection-view。
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
var cell : UICollectionViewCell!
switch isGrid {
case true:
cell = collectionView.dequeueReusableCell(withReuseIdentifier: "SearchProfileCell", for: indexPath)
if let annotateCell = cell as? SearchProfileCell {
annotateCell.photo = photos[indexPath.item]
}
case false:
cell = collectionView.dequeueReusableCell(withReuseIdentifier: "AnnotatedPhotoCell", for: indexPath)
if let annotateCell = cell as? AnnotatedPhotoCell {
annotateCell.cellwidth = collectionView.contentSize.width/3
annotateCell.photo = photos[indexPath.item]
}
}
cell.contentView.layer.cornerRadius = 0
return cell
}
配置文件和图片按钮操作代码。
@IBAction func pictureClick(sender:UIButton) {
isGrid = false
self.searchCollectionView.reloadData()
}
@IBAction func profilClick(sender:UIButton) {
isGrid = true
self.searchCollectionView.reloadData()
}
我认为问题不在布局内部,而可能在 cellForItemAt 内部。如果您为两种布局使用不同的单元格,则不要在 cellForItemAt 方法中比较 bool。你应该比较布局 class 类型
像下面的代码:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if collectionView.collectionViewLayout.isKind(of: PinterestLayout.self) {
// return cell for PinterestLayout
guard let annotateCell = collectionView.dequeueReusableCell(withReuseIdentifier: "SearchProfileCell", for: indexPath) as? SearchProfileCell else {
fatalError("SearchProfileCell Not Found")
}
annotateCell.photo = photos[indexPath.item]
return annotateCell
} else {
// return cell for flowLayout
guard let annotateCell = collectionView.dequeueReusableCell(withReuseIdentifier: "AnnotatedPhotoCell", for: indexPath) as? AnnotatedPhotoCell else {
fatalError("AnnotatedPhotoCell Not Found")
}
annotateCell.cellwidth = collectionView.contentSize.width/3
annotateCell.photo = photos[indexPath.item]
return annotateCell
}
}
还需要更新布局更改操作方法,例如:
@IBAction func pictureClick(sender:UIButton) {
isGrid = false
self.collectionView?.collectionViewLayout.invalidateLayout()
self.collectionView?.setCollectionViewLayout(PinterestLayout(),
animated: false, completion: { [weak self] (complite) in
guard let strongSelf = self else {
return
}
strongSelf.searchCollectionView?.reloadData()
})
}
@IBAction func profilClick(sender:UIButton) {
isGrid = true
self.collectionView?.collectionViewLayout.invalidateLayout()
self.collectionView?.setCollectionViewLayout(flowLayout,
animated: false, completion: { [weak self] (complite) in
guard let strongSelf = self else {
return
}
strongSelf.searchCollectionView?.reloadData()
})
}
为什么使用 pintrestLayout 可以实现相同的结果却使用两种不同的布局。 https://www.raywenderlich.com/392-uicollectionview-custom-layout-tutorial-pinterest.
仔细检查 pintrestLayout,它有动态高度的委托。
let photoHeight = delegate.collectionView(collectionView, heightForPhotoAtIndexPath: indexPath)
如果您 return 静态高度,您的 pintrest 布局将变为 GridLayout(您的第一个布局)。
如果您希望 pintrest 布局同时适用于两种布局,您需要在 pintrest 中声明相同的布尔值 (isGrid) layout.and 使用此布尔值 return UICollectionViewLayoutAttributes
更重要的 raywenderlich pintrest 布局使用缓存来存储布局 attribute.you 在应用其他布局之前必须删除缓存对象。
查看本教程,如何将相同的布局用于网格、列表和线性。
https://benoitpasquier.com/optimise-uicollectionview-swift/
您在布局中需要什么。
var isGrid : Bool = true {
didSet {
if isGrid != oldValue {
cache.removeAll()
self.invalidateLayout()
}
}
}
我有一个 UICollectionView
,我想动态应用两个不同的布局。
UICollectionViewFlowLayout
: 具有相同大小单元格和圆形图像的布局。var flowLayout: UICollectionViewFlowLayout { let flowLayout = UICollectionViewFlowLayout() flowLayout.itemSize = CGSize(width: UIScreen.main.bounds.width/3, height: 140) flowLayout.sectionInset = UIEdgeInsetsMake(0, 0, 0, 0) flowLayout.scrollDirection = UICollectionViewScrollDirection.vertical flowLayout.minimumInteritemSpacing = 0.0 return flowLayout }
Pintrest Layout
: https://www.raywenderlich.com/392-uicollectionview-custom-layout-tutorial-pinterest
例如:当用户单击配置文件按钮时,FlowLayout 将被应用并且单元格与图像一起出现在圆形中。当用户单击图片按钮时,将应用 pintrest 布局,并且单元格会以具有动态高度的矩形形状显示图像。
最初 CollectionView 有 1.flowLayout,当我点击图片按钮时它出现 perfectly.but Pintrest 布局与之前的布局混淆,如上图所示。
以下是更改布局的代码。
if isGrid {
let horizontal = flowLayout
recentCollectionView.setCollectionViewLayout(horizontal, animated: true)
recentCollectionView.reloadData()
}
else {
let horizontal = PinterestLayout()
horizontal.delegate = self
recentCollectionView.setCollectionViewLayout(horizontal, animated: true)
recentCollectionView.reloadData()
}
视图层次结构:
我有主要 Collection-view 包含 header 和一个底部 cell.cell 包含其他 Collection-view 我正在向其应用多个 layout.I 每个都有两个不同的单元格 layout.I 希望底部单元格大小等于内容 Collection-view 内容大小以便用户可以垂直滚动整个主 collection-view。
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
var cell : UICollectionViewCell!
switch isGrid {
case true:
cell = collectionView.dequeueReusableCell(withReuseIdentifier: "SearchProfileCell", for: indexPath)
if let annotateCell = cell as? SearchProfileCell {
annotateCell.photo = photos[indexPath.item]
}
case false:
cell = collectionView.dequeueReusableCell(withReuseIdentifier: "AnnotatedPhotoCell", for: indexPath)
if let annotateCell = cell as? AnnotatedPhotoCell {
annotateCell.cellwidth = collectionView.contentSize.width/3
annotateCell.photo = photos[indexPath.item]
}
}
cell.contentView.layer.cornerRadius = 0
return cell
}
配置文件和图片按钮操作代码。
@IBAction func pictureClick(sender:UIButton) {
isGrid = false
self.searchCollectionView.reloadData()
}
@IBAction func profilClick(sender:UIButton) {
isGrid = true
self.searchCollectionView.reloadData()
}
我认为问题不在布局内部,而可能在 cellForItemAt 内部。如果您为两种布局使用不同的单元格,则不要在 cellForItemAt 方法中比较 bool。你应该比较布局 class 类型 像下面的代码:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if collectionView.collectionViewLayout.isKind(of: PinterestLayout.self) {
// return cell for PinterestLayout
guard let annotateCell = collectionView.dequeueReusableCell(withReuseIdentifier: "SearchProfileCell", for: indexPath) as? SearchProfileCell else {
fatalError("SearchProfileCell Not Found")
}
annotateCell.photo = photos[indexPath.item]
return annotateCell
} else {
// return cell for flowLayout
guard let annotateCell = collectionView.dequeueReusableCell(withReuseIdentifier: "AnnotatedPhotoCell", for: indexPath) as? AnnotatedPhotoCell else {
fatalError("AnnotatedPhotoCell Not Found")
}
annotateCell.cellwidth = collectionView.contentSize.width/3
annotateCell.photo = photos[indexPath.item]
return annotateCell
}
}
还需要更新布局更改操作方法,例如:
@IBAction func pictureClick(sender:UIButton) {
isGrid = false
self.collectionView?.collectionViewLayout.invalidateLayout()
self.collectionView?.setCollectionViewLayout(PinterestLayout(),
animated: false, completion: { [weak self] (complite) in
guard let strongSelf = self else {
return
}
strongSelf.searchCollectionView?.reloadData()
})
}
@IBAction func profilClick(sender:UIButton) {
isGrid = true
self.collectionView?.collectionViewLayout.invalidateLayout()
self.collectionView?.setCollectionViewLayout(flowLayout,
animated: false, completion: { [weak self] (complite) in
guard let strongSelf = self else {
return
}
strongSelf.searchCollectionView?.reloadData()
})
}
为什么使用 pintrestLayout 可以实现相同的结果却使用两种不同的布局。 https://www.raywenderlich.com/392-uicollectionview-custom-layout-tutorial-pinterest.
仔细检查 pintrestLayout,它有动态高度的委托。
let photoHeight = delegate.collectionView(collectionView, heightForPhotoAtIndexPath: indexPath)
如果您 return 静态高度,您的 pintrest 布局将变为 GridLayout(您的第一个布局)。
如果您希望 pintrest 布局同时适用于两种布局,您需要在 pintrest 中声明相同的布尔值 (isGrid) layout.and 使用此布尔值 return UICollectionViewLayoutAttributes
更重要的 raywenderlich pintrest 布局使用缓存来存储布局 attribute.you 在应用其他布局之前必须删除缓存对象。
查看本教程,如何将相同的布局用于网格、列表和线性。 https://benoitpasquier.com/optimise-uicollectionview-swift/
您在布局中需要什么。
var isGrid : Bool = true {
didSet {
if isGrid != oldValue {
cache.removeAll()
self.invalidateLayout()
}
}
}