其他两种layout布局-1.写出这样的布局
这个问题就是说数组越界,就是我在count改不成count!,否则系统认为可能是0,所以越界知识点:
1.如果要删除tableview,或者colletionView的某个cell,步骤分两个 第一,删除数据源中的,第二是删除collection的中,然后刷新,顺序必须这样,如果顺序颠倒,那么数据源中获取的index是不对的!
2.现在想创建一个可变数组,并且数组中只能放置某种类型的对象,如何写?private lazy var attrisArr = [UICollectionViewLayoutAttributes]()
使用的时候用调用attrisArr.append(attri)
这个方法,addObject
不能用了,感觉怪怪的
继承UICollectionViewLayout奥本文要写一个这样的效果
思路
1.自定义一个layout
2.重写layoutAttributesForElementsInRect
方法
3.手动计算不同cell所在的attri.frame
4.计算content size
5.代码重构
1.自定义一个layout
自定义一个
SFGridLayout
手动开始写布局,因为父类是UICollectionViewLayout
所以所有的布局都要自己写
2.重写layoutAttributesForElementsInRect
方法
过去都要调用
super. layoutAttributesForElementsInRect
方法获取到每个cell的attributeLayout,现在不用了,因为我们之前继承的是流水布局,他会给我们算好位置等等属性,但是我们现在继承的是一个抽象的类,所以啥也没有,只能靠自己来计算,所以我们自己创建和返回一个数组。
2.1懒加载一个数组,里面放置的是UICollectionViewLayoutAttributes
对象
//懒加载数据
private lazy var attrisArr = [UICollectionViewLayoutAttributes]()
//实际调用
attrisArr.append(attri)
3.手动计算不同cell所在的attri.frame
结构剖析图分析之后,看到的前六个是有规律的,那么先给前六个布局试试
let indexPath = NSIndexPath.init(forItem: index, inSection: 0)
let attri = UICollectionViewLayoutAttributes.init(forCellWithIndexPath: indexPath)
let width = UIScreen.mainScreen().bounds.width * 0.5
var height:CGFloat = 0
var x:CGFloat = 0
var y:CGFloat = 0
if(index == 0){
height = width
x = 0
y = 0
}else if(index == 1){
height = width*0.5
x = width
y = 0
}else if(index == 2){
height = width*0.5
x = width
y = height
}else if(index == 3){
height = width*0.5
x = 0
y = width
}else if(index == 4){
height = width*0.5
x = 0
y = height+width
}else if(index == 5){
height = width
x = width
y = width
}
前六个照片
六个以后,就是获取attrisArr[index - 6] 和对象,其他的属性都是一致的,唯独是y应该是加上width*2,请自行补脑
//接上段代码
else{
let lastAttr = attrisArr[index-6]
x = lastAttr.frame.origin.x
y = 2*width + lastAttr.frame.origin.y;
height = lastAttr.frame.height
}
attri.frame = CGRectMake(x, y, width, height)
attrisArr.append(atria)
布局完事了4.计算content size
这样就可以做出这样的效果
但还是有一定的问题,就是不能滑动,为啥,因为你自定义了抽象类的布局,所有的东西都要自己去出去好吗!
所以啊,我们应该重写一个方法,返回collectionView
的contensize
属性
//重写contensize方法
override func collectionViewContentSize() -> CGSize {
//获取最后一个
// let arr = layoutAttributesForElementsInRect(CGRectZero)
let count = collectionView?.numberOfItemsInSection(0)
let rows = (count!+3-1)/3
let rowH = (collectionView?.frame.size.width)! * 0.5
return CGSizeMake(0, rowH * CGFloat(rows))
}
5.代码重构
刚才说到在layoutAttributesForElementsInRect
计算cell组的东西,多少有些麻烦,影响效率,因为每次rect变化,都要调用这个方法,重新计算一下,所以不好,应该是只计算一次,所以放到prepareLayout
方法中,
override func prepareLayout() {
super.prepareLayout()
//假设只有一组
let count = collectionView?.numberOfItemsInSection(0)
for index in 0 ..< count!
{
let indexPath = NSIndexPath.init(forItem: index, inSection: 0)
let attri = UICollectionViewLayoutAttributes.init(forCellWithIndexPath: indexPath)
let width = UIScreen.mainScreen().bounds.width * 0.5
var height:CGFloat = 0
var x:CGFloat = 0
var y:CGFloat = 0
if(index == 0){
height = width
x = 0
y = 0
}else if(index == 1){
height = width*0.5
x = width
y = 0
}else if(index == 2){
height = width*0.5
x = width
y = height
}else if(index == 3){
height = width*0.5
x = 0
y = width
}else if(index == 4){
height = width*0.5
x = 0
y = height+width
}else if(index == 5){
height = width
x = width
y = width
}else{
let lastAttr = attrisArr[index-6]
x = lastAttr.frame.origin.x
y = 2*width + lastAttr.frame.origin.y;
height = lastAttr.frame.height
}
attri.frame = CGRectMake(x, y, width, height)
attrisArr.append(attri)
}
}
/**
* 重写返回布局属性数组
*/
override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]?
{
return attrisArr
}