九宫格配图

仿照微博配图布局:

complate.png

如果按照通常的九宫格布局公式,行取整,列取模,得到的是依次排列的布局

例如四张图片时为:

item_4.png

而微博配图的布局样式为

一张图片时:


item_1.png

四张图片时:

item_4_new.png

五张图片时:

item_5.png

七张图片时:

item_7.png

九张图片时:

item_9.png

不同点在于当只有四张配图时布局有所变化,所以行与列的公式需要调整:

      //计算行数和列数 如果个数为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
            })
        }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容