Tal*_*han 52 flowlayout ios uicollectionview swift
我使用UICollectionView(flowlayout)来构建一个简单的布局.每个单元格的宽度设置为使用的屏幕宽度self.view.frame.width
但是当我旋转设备时,单元格不会更新.
我找到了一个函数,在调整方向时调用它:
override func willRotateToInterfaceOrientation(toInterfaceOrientation:
UIInterfaceOrientation, duration: NSTimeInterval) {
//code
}
Run Code Online (Sandbox Code Playgroud)
但我无法找到更新UICollectionView布局的方法
主要代码在这里:
class ViewController: UIViewController , UICollectionViewDelegate , UICollectionViewDataSource , UICollectionViewDelegateFlowLayout{
@IBOutlet weak var myCollection: UICollectionView!
var numOfItemsInSecOne: Int!
override func viewDidLoad() {
super.viewDidLoad()
numOfItemsInSecOne = 8
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func willRotateToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval) {
//print("orientation Changed")
}
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return numOfItemsInSecOne
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cellO", forIndexPath: indexPath)
return cell
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize{
let itemSize = CGSize(width: self.view.frame.width, height: 100)
return itemSize
}}
Run Code Online (Sandbox Code Playgroud)
Khu*_*ong 60
添加此功能:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
myCollection.collectionViewLayout.invalidateLayout()
}
Run Code Online (Sandbox Code Playgroud)
更改方向时,将调用此函数.
kel*_*lin 49
更好的选择是调用invalidateLayout()而不是reloadData()因为它不会强制重新创建单元格,因此性能会稍好一些:
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
myCollection.collectionViewLayout.invalidateLayout()
}
Run Code Online (Sandbox Code Playgroud)
bir*_*rdy 14
要更新UICollectionViewLayout,traitCollectionDidChange也可以使用方法:
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
guard previousTraitCollection != nil else { return }
collectionView?.collectionViewLayout.invalidateLayout()
}
Run Code Online (Sandbox Code Playgroud)
小智 12
您也可以通过这种方式使其无效.
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
[self.collectionView.collectionViewLayout invalidateLayout];
}
Run Code Online (Sandbox Code Playgroud)
小智 11
当UICollectionLayout检测到边界变化时,它会询问是否需要重新路由 Invalidate 布局。您可以直接重写该方法。UICollectionLayout可以invalidateLayout在合适的时间调用方法
class CollectionViewFlowLayout: UICollectionViewFlowLayout{
/// The default implementation of this method returns false.
/// Subclasses can override it and return an appropriate value
/// based on whether changes in the bounds of the collection
/// view require changes to the layout of cells and supplementary views.
/// If the bounds of the collection view change and this method returns true,
/// the collection view invalidates the layout by calling the invalidateLayout(with:) method.
override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
return (self.collectionView?.bounds ?? newBounds) != newBounds
}
}
Run Code Online (Sandbox Code Playgroud)
viewWillLayoutSubviews()对我不起作用.viewDidLayoutSubviews()也没有.两者都使应用程序进入无限循环,我使用打印命令检查.
其中一种方法是工作
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
// Reload here
}
Run Code Online (Sandbox Code Playgroud)
请理解这一点
traitCollectionDidChange(previousTraitCollection :) 在 iPad 旋转时不会被调用,因为尺寸类在纵向和横向都是 .regular 。只要集合视图大小发生变化,就会调用 viewWillTransition(to:with:) 。
此外,如果您的应用程序支持多任务处理,您不应该使用 UIScreen.mainScreen().bounds,因为它可能不会占据整个屏幕,最好使用 collectionView.frame.width。
小智 9
我的代码:
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
self.collectionView.collectionViewLayout.invalidateLayout()
}
Run Code Online (Sandbox Code Playgroud)
会正常工作!!!
呼叫viewWillLayoutSubviews不是最佳选择。首先尝试调用该invalidateLayout()方法。
如果遇到The behaviour of the UICollectionViewFlowLayout is not defined错误,您需要验证视图中的所有元素是否已根据新布局更改了其大小。(请参阅示例代码中的可选步骤)
这是代码,可帮助您入门。根据创建 UI 的方式,您可能需要尝试找到正确的视图来调用该recalculate方法,但这应该会引导您迈出第一步。
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
/// (Optional) Additional step 1. Depending on your layout, you may have to manually indicate that the content size of a visible cells has changed
/// Use that step if you experience the `the behavior of the UICollectionViewFlowLayout is not defined` errors.
collectionView.visibleCells.forEach { cell in
guard let cell = cell as? CustomCell else {
print("`viewWillTransition` failed. Wrong cell type")
return
}
cell.recalculateFrame(newSize: size)
}
/// (Optional) Additional step 2. Recalculate layout if you've explicitly set the estimatedCellSize and you'll notice that layout changes aren't automatically visible after the #3
(collectionView.collectionViewLayout as? CustomLayout)?.recalculateLayout(size: size)
/// Step 3 (or 1 if none of the above is applicable)
coordinator.animate(alongsideTransition: { context in
self.collectionView.collectionViewLayout.invalidateLayout()
}) { _ in
// code to execute when the transition's finished.
}
}
/// Example implementations of the `recalculateFrame` and `recalculateLayout` methods:
/// Within the `CustomCell` class:
func recalculateFrame(newSize: CGSize) {
self.frame = CGRect(x: self.bounds.origin.x,
y: self.bounds.origin.y,
width: newSize.width - 14.0,
height: self.frame.size.height)
}
/// Within the `CustomLayout` class:
func recalculateLayout(size: CGSize? = nil) {
estimatedItemSize = CGSize(width: size.width - 14.0, height: 100)
}
/// IMPORTANT: Within the `CustomLayout` class.
override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
guard let collectionView = collectionView else {
return super.shouldInvalidateLayout(forBoundsChange: newBounds)
}
if collectionView.bounds.width != newBounds.width || collectionView.bounds.height != newBounds.height {
return true
} else {
return false
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
54112 次 |
| 最近记录: |