iOS UICollectionView 横向滑动 多页 自定义UICollectionViewFlowLayout实现

4 篇文章 0 订阅

import UIKit

class WorkViewF2lowLayout: UICollectionViewFlowLayout {
    var numRow:Int = 0;//行数
    var numCol:Int = 0;//列数
    var pageNumber :NSInteger = 1;
    var itemSpacing : CGFloat = 0;//左右间距
    var lineSpacing :CGFloat = 0;// 上下间距
    
    
    
    var contentInsets: UIEdgeInsets =  UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
    //所有cell的布局属性
    var layoutAttributes: [UICollectionViewLayoutAttributes] = [UICollectionViewLayoutAttributes]();
    
    override init() {
        super.init();
        self.itemSize = CGSize(width: SCREEN_WIDTH/4 , height: 95);
        self.scrollDirection = .horizontal
        self.numRow = 2;
        self.numCol = 4;
        self.contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
    }
    override func prepare() {
        
        let itemNumber : NSInteger = ((self.collectionView?.numberOfItems(inSection: 0))!)
        pageNumber = (itemNumber-1)/(numRow * numCol)+1 //13-1   12/8 = 1     :2
    }
    //返回制定indexPath的item布局信息
    override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
        let attributte = UICollectionViewLayoutAttributes.init(forCellWith: indexPath)
        var fram1 : CGRect = CGRect.init(x: 0, y: 0, width: 0, height: 0)
        fram1.size = self.itemSize
        let number : Int = numCol*numRow
        var m : Int = 0
        var p : Int = 0
        if indexPath.item >= number {
            p = indexPath.item/number          //大于等于8 的时候 p = 1
            m = (indexPath.item%number) / numCol // m来确定第二页的时候的m
        }else {
            m = indexPath.item/numCol     //每页8个item.当小于8(0...7)m/4 来判断是第一行还是第二行, m用来计算item的y
        }
       let n  =  indexPath.item%numCol  //n用来计算item的x
        let k = indexPath.section + p //计算有几页 这个flowlayout只有一个分区的时候计算正确
    print("item ===\(indexPath.item),n====\(n),m===\(m),p==\(p),k===\(k)")
       let width :CGFloat = self.itemSize.width
       let height :CGFloat = self.itemSize.height
        
        //计算水平距离  item的宽度*第几个item+第几个item *左右间距+左间距+第几页*k集合视图的宽度
        var x:CGFloat = CGFloat(n) * width + CGFloat(n) * itemSpacing + self.contentInsets.left
        x = x + CGFloat(k) * (self.collectionView?.frame.size.width)!
        //计算y 第几行*item的高度 + 第几行*上下间距+ top间距
        let y :CGFloat = CGFloat(m) * height + CGFloat(m) * lineSpacing + self.contentInsets.top
        
        //设置item 的frame
        attributte.frame = CGRect.init(x:x, y: y, width: self.itemSize.width, height: self.itemSize.height)
        print("frame======\(attributte.frame)")
        return attributte
    }
    //为所有item返回一个layout attributes数组,数组中元素的类型为UICollectionViewLayoutAttributes。UICollectionViewLayoutAttributes记录了一个layout的位置、大小、透明度等信息。

    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        let temAttributes = NSMutableArray.init(capacity: 1)
        let N :Int  = ((self.collectionView?.numberOfSections)!)
        for j in 0..<N{
            let count : Int = (self.collectionView?.numberOfItems(inSection: j))!
            for i in 0..<count{
                let indexPath : NSIndexPath =  NSIndexPath.init(item: i, section: j)
                //循环添加UICollectionViewLayoutAttributes进数组
                temAttributes.add(self.layoutAttributesForItem(at: indexPath as IndexPath) as Any)
            }
        
        }
        return (temAttributes as! [UICollectionViewLayoutAttributes])
    }
    //重写集合视图的size
   override open var collectionViewContentSize: CGSize  {
        return CGSize.init(width: (self.collectionView?.bounds.size.width)! * CGFloat(pageNumber), height: (self.collectionView?.bounds.size.height)!)
    }
    //询问是否需要从新布局
    override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
        return false
    }
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

使用方法

import UIKit
import Foundation 
class workView: UIView ,UICollectionViewDelegate,UICollectionViewDataSource,UIScrollViewDelegate {

    
    var collectionView:UICollectionView?
    var pagCon :UIPageControl?
    
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        self.backgroundColor = UIColor.yellow
        collectionView = UICollectionView.init(frame: CGRect.init(x: 0, y: 0, width: frame.width, height: frame.height), collectionViewLayout: WorkViewF2lowLayout())
        collectionView?.backgroundColor = UIColor.white
        collectionView?.delegate = self
        collectionView?.dataSource = self
      
        collectionView?.isPagingEnabled = true
        collectionView?.register(UINib.init(nibName: "workCollCell", bundle: Bundle.main), forCellWithReuseIdentifier: "cell")
        self.addSubview(collectionView!)
        
        
        pagCon = UIPageControl.init(frame: CGRect(x: 0, y: 147.5, width: 90, height: 10))
        pagCon?.numberOfPages = 2
        pagCon?.currentPageIndicatorTintColor = UIColor.green
        pagCon?.center = CGPoint.init(x: SCREEN_WIDTH/2, y: 180)
        pagCon?.pageIndicatorTintColor = UIColor.blue
        self.addSubview(pagCon!)
        
        
        
    }

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        let pageNumber:Int = Int(scrollView.contentOffset.x / SCREEN_WIDTH + 0.5);
        pagCon?.currentPage = pageNumber
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
      return 13
    }
   
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! workCollCell

        return cell
        
    }
    
    func  collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        print("第---\(indexPath.section)区---\(indexPath.row)行")
    }
    
}

注意的点: 1.当计算item的frame的x是,习惯性的写了一长串的计算式子,然后就报错了,错误信息的大概意思是不能在时间内计算好结果。解决方式就是需要我们去拆分,分开计算。。。

                 2. swift计算中 Int和CGFloat不能进行加减乘除等数学计算,只能先把int数据转成CGFloat,类如 CGFloat(m)

                 3. oc中的for (int i = 0, i<5;i++)已经被取消了,swift中使用 for i in 0..<5 ;0..<5代表的是0到4,0...5代表的0到5

                  4.swift中的print 很方便,不用在像以前oc还需要写它的类型,现在只要\() 例如:print("ssss的值==\(m)")

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值