我在ViewController中嵌入了一个非常简单的UICollectionView。
UICollectionView使用自动布局(在IB中定义)来占用ViewController中的整个空间。
我的UICollectionViewCell具有相同的大小,它们占用了UICollectionView的整个空间,因为我只希望在ViewController中显示一个单元格。 UICollectionViewCell仅显示UIImage(嵌入在UIScrollView中进行缩放)。
除非设备旋转,否则工作正常。有一条错误消息:
未定义UICollectionViewFlowLayout的行为,因为: 项高度必须小于UICollectionView的高度减去截面插入顶部和底部值,减去内容插入顶部和底部值。 相关的UICollectionViewFlowLayout实例是,并附加到;动画= {bounds.origin =; bounds.size =;位置=; }; layer =; contentOffset:{0,0}; contentSize:{4875,323}>集合视图布局:。
这很清楚,我需要调整我的UICollectionViewCell大小以适应新的高度/宽度。旋转后,UICollectionViewCell显示具有适当的高度/宽度但动画效果不佳。
以下是代码:
@IBOutlet weak var theCollectionView: UICollectionView!
@IBOutlet weak var theFlowLayout: UICollectionViewFlowLayout!
override func viewDidLoad() {
super.viewDidLoad()
//theCollectionView.delegate = self
theCollectionView.dataSource = self
automaticallyAdjustsScrollViewInsets = false
theFlowLayout.itemSize = theCollectionView.frame.size
theFlowLayout.sectionInset = UIEdgeInsetsMake(0,0,0,0)
theFlowLayout.minimumLineSpacing = 0.0
theCollectionView.reloadData()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
print("\(#function) \(view.frame.size)")
coordinator.animate(alongsideTransition: nil, completion: {
_ in
self.theFlowLayout.itemSize = self.theCollectionView.frame.size
})
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
print("\(#function) \(view.frame.size)")
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
print("\(#function) \(view.frame.size)")
}
问题是,如何以及何时执行UICollectionViewCell更改以避免警告并获得平滑动画?
当设备轮换发生时,我可以看到以下内容: viewWillTransition(to:with :)(375.0,667.0) viewWillLayoutSubviews()(667.0,375.0) viewDidLayoutSubviews()(667.0,375.0)
错误显示在viewDidLayoutSubviews()之后。我试图在viewDidLayoutSubviews()中调用FlowLayout.invalidateLayout(),但它不会改变问题。
我已经读过其他类似问题,但我找不到答案: - (
感谢您的帮助,
的Sebastien
答案 0 :(得分:1)
我没有找到最佳解决方案,但至少它有效。
我使用viewWillTransition来计算单元格的索引并在旋转后重置偏移量。为了避免动画效果不佳,我将alpha设置为0并在开头设置,并在动画结束时再设置为1。
viewWillLayoutSubviews用于使UICollectionViewFlowLayout和viewDidLayoutSubviews的布局无效,以设置新的单元格大小。
也许它会帮助别人,但如果你有更好的解决方案,请分享!
@IBOutlet weak var theCollectionView: UICollectionView! {
didSet {
theCollectionView.backgroundColor = UIColor.black
theCollectionView.delegate = self
theCollectionView.dataSource = self
}
}
@IBOutlet weak var theFlowLayout: UICollectionViewFlowLayout! {
didSet {
theFlowLayout.itemSize = theCollectionView.frame.size
theFlowLayout.sectionInset = UIEdgeInsetsMake(0,0,0,0)
theFlowLayout.minimumLineSpacing = 0.0
}
}
var assets:[PHAsset]!
var startAssetIndex = 0
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.black
automaticallyAdjustsScrollViewInsets = false
theCollectionView.reloadData()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
theCollectionView.scrollToItem(at: IndexPath(row:startAssetIndex, section:0), at: .left, animated: true)
}
/// Resize the collectionView during device rotation
///
/// - Parameters:
/// - size: New size of the viewController
/// - coordinator: coordinator for the animation
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
// Compute the index of the image/video currently displayed
let offset = self.theCollectionView.contentOffset;
let index = round(offset.x / self.theCollectionView.bounds.size.width);
// hide the collection view to avoid horrible animation during the rotation
// animation is horrible due to the offset change
theCollectionView.alpha = 0.0
coordinator.animate(alongsideTransition: nil, completion: {
_ in
// display the collectionView during the animation
self.theCollectionView.alpha = 1.0
// compute the new offset based on the index and the new size
let newOffset = CGPoint(x: index * self.theCollectionView.frame.size.width, y: offset.y)
self.theCollectionView.setContentOffset(newOffset, animated: false)
})
}
/// Invalidate the layout of the FlowLayout, it's mandatory for the rotation
override func viewWillLayoutSubviews() {
theFlowLayout.invalidateLayout()
super.viewWillLayoutSubviews()
}
/// Set the size of the items (mandatory for the rotation)
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
theFlowLayout.itemSize = theCollectionView.frame.size
}