我想调整像这个应用程序的单元格:
如您所见,右侧单元格比左侧短.为了达到同样的效果,我使用了以下代码:
var testI=1
func collectionView(collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
var cellHeight=287
if testI % 2 == 0 {
cellHeight=247
}
testI += 1
return CGSizeMake(CGFloat(176), CGFloat(cellHeight))
}
Run Code Online (Sandbox Code Playgroud)
结果:
我不想要这些顶级空间.我该如何删除它们?我的收藏品视图:
我怎么能做到这一点?
ozg*_*gur 10
UICollectionViewFlowLayout期望有问题的单元具有相同的高度(或宽度取决于滚动方向),以便它可以水平或垂直地正确对齐它们.
因此,您无法使用它来获得上述效果.您需要创建这将有类似的性质作为自己的布局类UICollectionViewFlowLayout,如minimumInteritemSpacing,sectionInset等.此外,新的子类(我将其命名为 UserCollectionViewLayout从现在开始)将能够生成与帧值分别对应小区内的所有布局属性具有不同的高度,以便细胞定位就像您共享的图像一样.
在开始之前,您至少应该对如何创建自定义布局有一个基本的了解,因此我强烈建议您阅读本文以便重新开始.
首先,我们需要创建自己的UICollectionViewLayoutAttributes类,以便我们可以将单元格的高度存储在那里供以后使用.
class UserCollectionViewLayoutAttributes: UICollectionViewLayoutAttributes {
var height: CGFloat = 0.0
}
Run Code Online (Sandbox Code Playgroud)
布局类有时会UICollectionViewLayoutAttributes在需要时复制,因此我们需要覆盖几个方法,以便height在发生时传递给复制的对象:
override func copyWithZone(zone: NSZone) -> AnyObject {
let copy = super.copyWithZone(zone) as! UserCollectionViewLayoutAttributes
copy.height = height
return copy
}
override func isEqual(object: AnyObject?) -> Bool {
if let object = object as? UserCollectionViewLayoutAttributes {
if height != object.height {
return false
}
return super.isEqual(object)
}
return false
}
Run Code Online (Sandbox Code Playgroud)
我们将需要一个新的协议,它将要求代表每个单元格的高度:
(相似UICollectionViewDelegateFlowLayout.sizeForItemAtIndexPath)
protocol UserCollectionViewLayoutDelegate: UICollectionViewDelegate {
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UserCollectionViewLayout, heightForItemAtIndexPath indexPath: NSIndexPath) -> CGFloat
}
Run Code Online (Sandbox Code Playgroud)
好的,我们在定义布局的过程中需要的一切就在那里.那么,让我们开始吧:
class UserCollectionViewLayout: UICollectionViewLayout {
private var contentHeight: CGFloat = 0.0
private var allAttributes = [UserCollectionViewLayoutAttributes]()
weak var delegate: UserCollectionViewLayoutDelegate!
var numberOfColumns: Int = 2
private var numberOfItems: Int {
return collectionView?.numberOfItemsInSection(0) ?? 0
}
private var contentWidth: CGFloat {
return CGRectGetWidth(collectionView?.bounds ?? CGRectZero)
}
private var itemWidth: CGFloat {
return round(contentWidth / CGFloat(numberOfColumns))
}
...
Run Code Online (Sandbox Code Playgroud)
好的,让我们一块一块地解释上面的属性:
contentHeight:集合视图的内容高度,因此它将知道如何/在哪里滚动.与定义相同scrollView.contentSize.height.allAttributes:包含每个单元格属性的数组.它将填入prepareLayout()方法中.numberOfColumns:一个值,指示每行将显示多少个单元格.它将2在您的示例中,因为您要连续显示2张照片.让我们继续覆盖一些重要的方法:
override func collectionViewContentSize() -> CGSize {
return CGSize(width: contentWidth, height: contentHeight)
}
override class func layoutAttributesClass() -> AnyClass {
return UserCollectionViewLayoutAttributes.self
}
Run Code Online (Sandbox Code Playgroud)
关键是要prepareLayout正确实施.在此方法中,我们将填充与每个indexPath对应的所有布局属性,并将其存储以allAttributes供以后使用.
布局看起来像2D单元格.但是,每个细胞的高度可能不同.因此,您应该记住frame.origin.y位于同一行的单元格的值可能不相同:
override func prepareLayout() {
if allAttributes.isEmpty {
let xOffsets = (0..<numberOfColumns).map { index -> CGFloat in
return CGFloat(index) * itemWidth
}
var yOffsets = Array(count: numberOfColumns, repeatedValue: CGFloat(0))
var column = 0
for item in 0..<numberOfItems {
let indexPath = NSIndexPath(forItem: item, inSection: 0)
let attributes = UserCollectionViewLayoutAttributes(forCellWithIndexPath: indexPath)
let cellHeight = delegate.collectionView(collectionView!, layout: self, heightForItemAtIndexPath: indexPath)
let frame = CGRect(x: xOffsets[column], y: yOffsets[column], width: itemWidth, height: cellHeight)
attributes.frame = frame
attributes.height = cellHeight
allAttributes.append(attributes)
yOffsets[column] = yOffsets[column] + cellHeight
column = (column >= numberOfColumns - 1) ? 0 : column + 1
contentHeight = max(contentHeight, CGRectGetMaxY(frame))
}
}
}
override func invalidateLayout() {
allAttributes.removeAll()
contentHeight = 0
super.invalidateLayout()
}
Run Code Online (Sandbox Code Playgroud)
我们需要实现另外两个方法,让布局知道在显示单元格时应该使用哪个布局属性:
让我们试一试:
override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
return cachedAttributes.filter { attribute -> Bool in
return CGRectIntersectsRect(rect, attribute.frame)
}
}
override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? {
return cachedAttributes.filter { attribute -> Bool in
return attribute.indexPath == indexPath
}.first
}
Run Code Online (Sandbox Code Playgroud)
好的,这就是布局部分的全部内容.现在,我们有一个布局类,能够在一行中显示具有不同高度值的单元格.现在,我们需要弄清楚如何将height值传递给实际的单元对象.
对我们来说幸运的是,如果你正在使用组织你的单元格内容,这是非常简单的AutoLayout.有一个命名的方法applyLayoutAttributes中UICollectionViewCell,使您能够做出格的布局最后一分钟的变化.
class UserCell: UICollectionViewCell {
let userView = UIView(frame: CGRectZero)
private var heightLayoutConstraint: NSLayoutConstraint!
override func applyLayoutAttributes(layoutAttributes: UICollectionViewLayoutAttributes) {
super.applyLayoutAttributes(layoutAttributes)
let attributes = layoutAttributes as! UserCollectionViewLayoutAttributes
heightLayoutConstraint.constant = attributes.height
}
override init(frame: CGRect) {
super.init(frame: frame)
contentView.backgroundColor = UIColor.whiteColor()
contentView.addSubview(userView)
userView.translatesAutoresizingMaskIntoConstraints = false
contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat(
"H:|[userView]|",
options: NSLayoutFormatOptions.AlignAllCenterY,
metrics: nil,
views: ["userView": userView])
)
contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat(
"V:|[userView]|",
options: NSLayoutFormatOptions.AlignAllCenterX,
metrics: nil,
views: ["userView": userView])
)
heightLayoutConstraint = NSLayoutConstraint(
item: self,
attribute: NSLayoutAttribute.Height,
relatedBy: NSLayoutRelation.Equal,
toItem: nil,
attribute: NSLayoutAttribute.NotAnAttribute,
multiplier: 0.0,
constant: 0.0
)
heightLayoutConstraint.priority = 500
contentView.addConstraint(heightLayoutConstraint)
}
}
Run Code Online (Sandbox Code Playgroud)
将所有这些结合在一起,结果如下:
我相信你可以像在课堂上一样添加minimumInteritemSpacing和sectionInset属性UICollectionViewFlowLayout,以便在单元格之间添加一些填充.
(提示:你应该相应调整prepareLayout方法中的单元格框架.)
您可以从此处下载示例项目.
| 归档时间: |
|
| 查看次数: |
1323 次 |
| 最近记录: |