使用自动布局时设置 UICollectionViewFlowLayout 的属性不起作用
Posted
技术标签:
【中文标题】使用自动布局时设置 UICollectionViewFlowLayout 的属性不起作用【英文标题】:Settings UICollectionViewFlowLayout's properties not working when using Auto Layout 【发布时间】:2015-08-20 20:34:23 【问题描述】:我正在尝试使用 UICollectionViewFlowLayout 设置 UICollectionView,并满足以下要求:minimumLineSpacing 应始终恰好为三分之一UICollectionView 的高度。我最初的想法是像这样覆盖 viewDidLayoutSubviews:
override func viewDidLayoutSubviews()
super.viewDidLayoutSubviews()
collectionViewFlowLayout.minimumLineSpacing = collectionView.frame.height / 3
collectionViewFlowLayout.invalidateLayout()
请注意,我使用 viewDidLayoutSubviews 是因为我打算使用自动布局,并且框架可能取决于一些复杂的约束。所以我无法自己计算框架,但必须等到 Auto Layout 计算好后才能在 viewDidLayoutSubviews 中使用。
我通过以编程方式创建 UICollectionView 对此进行了一些测试(并旋转模拟器以查看 minimumLineSpacing 是否始终正确)。它似乎工作得很好。
然后,我切换到自动布局。我只是将集合视图的顶部、底部、前导和尾随空间限制在其父视图中。这样做之后,设置 minimumLineSpacing 不再具有预期的效果,它根本没有改变集合视图的外观。
以下代码很好地演示了这个问题。一旦我将useAutoLayout
设置为true
,设置 minimumLineSpacing 就不再起作用了。
class DemoViewController: UIViewController, UICollectionViewDataSource
var collectionView: UICollectionView!
var collectionViewFlowLayout: UICollectionViewFlowLayout!
// MARK: - UIViewController
override func viewDidLoad()
super.viewDidLoad()
collectionViewFlowLayout = UICollectionViewFlowLayout()
collectionViewFlowLayout.itemSize = CGSizeMake(100, 100)
collectionView = UICollectionView(frame: view.frame, collectionViewLayout: collectionViewFlowLayout)
collectionView.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: "cell")
collectionView.dataSource = self
view.addSubview(collectionView)
let useAutoLayout = false // Change this to true to test!
if useAutoLayout
collectionView.setTranslatesAutoresizingMaskIntoConstraints(false)
NSLayoutConstraint.activateConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-[collectionView]-|", options: nil, metrics: nil, views: ["collectionView" : collectionView]))
NSLayoutConstraint.activateConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-[collectionView]-|", options: nil, metrics: nil, views: ["collectionView" : collectionView]))
else
collectionView.autoresizingMask = .FlexibleHeight | .FlexibleWidth
override func viewDidLayoutSubviews()
super.viewDidLayoutSubviews()
collectionViewFlowLayout.minimumLineSpacing = collectionView.frame.height / 3
collectionViewFlowLayout.invalidateLayout()
// MARK: - <UICollectionViewDataSource>
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int
return 1
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
return 100
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! UICollectionViewCell
cell.backgroundColor = UIColor.greenColor()
return cell
在模拟器中测试这段代码,旋转它,看看当useAutoLayout
设置为true
时,设置 minimumLineSpacing 有什么作用。所以我的问题是:如何使用自动布局并仍然提供 minimumLineSpacing?
注意事项Base SDK 设置为 ios 8.4 SDK。设置 itemSize
或 minimumInteritemSpacing
等其他属性也不起作用。
【问题讨论】:
不使用viewDidLayoutSubviews
,您是否尝试过提供委托方法- collectionView:layout:minimumLineSpacingForSectionAtIndex:
?
【参考方案1】:
我已经复制了你的描述。很奇怪。
我认为在这种情况下,特定的旋转会导致 invalidLayout()
被忽略。也许问题在于您对invalidateLayout()
的调用发生在布局对象认为它已经响应或正在响应的点上.然后您的失效将被忽略,因为它来不及合并到自动失效中,而且太早算作单独的失效。我正在猜测。我注意到你甚至可以在那里继续增加minimumLineSpacing
,它会很高兴地前进到无穷大,而集合视图却没有再次进行布局的机智。
但是,如果您设置视图控制器以使抖动事件触发失效,那么它会注意到该值。
因此,您可以通过强制在运行循环的下一轮发生失效来解决问题,从而逃避在旋转期间阻止它的任何奇怪的特殊逻辑。例如,如果您将 viewDidLayoutSubviews()
替换为以下内容:
override func viewDidLayoutSubviews()
super.viewDidLayoutSubviews()
let newValue = collectionView.bounds.height / 3
dispatch_async(dispatch_get_main_queue())
[weak collectionViewFlowLayout] in
collectionViewFlowLayout?.minimumLineSpacing = newValue
然后就可以了。
为什么需要这样做?我不知道。我认为没有必要。这对我来说就像UICollectionView
中的一个错误,或者至少是一个非常不直观的 API。
【讨论】:
感谢您的帮助。虽然我不太喜欢 dispatch_async 解决方法,但我同意这是我现在唯一能做的事情。我已经怀疑这是一个错误,所以我提交了一个雷达 (openradar.appspot.com/radar?id=5081000568684544) 是的,我也不喜欢这种变通方法,因为感觉它没有必要!但如果 UIKit 本身是不正确的,则可能没有“正确”的解决方案。以上是关于使用自动布局时设置 UICollectionViewFlowLayout 的属性不起作用的主要内容,如果未能解决你的问题,请参考以下文章
如何使用自动布局以编程方式快速设置旋转时 UICollectionView 的宽度
使用自动布局时设置 UICollectionViewFlowLayout 的属性不起作用
错误:线程 1:“无法设置未准备好约束的视图层次结构的布局。”使用自动布局时
未设置 NIB“使用自动布局”时,我可以使用 NSLayoutConstraint 吗?
当我使用自动布局和 xib 制作 uitableviewcell 时,为啥要将 translatesAutoresizingMaskIntoConstraints 设置为 YES?