[英]UICollectionViewCell resizing on device rotation
I have a very simple UICollectionView embedded in a ViewController. 我在ViewController中嵌入了一个非常简单的UICollectionView。
The UICollectionView uses auto-layout (defined in IB) to take the whole space in the ViewController. UICollectionView使用自动布局(在IB中定义)来占用ViewController中的整个空间。
My UICollectionViewCell have all the same size and they take the whole space of the UICollectionView because I want only one cell to be displayed in the ViewController. 我的UICollectionViewCell具有相同的大小,它们占据了UICollectionView的整个空间,因为我只希望在ViewController中显示一个单元格。 The UICollectionViewCell displays only an UIImage (which is embedded in a UIScrollView for zooming).
UICollectionViewCell仅显示一个UIImage(嵌入在UIScrollView中以进行缩放)。
It works fine except when the device rotate. 除非设备旋转,否则它工作正常。 There's an error message:
出现错误消息:
The behavior of the UICollectionViewFlowLayout is not defined because: the item height must be less than the height of the UICollectionView minus the section insets top and bottom values, minus the content insets top and bottom values.
未定义UICollectionViewFlowLayout的行为,因为:项目高度必须小于UICollectionView的高度减去该部分插入的上限值和下限值,减去内容插入的上限值和下限值。 The relevant UICollectionViewFlowLayout instance is , and it is attached to ;
相关的UICollectionViewFlowLayout实例为,并附加到; animations = { bounds.origin=;
动画= {bounds.origin =; bounds.size=;
bounds.size =; position=;
position =; };
}; layer = ;
层=; contentOffset: {0, 0};
contentOffset:{0,0}; contentSize: {4875, 323}> collection view layout: .
contentSize:{4875,323}>集合视图布局:。
That's pretty clear, I need to resize my UICollectionViewCell to fit the new height / width. 这很清楚,我需要调整UICollectionViewCell的大小以适合新的高度/宽度。 After the rotation the UICollectionViewCell display with the appropriate height / width but with a poor animation.
旋转后,UICollectionViewCell将显示适当的高度/宽度,但动画效果不佳。
Here's the code: 这是代码:
@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)")
}
The question is, how and when perform the UICollectionViewCell change to avoid the warning and get the smooth animation? 问题是,如何以及何时执行UICollectionViewCell更改以避免警告并获得平滑的动画?
When the device rotation happens, I can see the following: viewWillTransition(to:with:) (375.0, 667.0) viewWillLayoutSubviews() (667.0, 375.0) viewDidLayoutSubviews() (667.0, 375.0) 当设备旋转时,我可以看到以下内容:viewWillTransition(to:with :)(375.0,667.0)viewWillLayoutSubviews()(667.0,375.0)viewDidLayoutSubviews()(667.0,375.0)
The error is displayed just after the viewDidLayoutSubviews(). 该错误仅在viewDidLayoutSubviews()之后显示。 I have tried to call theFlowLayout.invalidateLayout() in viewDidLayoutSubviews() but it doesn't change the issue.
我试图在viewDidLayoutSubviews()中调用theFlowLayout.invalidateLayout(),但它不会改变问题。
I have read others similar questions but I could not find my answer :-( 我读过其他类似的问题,但找不到答案:-(
Thanks for your help, 谢谢你的帮助,
Sebastien 塞巴斯蒂安
I have not found the best solution but at least it works. 我还没有找到最好的解决方案,但至少可以奏效。
I use viewWillTransition to compute the index of the cell and to reset the offset after the rotation. 我使用viewWillTransition计算单元格的索引并在旋转后重置偏移量。 To avoid poor animation I set the alpha to 0 and at the beginning and to 1 again at the end of the animation.
为避免动画效果不佳,我将Alpha设置为0,并在动画的开始处将其设置为1,然后在动画结束时将其设置为1。
viewWillLayoutSubviews is used to invalidated the layout of the UICollectionViewFlowLayout and viewDidLayoutSubviews to set the new cell size. viewWillLayoutSubviews用于使UICollectionViewFlowLayout和viewDidLayoutSubviews的布局无效以设置新的单元格大小。
Maybe it will help others but if you have a better solution, please share it! 也许会对其他人有所帮助,但是如果您有更好的解决方案,请与我们分享!
@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
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.