仿照微博配图布局:
如果按照通常的九宫格布局公式,行取整,列取模,得到的是依次排列的布局
例如四张图片时为:
而微博配图的布局样式为
一张图片时:
四张图片时:
五张图片时:
七张图片时:
九张图片时:
不同点在于当只有四张配图时布局有所变化,所以行与列的公式需要调整:
//计算行数和列数 如果个数为4,显示两行两列的正方形分布
let col = count == 4 ? 2 : (count >= 3 ? 3 : count)
let row = count == 4 ? 2 : ((count - 1 ) / 3 + 1)
封装代码:
import UIKit
//item重用标识
private let pictureCellId = "pictureCellId"
//item间距
private let itemMargin: CGFloat = 5
//计算Cell宽高 ScreenW为屏幕宽度 margin为自定义屏幕间距
private let itemWH = ( SCREENW - margin * 2 - itemMargin * 2) / 3
class JSPictureCollectionView: UICollectionView {
//配图数组
var pic_urls: [JSPictureModel]?{
didSet{
//设置约束
self.snp_updateConstraints { (make) in
make.size.equalTo(getCollectionViewSize((pic_urls?.count)!))
}
//设置数据
reloadData()
}
}
private func getCollectionViewSize (count: Int) -> CGSize {
//计算行数和列数 如果个数为4,显示两行两列的正方形分布
let col = count == 4 ? 2 : (count >= 3 ? 3 : count)
let row = count == 4 ? 2 : ((count - 1 ) / 3 + 1)
//计算配图CollectionView的宽高
let width = CGFloat(col) * itemWH + CGFloat( col - 1 ) * itemMargin
let height = CGFloat(row) * itemWH + CGFloat( row - 1 ) * itemMargin
return CGSizeMake(width, height)
}
override init(frame: CGRect, collectionViewLayout layout: UICollectionViewLayout) {
super.init(frame: frame, collectionViewLayout: UICollectionViewFlowLayout())
//设置UI
setupUI()
}
private func setupUI () -> () {
backgroundColor = UIColor.whiteColor()
//设置数据源代理
dataSource = self
//注册Cell
registerClass(JSPictureCell.self, forCellWithReuseIdentifier: pictureCellId)
//获取到layout
let flowLayout = collectionViewLayout as! UICollectionViewFlowLayout
//设置itemSize为CollectionView的宽高
flowLayout.itemSize = CGSizeMake(itemWH, itemWH)
//设置垂直、水平间距
flowLayout.minimumLineSpacing = itemMargin
flowLayout.minimumInteritemSpacing = itemMargin
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
extension JSPictureCollectionView: UICollectionViewDataSource {
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return pic_urls?.count ?? 0
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(pictureCellId, forIndexPath: indexPath) as! JSPictureCell
cell.picture = pic_urls![indexPath.item]
return cell
}
}
class JSPictureCell: UICollectionViewCell {
//图片数据
var picture: JSPictureModel?{
didSet{
pictureView.sd_setImageWithURL(NSURL(string: picture?.thumbnail_pic ?? ""), placeholderImage: UIImage(named: "tabbar_discover"))
}
}
//懒加载
private lazy var pictureView: UIImageView = {
let imgView = UIImageView()
imgView.contentMode = UIViewContentMode.ScaleAspectFit
return imgView
}()
override init(frame: CGRect) {
super.init(frame: frame)
//添加控件
contentView.addSubview(pictureView)
//添加约束
pictureView.snp_makeConstraints { (make) in
// make.size.equalTo(contentView)
// make.edges.equalTo(contentView)
make.edges.equalTo(contentView).offset(UIEdgeInsetsZero)
}
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
CollectionView自身的Size已经根据图片的个数进行了约束,在调用该类时,只需要补齐其它约束即可
并且需要根据是否有值,判断CollectionView的显示与否,同时与之相关的约束也需要记录并进行更新
例如:
//用来记录需要更新的底部约束
private var originalBottomContraint: Constraint?
记录约束
//这里的self是CollectionView配图的父视图
//如果有配图,父视图的底部约束就在配图底部的基础上加上一个边距
//如果没有配图,父视图的底部约束就由其他子控件的底部加上边距
self.snp_makeConstraints { (make) in
originalBottomContraint = make.bottom.equalTo(pictureView).offset(margin).constraint
}
//设置配图
originalBottomContraint?.uninstall()//卸载约束
if userInfo?.pic_urls?.count > 0{
//有配图
pictureView.hidden = false
pictureView.pic_urls = userInfo?.pic_urls
self.snp_updateConstraints(closure: { (make) in
originalBottomContraint = make.bottom.equalTo(pictureView).offset(margin).constraint
})
} else {
//没有配图
pictureView.hidden = true
self.snp_updateConstraints(closure: { (make) in
originalBottomContraint = make.bottom.equalTo(messageLabel).offset(margin).constraint
})
}