在设备旋转后调用 invalidateLayout() 或 reloadData() 重新加载从故事板创建的 UICollectionView
Calling invalidateLayout() or reloadData() to reload a UICollectionView created from storyboard after device rotation
在 UITableViewController
、UITableViewCell
中,我有一个网格,每行有固定数量的静态 UICollectionViewCells
(无间距)。
extension NounsTVC: UICollectionViewDataSource {
func collectionView( _ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return cellIds.count
}
func collectionView( _ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell( withReuseIdentifier: cellIds[indexPath.item], for: indexPath)
cell.layer.borderColor = UIColor.gray.cgColor
cell.layer.borderWidth = 0.5
return cell
}
}
extension NounsTVC: UICollectionViewDelegateFlowLayout
{
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 0, left: 0, bottom: 10, right: 0)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let availableWidth = collectionView.bounds.size.width
let minimumWidth = floor(availableWidth / cellsPerRow)
let remainder = availableWidth - minimumWidth * CGFloat(cellsPerRow)
let columnIndex = indexPath.row % Int(cellsPerRow)
let cellWidth = CGFloat(columnIndex) < remainder ? minimumWidth + 1 : minimumWidth
return CGSize(width: cellWidth, height: 45)
}
}
工作正常。
但是,当我旋转设备时,它需要调用这些布局方式。
这看起来像答案:
但是我没有 UICollectionView
作为 invalidLayout()
因为 UICollectionView
是在 IB 中创建的(据我所知),所以我如何在我的 [=14 上调用 invalidateLayout =]?
在上述情况中发现了两个问题。
首先,xcode 没有通过在故事板和 .swift 文件之间拖动一条线来在我的自定义 UITableViewCell 中创建 IBOutlet(显然是某些星座中的错误)。解决方案是手动输入代码,然后按住 ctrl 键将其反向拖放到情节提要中的正确视图。
@IBOutlet weak var myCollectionView: UICollectionView!
其次,因为集合视图是在自定义 UITableViewCell 中实例化的,所以无法使用 viewWillTransitionToSize:withTransitionCoordinator: 或 viewWillLayoutSubviews(table 视图方法)。但是,UITableViewCell 确实有以下内容,其中可以调用 .invalidateLayout():
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?)
{
super.traitCollectionDidChange(previousTraitCollection)
guard previousTraitCollection != nil else
{ return }
myCollectionView.collectionViewLayout.invalidateLayout()
}
在 UITableViewController
、UITableViewCell
中,我有一个网格,每行有固定数量的静态 UICollectionViewCells
(无间距)。
extension NounsTVC: UICollectionViewDataSource {
func collectionView( _ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return cellIds.count
}
func collectionView( _ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell( withReuseIdentifier: cellIds[indexPath.item], for: indexPath)
cell.layer.borderColor = UIColor.gray.cgColor
cell.layer.borderWidth = 0.5
return cell
}
}
extension NounsTVC: UICollectionViewDelegateFlowLayout
{
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 0, left: 0, bottom: 10, right: 0)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let availableWidth = collectionView.bounds.size.width
let minimumWidth = floor(availableWidth / cellsPerRow)
let remainder = availableWidth - minimumWidth * CGFloat(cellsPerRow)
let columnIndex = indexPath.row % Int(cellsPerRow)
let cellWidth = CGFloat(columnIndex) < remainder ? minimumWidth + 1 : minimumWidth
return CGSize(width: cellWidth, height: 45)
}
}
工作正常。
但是,当我旋转设备时,它需要调用这些布局方式。
这看起来像答案:
但是我没有 UICollectionView
作为 invalidLayout()
因为 UICollectionView
是在 IB 中创建的(据我所知),所以我如何在我的 [=14 上调用 invalidateLayout =]?
在上述情况中发现了两个问题。
首先,xcode 没有通过在故事板和 .swift 文件之间拖动一条线来在我的自定义 UITableViewCell 中创建 IBOutlet(显然是某些星座中的错误)。解决方案是手动输入代码,然后按住 ctrl 键将其反向拖放到情节提要中的正确视图。
@IBOutlet weak var myCollectionView: UICollectionView!
其次,因为集合视图是在自定义 UITableViewCell 中实例化的,所以无法使用 viewWillTransitionToSize:withTransitionCoordinator: 或 viewWillLayoutSubviews(table 视图方法)。但是,UITableViewCell 确实有以下内容,其中可以调用 .invalidateLayout():
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?)
{
super.traitCollectionDidChange(previousTraitCollection)
guard previousTraitCollection != nil else
{ return }
myCollectionView.collectionViewLayout.invalidateLayout()
}