本文的例子和Swift版本是基于Xcode7.2的。以后也许不知道什么时候会更新。
我们要干点啥
用新浪微博的Open API做后端来实现我们要提到的功能。把新浪微博的内容,图片和文字展示在collection view中。本文只简单的展示内容。下篇会用pinterest一样的效果来展示这些内容。
我们准备优先展示图片。你的好友花了那么多时间拍照或者从相册里选择图片发上来多不容易。如果微博返回的数据中有中等大小的缩略图,那么久展示这个缩略图。否则的话显示文本。文本都没有的话。。。这个就不是微博了。但是我们还是会准备一个颜色显示出来。
啥是UICollectionView
UICollectionView有一个灵活的布局,可以用各种不同的布局展示数据。
UICollectionView的使用和UITableView类似,也是需要分别去实现一组datasource的代理和UICollectionView本身的代理来把数据展示在界面中。
UICollectionView也是UIScrollView的一个子类
其他的还有:
1. UICollectionViewCell:这些Cell组成了整个UICollectionView,并作为子View添加到UICollectionView中。可以在Interface builder中创建,也可以代码创建。
2. Header/Footer:跟UITableView差不多的概念。显示一些title什么的信息。
UICollectionView还有一个叫做Decoration view的东西。顾名思义,主要是装饰用的。
不过要用这部分的功能你需要单独写定制的layout。
除了以上说到的内容之外,collection view还有一个专门处理布局的UICollectionViewLayout
。你可以继承UICollectionViewLayout
来创建一个自己的collection view的布局。苹果给了一个基础的布局UICollectionViewFlowLayout
,可以实现一个基本的流式布局。这些会在稍后的教程中介绍。
开始我们的项目:
首先创建一个single view的应用。
然后给你的项目起一个名字,我们这里就叫做CollectionViewDemo
。Storyboard中默认生成的Controller已经木有什么用处了。直接干掉,拖一个UICollectionViewController
进去并设置为默认的Controller。并删除默认生成的ViewController.swift文件,并创建一个叫做HomeCollectionViewController.swift的文件。之后在interface builder中把collection view的类设置为HomeCollectionViewController
。
然后:
- 在Storyboard中添加一个navigation controller
- 把collection view设置为上面的navigation controller的root view controller。
- 把这个navigation controller设置为initial view controller。
接下来再次回到collection view controller。这个
进一步了解UICollectionView
如前文所述,UICollectionView和UITableView类似,都有datasource和delegate。这样就可以设置datasource和设置一些用户的交互,比如选中某一个cell的时候怎么处理。
UICollectionViewFlowLayout
有一个代理:UICollectionViewDelegateFlowLayout
。通过这个代理可以设定布局的一些行为比如:cell的间隔,collection view的滚动方向等。
下面就开始在我们的代码中给UICollectionViewDataSource
和UICollectionViewDelegateFlowLayout
两个代理的方法做一个填空。UICollectionViewDelegate
里的方法暂时还用不着,稍后会给这个代理做填空。
实现UICollectionViewDataSource
这里我们用微博开放API为例。从微博的开发API上获取到当前用户的全部的微博,然后用UICollectionView展示。获取到的微博time line最后会放在这里:
private var timeLineStatus: [StatusModel]?
在data source中的代码就很好添加了。
// MARK: UICollectionViewDataSource
override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1 //1
}
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.timeLineStatus?.count ?? 0 //2
}
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath)
cell.backgroundColor = UIColor.orangeColor() //3
return cell
}
- 我们只要一个section,所以这里返回数字1。
- 返回的time line都会放在类型为
StatusModel
的数组里。这个数组可能为空,因为很多情况会影响到网络请求,比如网络不通的时候。这个时候返回的time line就是空了。所以self.timeLineStatus?.count
得出的数字也可能是空,那么这个时候就应该返回0。 - 由于没有合适的Cell返回,现在只好用改变Cell的背景色的方式看到Cell的排布。
效果是这样的:
UICollectionViewFlowLayoutDelegate
这个代理的作用和UITableView的func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
有非常类似的作用。heightForRowAtIndexPath
的作用是返回UITableViewCell的高度。而UICollectionViewCell有非常多的不同的大小,所以需要更加复杂的代理方法的支持。其中包括两个方法:
// 1
class HomeCollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout
// 2
private let sectionInsets = UIEdgeInsets(top: 10.0, left: 10.0, bottom: