网格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)
    }
    */
}

转载于:https://www.cnblogs.com/Free-Thinker/p/4838300.html

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

  1. iOS开发学无止境 - UICollectionView自定义布局之风火轮[译]

    现在有许多极具创造力的网站,几周前我碰巧浏览到一个名为Form Follows Function的网站,上面有各种交互动画.其中最吸引我的是网站上的导航转轮,转轮由各种交互体验海报组成. 原文:UIC ...

  2. UICollectionView自定义布局(二)

    这是UICollectionView自定义布局的第二篇,实现类似UltravisualApp的视差效果,同样这篇文章的教程来自Ray家的Swift Expanding Cells in iOS Col ...

  3. UICollectionView 自定义布局!看这篇就够了

    各位同学早上好,新的一周又开始啦!眨眼之间,我们就要与3月挥手告别了,时间过得可真快,不禁感慨道"无可奈何花落去,似曾相识燕归来". 最近,我花了很多的时间整理了 UICollec ...

  4. UICollectionView 自定义布局教程: Pinterest

    原文: UICollectionView Custom Layout Tutorial: Pinterest 作者:Paride Broggi 译者:kmyhy 更新说明:本教程由 Paride Br ...

  5. iOS-UICollectionView自定义布局

    UICollectionView自定义布局 转载: http://answerhuang.duapp.com/index.php/2013/11/20/custom_collection_view_l ...

  6. 自定义布局和自定义流水布局(CollectionViewLayout和CollectionViewFlowLayout)实例

    自定义布局和自定义流水布局(CollectionViewLayout和CollectionViewFlowLayout) 转载:https://www.jianshu.com/p/83f2d6ac7e ...

  7. ViewGroup1——自定义布局

    平时开发时,系统提供的几个布局基本就能满足我们的需求了.如果系统提供的布局无法满足需求,我们可以扩展ViewGroup类来实现自定义布局控件.先看下ViewGroup的继承图 由上图可知,ViewGr ...

  8. 从自定义TagLayout看自定义布局的一般步骤[手动加精]

    从自定义TagLayout看自定义布局的一般步骤[手动加精] 我们常用的布局有LinearLayout,FrameLayout,RelativeLayout,大多数情况下都能满足我们的需求,但是也有很 ...

  9. 【Android 性能优化】布局渲染优化 ( 过渡绘制 | 背景设置产生的过度绘制 | Android 系统的渲染优化 | 自定义布局渲染优化 )

    文章目录 一. 背景设置产生的过度绘制 二. Android 系统的渲染优化 1. 透明组件数据传递 2. GPU 存储机制 3. Android 7.0 之后的优化机制 三. 自定义布局渲染优化 一 ...

最新文章

  1. 计图MPI分布式多卡
  2. ImportError:cannot import name ‘display‘ File “XX“, line 5, in <module> from IPython import display
  3. Visual Studio 2019 16.1 第二个预览版发布
  4. c语言是非结构化程序设计语言,第章_结构化程序设计基础和C语言的控制结构(fb).ppt...
  5. python_day9线程、进程和协程
  6. ML之DL:机器学习领域发展最快的分支【深度学习】的发展史及其重要性节点之详细攻略
  7. MySQL 随笔记录
  8. 将MSRA-TD500标签转换成逆时针输出标签+labeleme json格式转四个点的txt
  9. 【实践】多场景下的搜索词推荐算法及在腾讯的应用实践.pdf(附下载链接)
  10. Android Error:Could not find lottie.jar
  11. 我的java web之路(安装)
  12. android m版本 root,Android M或开放更多权限,root还需要吗?
  13. 数据持久层框架Mybatis
  14. 各地级市-国内及外汇旅游收入(1995-2020)
  15. 再也不用花一天时间做ppt了
  16. war3 魔兽争霸3 双开 多开 联机 补丁 工具
  17. 轻量级pdf查看阅读工具Sumatra PDF
  18. 计算机word窗口的组成,word文件的组成
  19. [源码和报告分享]基于C++实现的运动会统分系统
  20. 数字图像处理大作业GUI设计

热门文章

  1. SDH/E1/T1/E3/T3/STM/TDM相关名词介绍
  2. Cassandra使用的各种策略
  3. 使用Wamp搭建Php本地开发环境,HBuilder调试
  4. 【ORACLE】碎片整理
  5. 算法---计数质数(Java)
  6. Android 三角形控件
  7. 支付宝sdk 支付订单查询失败
  8. Activity 启动模式以及常见的启动Flag
  9. 第九周项目一-深体验复制(2)
  10. 第五周项目一-三角形类雏形(2)