网格UICollectionView除了使用流布局,还可以使用自定义布局。实现自定义布局需要继承UICollectionViewLayout,同时还要重载下面的三个方法:
1
2
3
4
5
6
7
8
9
10
11
12
|
// 这个方法返回每个单元格的位置和大小
override
func
layoutAttributesForItemAtIndexPath(indexPath:
NSIndexPath
)
->
UICollectionViewLayoutAttributes
! {
}
// 返回内容区域总大小,不是可见区域
override
func
collectionViewContentSize() ->
CGSize
{
}
// 返回所有单元格位置属性
override
func
layoutAttributesForElementsInRect(rect:
CGRect
) -> [
AnyObject
] {
}
|
下面实现一个自定义布局的例子,单元格有大小两种。网格从上到下,先是左边一个大单元格右边两个小单元格,接着左边两个小单元格右边一个大单元格,依次同上循环排列。
效果图如下:
--- 自定义布局 CustomLayout.swift ---
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
import
UIKit
/**
* 这个类只简单定义了一个section的布局
*/
class
CustomLayout
:
UICollectionViewLayout
{
// 内容区域总大小,不是可见区域
override
func
collectionViewContentSize() ->
CGSize
{
return
CGSizeMake
(collectionView!.bounds.size.width,
CGFloat
(collectionView!.numberOfItemsInSection(0) * 200 / 3 + 200))
}
// 所有单元格位置属性
override
func
layoutAttributesForElementsInRect(rect:
CGRect
) -> [
AnyObject
] {
var
attributesArray = [
AnyObject
]()
let
cellCount =
self
.collectionView!.numberOfItemsInSection(0)
for
i
in
0..<cellCount {
var
indexPath =
NSIndexPath
(forItem:i, inSection:0)
var
attributes =
self
.layoutAttributesForItemAtIndexPath(indexPath)
attributesArray.append(attributes)
}
return
attributesArray
}
// 这个方法返回每个单元格的位置和大小
override
func
layoutAttributesForItemAtIndexPath(indexPath:
NSIndexPath
)
->
UICollectionViewLayoutAttributes
! {
//当前单元格布局属性
var
attribute =
UICollectionViewLayoutAttributes
(forCellWithIndexPath:indexPath)
//单元格外部空隙,简单起见,这些常量都在方法内部定义了,没有共享为类成员
let
itemSpacing = 2
let
lineSpacing = 5
//单元格边长
let
largeCellSide:
CGFloat
= 200
let
smallCellSide:
CGFloat
= 100
//内部间隙,左右5
var
insets =
UIEdgeInsetsMake
(2, 5, 2, 5)
//当前行数,每行显示3个图片,1大2小
var
line:
Int
= indexPath.item / 3
//当前行的Y坐标
var
lineOriginY = largeCellSide *
CGFloat
(line) +
CGFloat
(lineSpacing * line) + insets.top
//右侧单元格X坐标,这里按左右对齐,所以中间空隙大
var
rightLargeX = collectionView!.bounds.size.width - largeCellSide - insets.right
var
rightSmallX = collectionView!.bounds.size.width - smallCellSide - insets.right
// 每行2个图片,2行循环一次,一共6种位置
if
(indexPath.item % 6 == 0) {
attribute.frame =
CGRectMake
(insets.left, lineOriginY, largeCellSide, largeCellSide)
}
else
if
(indexPath.item % 6 == 1) {
attribute.frame =
CGRectMake
(rightSmallX, lineOriginY, smallCellSide, smallCellSide)
}
else
if
(indexPath.item % 6 == 2) {
attribute.frame =
CGRectMake
(rightSmallX, lineOriginY + smallCellSide + insets.top,
smallCellSide, smallCellSide)
}
else
if
(indexPath.item % 6 == 3) {
attribute.frame =
CGRectMake
(insets.left, lineOriginY, smallCellSide, smallCellSide)
}
else
if
(indexPath.item % 6 == 4) {
attribute.frame =
CGRectMake
(insets.left, lineOriginY + smallCellSide + insets.top,
smallCellSide, smallCellSide)
}
else
if
(indexPath.item % 6 == 5) {
attribute.frame =
CGRectMake
(rightLargeX, lineOriginY, largeCellSide, largeCellSide)
}
return
attribute
}
/*
//如果有页眉、页脚或者背景,可以用下面的方法实现更多效果
func layoutAttributesForSupplementaryViewOfKind(elementKind: String!,
atIndexPath indexPath: NSIndexPath!) -> UICollectionViewLayoutAttributes!
func layoutAttributesForDecorationViewOfKind(elementKind: String!,
atIndexPath indexPath: NSIndexPath!) -> UICollectionViewLayoutAttributes!
*/
}
|
--- 主页面 ViewController.swift ---
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
import
UIKit
class
ViewController
:
UIViewController
,
UICollectionViewDelegate
,
UICollectionViewDataSource
{
var
collectionView:
UICollectionView
!
//课程名称和图片,每一门课程用字典来表示
let
courses = [
[
"name"
:
"Swift"
,
"pic"
:
"swift.png"
],
[
"name"
:
"OC"
,
"pic"
:
"oc.jpg"
],
[
"name"
:
"Java"
,
"pic"
:
"java.png"
],
[
"name"
:
"PHP"
,
"pic"
:
"php.jpeg"
],
[
"name"
:
"JS"
,
"pic"
:
"js.jpeg"
],
[
"name"
:
"HTML"
,
"pic"
:
"html.jpeg"
],
[
"name"
:
"Ruby"
,
"pic"
:
"ruby.png"
]
]
override
func
viewDidLoad() {
super
.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let
layout =
CustomLayout
()
//let layout = UICollectionViewFlowLayout()
self
.collectionView =
UICollectionView
(
frame:
CGRectMake
(0,20,view.bounds.size.width,view.bounds.height-20),
collectionViewLayout:layout)
self
.collectionView.delegate =
self
self
.collectionView.dataSource =
self
// 注册CollectionViewCell
self
.collectionView.registerClass(
UICollectionViewCell
.
self
,
forCellWithReuseIdentifier:
"ViewCell"
)
//默认背景是黑色和label一致
self
.collectionView.backgroundColor =
UIColor
.whiteColor()
self
.view.addSubview(collectionView)
}
override
func
didReceiveMemoryWarning() {
super
.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// CollectionView行数
func
collectionView(collectionView:
UICollectionView
, numberOfItemsInSection section:
Int
) ->
Int
{
return
courses.count;
}
// 获取单元格
func
collectionView(collectionView:
UICollectionView
, cellForItemAtIndexPath indexPath:
NSIndexPath
)
->
UICollectionViewCell
{
// storyboard里设计的单元格
let
identify:
String
=
"ViewCell"
// 获取设计的单元格,不需要再动态添加界面元素
let
cell =
self
.collectionView.dequeueReusableCellWithReuseIdentifier(
identify, forIndexPath: indexPath)
as
UICollectionViewCell
// 添加图片
let
img =
UIImageView
(image:
UIImage
(named: courses[indexPath.item][
"pic"
]!))
img.frame = cell.bounds
// 图片上面显示课程名称,居中显示
let
lbl =
UILabel
(frame:
CGRectMake
(0,5,cell.bounds.size.width,20))
lbl.textAlignment =
NSTextAlignment
.
Center
lbl.text = courses[indexPath.item][
"name"
]
cell.addSubview(img)
cell.addSubview(lbl)
return
cell
}
/* 自定义布局不需要调用
//单元格大小
func collectionView(collectionView: UICollectionView!,
layout collectionViewLayout: UICollectionViewLayout!,
sizeForItemAtIndexPath indexPath: NSIndexPath!) -> CGSize {
let size:Float = indexPath.item % 3 == 0 ? 200 : 100
return CGSize(width:size, height:size)
}
*/
}
|