Swift - 使用网格(UICollectionView)的自定义布局实现复杂页面

网格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)
     }
     */
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值