UICollectionView在Swift3.0中的用法
UICollectionView的初始化跟OC中是相似的,创建 GameView 集成自 UICollectionView 。注意不同于UITableView的用法,他需要用 UICollectionViewFlowLayout 来指定一些需要设置的属性,或者可以通过遵守
UICollectionViewDelegateFlowLayout 这个代理来实现。下面我用设置属性的方式来实现的,比较方便。
//布局
layout.scrollDirection = .vertical//滑动方向 这个就是默认是纵向滑动
layout.itemSize = CGSize(width: width, height: width)//item的size
layout.sectionInset = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)//section距上下左右的数据
layout.minimumLineSpacing = CGFloat(integerLiteral: 5)//如果是纵向滑动的话即行间距,如果是横向滑动则为列间距
layout.minimumInteritemSpacing = CGFloat(integerLiteral: 5)//如果是纵向滑动的话即列间距,如果是横向滑动则为行间距
layout.headerReferenceSize = CGSize(width: maiSrc.width, height: 30)//设置headerView的size
layout.footerReferenceSize = CGSize(width: maiSrc.width, height: 30)//设置footerView的size
下边直接贴出整个的源码 ,调用就异常简单了 :
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.view.backgroundColor = UIColor.white() let game = GameView.init(frame: CGRect(x: 0, y: 20, width: maiSrc.width, height: maiSrc.height - 20))
self.view.addSubview(game) }
源码 :
//
// GameView.swift
// CharacterGame
//
// Created by 江南花印孓 on 2016/6/28.
// Copyright © 2016年 恒江. All rights reserved.
// import UIKit let identifier = "identifier"
let headerIdentifier = "headerIdentifier"
let footerIdentifier = "footerIdentifier" class GameView: UICollectionView ,UICollectionViewDelegate ,UICollectionViewDataSource ,UICollectionViewDataSourcePrefetching{ internal var num = 6
internal var items = 196
var source = [Int]() //MARK:---------这里是一个 init 初始化标记
init(frame:CGRect) {
//TODO: -----int 初始化方法 里边要做的事情----
let layout = UICollectionViewFlowLayout.init()//通过Layout的一些属性把对应数据设置好,则不用再实现对应函数
let leftWidth = maiSrc.width - CGFloat(integerLiteral: ( num + 1 ) * 5)
let width = leftWidth / CGFloat(integerLiteral: num)
for i in 1...items {
source.append(i)
}
//FIXME: 问题一 : 除了使用layout属性设置还可以用什么方法来实现?
//布局
layout.scrollDirection = .vertical//滑动方向 这个就是默认是纵向滑动
layout.itemSize = CGSize(width: width, height: width)//item的size
layout.sectionInset = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)//section距上下左右的数据
layout.minimumLineSpacing = CGFloat(integerLiteral: 5)//如果是纵向滑动的话即行间距,如果是横向滑动则为列间距
layout.minimumInteritemSpacing = CGFloat(integerLiteral: 5)//如果是纵向滑动的话即列间距,如果是横向滑动则为行间距
layout.headerReferenceSize = CGSize(width: maiSrc.width, height: 30)//设置headerView的size
layout.footerReferenceSize = CGSize(width: maiSrc.width, height: 30)//设置footerView的size //FIXME: 注意这个父类 init 方法写在这里了
super.init(frame: frame, collectionViewLayout: layout) //初始化
self.backgroundColor = UIColor.white()
self.delegate = self
self.dataSource = self
self.prefetchDataSource = self;//这个协议对应 UICollectionViewDataSourcePrefetching 是 10.0 以后新加的两个方法,下面介绍
self.isPrefetchingEnabled = true//允许实现 UICollectionViewDataSourcePrefetching 这个协议 10.0 后新加的
self.allowsMultipleSelection = true//允许多选
self.showsVerticalScrollIndicator = false //右侧那条上下滑动的线 //这三个方法可以看底层说明,讲的很详细
self.register(singleCell.self, forCellWithReuseIdentifier: identifier)
self.register(headerView.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: headerIdentifier)
self.register(footerView.self, forSupplementaryViewOfKind: UICollectionElementKindSectionFooter, withReuseIdentifier: footerIdentifier) //FIXME: 一个很实用的系统定义宏 , 用来打印对应object的所有属性信息
dump(self) /*
* 重排手势 UICollectionViewController 里有一个默认为 true 的属性用来设置开启重排手势功能,实现对应的代理函数即可实现对应功能。
* collectionView(_ : , moveItemAt : , to : )
* 这里集成自 UICollectionView ,没有手势,所以需要添加一个 长按手势 。
*/
let longGesture = UILongPressGestureRecognizer.init(target: self, action: #selector(handlelongGesture))
self.addGestureRecognizer(longGesture)
} //MARK: --------------- my action ------------
func handlelongGesture(longGesture:UILongPressGestureRecognizer) -> Void {
switch longGesture.state {
case .began:
//判断手势落点所在 item 的 indexPath 是否在 collectionView 内
let index = self.indexPathForItem(at: longGesture.location(in: self))
if index == nil {
break
}
//如果在,那么就开始移动这个位置上的cell
self.beginInteractiveMovementForItem(at: index!)
break
case .changed:
//当位置发生偏移时调用该函数,判断新的位置是否在 collectionView 以内来决定是放回原位置还是移动到新的位置
self.updateInteractiveMovementTargetPosition(longGesture.location(in: self))
print("on the way")
break
case .ended:
/*
* 接受后调用下边两个函数中的一个通知 collectionView 轨迹交互移动已经结束,把item永久的移动到新位置,同时响应
* collectionView(_ : , moveItemAt : , to : ) 函数 来处理数据源 确保数据源的数据结构没问题
*/
self.endInteractiveMovement()
break
default:
self.cancelInteractiveMovement()
break
}
} //MARK: -------- UICollection View Delegate -------
func collectionView(_ collectionView: UICollectionView, canMoveItemAt indexPath: IndexPath) -> Bool {
return true
} /* 注意:cell重置需要在 UICollectionViewController 里开启一个手势 installsStandardGestureForInteractiveMovement 开关
* 之后由控制器给 collectionView 添加长按手势 LongPressGesture 之后才会走下边的函数
* 单纯的 collectionView 并没有这个手势,所以无法触发这个代理
*/
func collectionView(_ collectionView: UICollectionView, moveItemAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
let str = source[sourceIndexPath.item!]
source.remove(at: sourceIndexPath.item!)
source.insert(str, at: destinationIndexPath.item!)
print("this is a test String")
} override func numberOfSections() -> Int {
return 1
} func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return items
} func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: identifier, for: indexPath) as! singleCell
let index = source[indexPath.item!]
cell.age.text = String.init(index)
cell.backgroundColor = UIColor.red()
return cell
} func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { /**
* 注意要点
* 1.supplementaryView 的返回类型为 UICollectionReusableView ,不能混淆,Swift里边对于返回值的类型要去很严格。
* 2.UICollectionReusableView 继承自 UIView ,是 UIView 的子类
* 3.kind 分为 footer 和 header 两种,区分开来
* 4.kind 和 identifier 要对应起来,因为是两个不同的 reuse identifier
*/
if kind == UICollectionElementKindSectionHeader {
let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: headerIdentifier, for: indexPath) as! headerView
header.name.text = "测试" return header
}
let footer = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: footerIdentifier, for: indexPath)
return footer
} func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { let index = indexPath.item! as Int
print("\(index)")
} //MARK: ----------- UICollectionViewDataSourcePrefetching 预取 缓存 -----
/* 获取 ‘预取’ 地址集合 item出现之前的预处理,iOS 10.0以后新加的,不明觉厉。。不知道有什么用
* 目前来看 只能是单纯的提升运行效率 做一下预处理。。。
* 当界面显示不完 item 时 , 类似复用队列一样可以缓存一部分尚未显示出来的 item ,具体缓存多少目前还没搞清楚,
* 貌似跟几何面积有关,单个item越大,缓存的行数越少;相反,item的size越小,缓存的行数越多
*/
func collectionView(_ collectionView: UICollectionView, prefetchItemsAt indexPaths: [IndexPath]) {
//dump(indexPaths)
}
/*
* optional public func collectionView(_ collectionView: UICollectionView, cancelPrefetchingForItemsAt indexPaths: [IndexPath])
* 这个函数的作用看文档说明,个人理解为 已经缓存,事实上却又没有用到,就是没有显示的 item 的子集。
*/ required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
} class headerView: UICollectionReusableView { override init(frame: CGRect) {
super.init(frame: frame) self.addSubview(name)
//单纯的个体案例 用不到三方框架 用 VFL 适配
self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[name]-0-|",
options: [],
metrics: nil,
views: ["name":name])) self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[name]-0-|",
options: [],
metrics: nil,
views: ["name" : name ]))
self.backgroundColor = UIColor.orange()
} //懒加载
lazy var name: UILabel = {
let name = UILabel.init()//2098
name.translatesAutoresizingMaskIntoConstraints = false
name.backgroundColor = UIColor.red()//
name.textAlignment = .center
name.textColor = UIColor.white()
return name
}() required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
} class footerView: UICollectionReusableView {
override init(frame: CGRect) {
super.init(frame: frame) self.backgroundColor = UIColor.green()
} required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
class singleCell: UICollectionViewCell { override init(frame: CGRect) {
super.init(frame: frame)
self.addSubview(age) self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-[age]-|",
options: [],
metrics: nil,
views: ["age":age])) self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-[age]-|",
options: [],
metrics: nil,
views: ["age" : age ]))
} lazy var age: UILabel = {
let age = UILabel.init()
age.translatesAutoresizingMaskIntoConstraints = false
age.backgroundColor = UIColor.blue()
age.textAlignment = .center
age.textColor = UIColor.white()
age.text = "0"
return age
}() required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
UICollectionView在Swift3.0中的用法的更多相关文章
-
Swift3.0中关于日期类的使用指引
日期的处理在大大小小的iOS项目中都十分常见,随着Swift3.0正式版的即将推出,语法的改变让NSDate以及相关类的使用都与之前略有不同,这里将会对基于Swift3.0版本的NSDate及相关类的 ...
-
swift3.0 中NSNotification 的使用
swift3.0 有很大变化,其中之一就是NSNotification使用跟原来不一样,以前NSNotification name是String:3.0中定义了一个类型NSNotification.n ...
-
Swift3.0 中 Strings/Characters 闲聊
前言 本篇文章主要浅析字符串\字符在 Swift 和 Objective-C 之间的区别及其简单用法.如有不妥的地方还望大家及时帮忙纠正. 字符串判空 在 swift 语言中空字符串初始化方式常用的有 ...
-
Swift3.0变化分享
Swift 3.0 做出的改变很大,在这篇文章中,我将尽我所能,利用代码样例给大家解释Swift 3.0最重要(要命)的改变,希望大家能够做好升级Swift 3.0 的准备.Swift 3.0的改变不 ...
-
swift3.0变化总结
Swift 3.0 做出的改变很大,在这篇文章中,我将尽我所能,利用代码样例给大家解释Swift 3.0最重要(要命)的改变,希望大家能够做好升级Swift 3.0 的准备.Swift 3.0的改变不 ...
-
Swift2.3 -->; Swift3.0 的变化
Swift3.0语法变化 首先和大家分享一下学习新语法的技巧: 用Xcode8打开自己的Swift2.3的项目,选择Edit->Convert->To Current Swift Synt ...
-
Swift3.0都有哪些变化
从写第一篇Swift文章的时候到现在Swift已经从1.2发展到了今天的3.0,这期间由于Swift目前还在发展阶段并不能向下兼容,因此第一篇文章中的部分代码在当前的Xcode环境中已经无法运行.在W ...
-
iOS 日期处理 (Swift3.0 NSDate)
处理日期的常见情景 NSDate -> String & String -> NSDate 日期比较 日期计算(基于参考日期 +/- 一定时间) 计算日期间的差异 拆解NSDate ...
-
Swift3.0语法变化
写在前面 首先和大家分享一下学习新语法的技巧:用Xcode8打开自己的Swift2.3的项目,选择Edit->Convert->To Current Swift Syntax- 让Xcod ...
随机推荐
-
一个js获取数组下标的函数
或许,面试的时候,你可能会被问到怎么模拟字符串的indexOf()函数获取数组的下标,这里是个人实现的一个小函数,里面包含的知识点挺多的,假如是新手,看不懂的地方可以百度,这里就不做详细介绍了,当然, ...
-
vue 2.0
vue2.0 据说也出了很久了,博主终于操了一次实刀. 整体项目采用 vue + vue-router + vuex (传说中的vue 全家桶 ),构建工具使用尤大大推出的vue-cli 项目是 ...
-
贪婪 vs 不贪婪
当重复一个正则表达式时,如用 a*,操作结果是尽可能多地匹配模式.当你试着匹配一对对称的定界符,如 HTML 标志中的尖括号时这个事实经常困扰你.匹配单个 HTML 标志的模式不能正常工作,因为 .* ...
-
Latency
1)在网络,延迟时间(latency),同义词为延迟,是表示从特定点得到一个数据包(packet)所花的时间.在一些情况下(例如,AT&T),延迟时间用发送出包到回到发送端这个运行一周的时间就 ...
-
VC++时间函数总结
目录 第1章基本概念 1 1.1 基本概念 1 1.2 时间表示法 2 第2章 Win32 API 3 2.1 获取 3 2.1.1 时间间隔 3 2.1.2 时刻 ...
-
LabVIEW设计模式系列——普遍使用值改变事件
标准: 1.当使用值改变事件时,使用单击时触发或者单击时释放开关动作.这样即保证仅仅触发一次,也保证按钮恢复默认值 标准:1.值改变事件的优点:不论是鼠标动作还是键盘动作都能触发值改变事件,增强了程序 ...
-
HTML文档类型声明的坑...
如果发现js莫名其妙的报错(比如demo不报错,自己写的就报错),或者样式显示不正常,一定记得检查HTML页面里面加没加如下文档声明: <!DOCTYPE HTML PUBLIC "- ...
-
.net实现依赖注入
.net实现依赖注入 1. 问题的提出 开发中,尤其是大型项目的开发中,为了降低模块间.类间的耦合关系,比较提倡基于接口开发,但在实现中也必须面临最终是“谁”提供实体类的问题.Martin Fowle ...
-
java Queue中 add/offer,element/peek,remove/poll区别
转自https://blog.csdn.net/u012050154/article/details/60572567 java Queue中 add/offer,element/peek,remov ...
-
二进制安装部署kubernetes集群---超详细教程
本文收录在容器技术学习系列文章总目录 前言:本篇博客是博主踩过无数坑,反复查阅资料,一步步搭建完成后整理的个人心得,分享给大家~~~ 本文所需的安装包,都上传在我的网盘中,需要的可以打赏博主一杯咖啡钱 ...