zoukankan      html  css  js  c++  java
  • UICollectionView在Swift3.0中的用法

    UICollectionView在Swift3.0中的用法

    UICollectionView的初始化跟OC中是相似的,创建 GameView 集成自 UICollectionView 。注意不同于UITableView的用法,他需要用 UICollectionViewFlowLayout 来指定一些需要设置的属性,或者可以通过遵守

    UICollectionViewDelegateFlowLayout 这个代理来实现。下面我用设置属性的方式来实现的,比较方便。

            //布局
            layout.scrollDirection = .vertical//滑动方向  这个就是默认是纵向滑动
            layout.itemSize = CGSize( 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( maiSrc.width, height: 30)//设置headerView的size
            layout.footerReferenceSize = CGSize( 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,  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, 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( maiSrc.width, height: 30)//设置headerView的size
            layout.footerReferenceSize = CGSize( 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")
        }
    }
    
  • 相关阅读:
    simhash算法:海量千万级的数据去重
    卸载pycharm再重新安装后,找不到第三方库
    一个完整的jmeter APP登录接口测试实例
    pycharm主题 变量颜色 自定义
    基于python xlsxwriter、xlrd 生成测试报告
    通过python xlsxwriter模块生成EXCEL柱状图、饼图
    jenkins环境搭建(Windows)
    'pip' 不是内部或外部命令,也不是可运行的程序 或批处理文件 — 处理办法
    python 模块学习——time模块
    Appium 使用android_uiautomator定位元素时报错: The requested resource could not be found, or a request was received using an HTTP method that is not supported by the mapped resource
  • 原文地址:https://www.cnblogs.com/huketianxia/p/5642802.html
Copyright © 2011-2022 走看看