62-Swift之轮播图(UICollectionView)

一、 前言

在现在App中首页信息展示非常重要,那问题就来了,如何在有限的空间来展示更多的产品信息呢?随着时代的进步,App的开发人员找到了一种能够满足首页信息更多展示的控件--轮播图。在轮播图的实现中多种多样,今天我们介绍一个实现的方法。使用 UICollectionView来实现,同时减少内存资源的消耗。

二、为什么选择 UICollectionView 做组件?

  • UICollectionView 可以减少内存资源的消耗,它是有两个Item进行展示的。

  • UICollectionView 在Item 滑动的过程中十分流畅。

  • UICollectionView 可以实现各种样式的效果。

三、本Demo 使用到的知识点如下

  • UICollectionView 的使用等一系列知识

  • 对象类型的判断 (is)

  • 图像的异步加载

  • 通知的添加和发出

  • 给一个类添加一个代理事件

  • 定时器的使用

  • UIPageControl 的使用等一些列知识

  • 如何解决 UICollectionViewCell 的复用问题

  • 可变数组的一些对元素的基本操作

四、本 Demo 的实现效果

Untitled.gif

五、关键代码的展示

1> UICollectionView的创建

// TODO: 创建 UICollectionView对象
func createCollectionView(_rect:CGRect) -> Void {
    // 创建对象
    collectionView = UICollectionView.init(frame:CGRect.init(x: 0, y: 0, width: _rect.size.width, height: _rect.size.height), collectionViewLayout:self.createFlowLayout())
    // 设置代理
    collectionView.delegate = self
    collectionView.dataSource = self
    // 隐藏活动标尺
    collectionView.showsHorizontalScrollIndicator = false
    // 设置 UICollectionView 分页滑动
    collectionView.isPagingEnabled = true
    // 注册 cell
    collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: cellId)
    // 初始让 UICollectionView 显示第二个 Item
    collectionView!.scrollToItem(at: IndexPath.init(row: 1, section: 0), at: .centeredHorizontally, animated: true)
    // 进行渲染
    self.addSubview(collectionView)
}

2> 布局对象的创建

// TODO: 创建布局对象
func createFlowLayout() -> UICollectionViewFlowLayout {
    // 创建对象
    let flowLayout = UICollectionViewFlowLayout.init()
    // 设置滑动方向
    flowLayout.scrollDirection = .horizontal
    return flowLayout
}

3> UICollectionView 的代理事件的实现

// MARK: CollectionView的代理事件

// UICollectionView 返回的 Section 的个数,也可以不写该代理。默认为一
func numberOfSections(in collectionView: UICollectionView) -> Int {
    return 1
}

// UICollectionView返回的Item个数
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return (self.handDataArray?.count)!
}

// 设置 Item 的大小
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    return self.bounds.size
}

// 设置 Item 之间的间隔
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
    return 0.0
}

// 创建和设置 UICollectionViewCell
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    // 创建对象
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath)
    // 防止cell复用产生
    for item in cell.contentView.subviews {
        item.removeFromSuperview()
    }
    // 创建展示对象
    let cellImageView = UIImageView.init(frame: cell.bounds)
    cellImageView.contentMode = .scaleAspectFit
    cellImageView.image = UIImage.init(named: "defaut.png")
    cellImageView.isUserInteractionEnabled = true
    // 加载图像
    let temp = self.handDataArray?[indexPath.row]
    self.asynLoadImage(temp: temp!, imageView: cellImageView,index: indexPath)
    cell.contentView.addSubview(cellImageView)
    // 返回创建对象
    return cell
}

// CollectionView 的 Item 点击事件
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    if self.delegate != nil {
        self.delegate?.didSelecdItem(index: indexPath)
    }
}

4> ShufflingViewDelegate 的代理声明

protocol ShufflingViewDelegate:NSObjectProtocol {
    func didSelecdItem(index:IndexPath) -> Void
}

5> 网络异步加载

// MARK: 异步加载图像
func asynLoadImage(temp:Any,imageView:UIImageView,index:IndexPath) -> Void {
    // 判断对象的类型
    // UIImage 类型
    if temp is UIImage {
        imageView.image = (temp as! UIImage)
        return
    }
    var tempRequest:Any?
    // URL
    if temp is URL {
        tempRequest = temp as! URL
    }
    if temp is String {
         tempRequest = URL.init(string: temp as! String)
    }
    let request = URLRequest.init(url: tempRequest as! URL, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 30)
    let session = URLSession.shared
    let dataTask = session.dataTask(with: request, completionHandler: {
        (data, response, error) -> Void in
        if error != nil{
            print(error.debugDescription)
        }else{
            //将图片数据赋予UIImage
            let img = UIImage(data:data!)
            imageView.image = img
            self.handDataArray?.replaceObject(at: index.row, with: img as Any)
        }
    }) as URLSessionTask
    //使用resume方法启动任务
    dataTask.resume()

6>可变数组的元素简单操作

// 处理传入的数据
func handlingData(array:NSArray) -> Int {
    // 初始化可变数组
    self.handDataArray = NSMutableArray.init(capacity: 0)
    // 判断是否存在
    if array.count != 0 {
        self.handDataArray = NSMutableArray.init(array: array)
        self.handDataArray?.add(array.firstObject!)
        self.handDataArray?.insert(array.lastObject!, at: 0)
        return array.count
    }
    return 3
}

7> 定时器的创建

// 定时器的创建
func createTimer() -> Void {
     timer = Timer.scheduledTimer(withTimeInterval: 5, repeats: true, block: { (timer) in
        // 获取 UICollectionView 的水平偏移
        let horizontalOffsetX =  self.collectionView.contentOffset.x
        // 计算滑动的个数
        var pageIndex = Int(horizontalOffsetX) / Int(self.bounds.width)
        // 判断图像是否是倒数第二个
        if pageIndex  == (self.handDataArray?.count)! - 1 {
            // 让图像滑动到UICollectionView的第二个Item的位置
            self.collectionView!.scrollToItem(at: IndexPath.init(row: 2, section: 0), at: .centeredHorizontally, animated: false)
            pageIndex = 2
        }else if pageIndex == (self.handDataArray?.count)!-2 {
            pageIndex = 1
            self.collectionView!.scrollToItem(at: IndexPath.init(row: ((self.handDataArray?.count)!-1), section: 0), at: .centeredHorizontally, animated: true)
        }else {
            self.collectionView!.scrollToItem(at: IndexPath.init(row: pageIndex+1, section: 0), at: .centeredHorizontally, animated: true)
            pageIndex = pageIndex + 1
        }
        // 设置小白点的显示
        self.pageControl.currentPage = pageIndex - 1
     })
}

8> 小白点的添加

// 小白点的创建
func createPageControl(index:Int) -> Void {
    pageControl = UIPageControl.init(frame: CGRect.init(x: self.bounds.width - 85, y: self.bounds.height - 30, width: 70, height: 20))
    pageControl.numberOfPages = index
    pageControl.currentPageIndicatorTintColor = UIColor.red
    pageControl.pageIndicatorTintColor = UIColor.white
    self.addSubview(pageControl)
}

9> 滑动的效果实现

// CollectionView的滑动事件
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
    self.createTimer()
    // 获取 UICollectionView 的水平偏移
    let horizontalOffsetX =  scrollView.contentOffset.x
    // 计算滑动的个数
    var pageIndex = Int(horizontalOffsetX) / Int(self.bounds.width)
    // 判断图像是否是倒数第二个
    if pageIndex == (self.handDataArray?.count)! - 1 {
        // 让图像滑动到UICollectionView的第二个Item的位置
        collectionView!.scrollToItem(at: IndexPath.init(row: 1, section: 0), at: .centeredHorizontally, animated: false)
        pageIndex = 1
    }
    if pageIndex == 0 {
        collectionView!.scrollToItem(at: IndexPath.init(row: ((self.handDataArray?.count)!-2), section: 0), at: .centeredHorizontally, animated: false)
        pageIndex = (self.handDataArray?.count)!-2
    }
    // 设置小白点的显示
    self.pageControl.currentPage = pageIndex - 1
}

10> 整体的使用

    // 轮播图的调用实现
    override func viewDidLoad() {
        super.viewDidLoad()
        // 编辑数据
        let imageArray = NSMutableArray.init(capacity: 0)
        for i in 0..<4 {
            let  str = String.init(format: "%d.jpg",i)
            imageArray.add(UIImage.init(named: str)!)
        }
        let suf = ShufflingView.init(frame: CGRect.init(x: 0, y: 64, width: self.view.frame.width, height: 160),dataArray: imageArray)
        suf.delegate = self
        self.view.addSubview(suf)
        
    }
    
    // MARK:  协议的实现
    func didSelecdItem(index: IndexPath) {
         print(index.row)
    }

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,406评论 5 475
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,976评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,302评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,366评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,372评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,457评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,872评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,521评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,717评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,523评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,590评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,299评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,859评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,883评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,127评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,760评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,290评论 2 342

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,357评论 25 707
  • UICollectionView是我们常说的集合视图,它在iOS 6中引入,是iOS开发者中最受欢迎的UI元素之一...
    pro648阅读 10,593评论 18 44
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,010评论 4 62
  • 外边的夜是安静而清冷的 灯光安静的亮着 指引着回家的行人 家中夜是安静而温暖的 书轻轻地展在面前 文字里讲述着悲欢...
    遇见更美的自己阅读 175评论 0 0
  • 第一章 天宫茶市集
    qqminghome阅读 269评论 0 0