写一个可以使用kingfisher加载图片的轮播器PPTView

前言:关于图片轮播的第三方资源已经很多了,其中大多的使用都是很简单方便的, 但是从oc到swift上面来, 就写一写基本的常用的"控件"当作熟悉吧, 如果在这个过程中能帮到一些正在学习的人,个人也还是很开心的

最终效果(和其他效果相似)

轮播图.gif

一. 构思

本次主要实现无限循环滚动, 手动滚动, 显示标题, 响应点击事件, 支持加载网络和本地的图片, 同时这个轮播的一点小小的特点是 : 允许你自己使用第三方的图片加载框架(kingfisher, SDWebImage...)来加载网络图片

注意暂时不支持直接在storyboard中使用, 直接将轮播的view加载到storyboard中的view上面即可使用

1. 轮播图的实现原理, 百度一下就可以找到很多, 这里我就简单说一下

1.1 直接在ScrollView上添加和图片个数一样的imageVIew来显示图片, 在滚动的时候调整ScrollView的contentOffSet即可, 但是图片较多的时候可能占用许多的内存

1.2 在ScrollView上添加两个imageView来显示图片, 其中一个imageView(A)始终显示在屏幕上, 另一个imageView(B)根据滑动的方向添加到对应的左或者右边, 在每次滚动完成的时候,通过调整ScrollView的contentOffSet将 A 始终位于当前屏幕上显示更改后的图片, 滚动过程如下

过程1.png

1.3 在ScrollView上添加三个imageView来显示图片, 原理和上面1.2 有点类似, 每次在滚动完成的时候将中间的那个imageView显示在屏幕上, 滚动过程如下

过程2.png

这里笔者就选择了三个ImageView来实现

2. 实现图片循环滚动

2.1 若使用1.1 的方式实现循环滚动比较难
2.1 若使用1.2和1.3 的方式,原理类似, 用一个数组来缓存"图片"(可能是Url) 根据左右滑动的方向计算出将要显示下一张图片的下标, 只需要处理下标为0 和数组的最后一个元素

3. 响应点击事件类似于之前笔者这个项目中这里给UIlabel添加响应, 给显示在屏幕上的哪一个imageView添加手势, 通过closures(或代理)响应外部点击

4. 允许使用第三方网络库来加载图片,这里我是用到了blosure来加载每一张图片(您也可以使用代理, 类似于UItableViewDatasource,加载的cell个数, cell的内容...)

5. 注意在手动滚动图片的时候要注意关闭计时器,以免松手的时候出现快速滚动, 同时在松手后要开启计时器,继续自动滚动, 这个具体待UIScrollView的代理方法处理里面可以看到

二 实现部分

控件.png

a.从这张图片中我们可以知道这个PPTView需要的控件有

属性.png

具体的处理您可以直接看源码

b. 逻辑处理

// 初始化
    public init(imagesCount: Int, setupImageForImageView: SetupImageForImageView?, pageDidClick: PageDidClickAction?) {
        
        // 这个blosure 处理点击
        self.pageDidClick = pageDidClick
        // 这个blosure获取图片 相当于UITableView的cellForRow...方法
        self.setupImageForImageView = setupImageForImageView
        // 相当于UITableView的numberOfRows...方法
        self.imagesCount = imagesCount
        
        super.init(frame: CGRectZero)
        // 这里面添加了各个控件, 和设置了初始的图片和title
        initialization()
        
    }

// 设置各个控件的位置和scrollView的contentSize(imageView的三倍宽度)
override public func layoutSubviews()


UIScrollView代理方法


    // 手指触摸到时
    public func scrollViewWillBeginDragging(scrollView: UIScrollView) {
        if autoScroll {
            stopTimer()

        }
    }
    
    // 松开手指时
    public func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) {
        if autoScroll {
            startTimer()

        }
    }

    /// 代码设置scrollview的contentOffSet滚动完成后调用
    public func scrollViewDidEndScrollingAnimation(scrollView: UIScrollView) {
        // 重新加载图片
        loadImages()

    }
    
    /// scrollview的滚动是由拖拽触发的时候,在它将要停止时调用
    public func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
        // fabs 绝对值
        if fabs(scrollView.contentOffset.x - scrollView.bounds.size.width) > scrollView.bounds.size.width / 2 {
            
            scrollDirection = scrollView.contentOffset.x > bounds.size.width ? .Left : .Right
            // 重新加载图片
            loadImages()
        }
        

    }
加载图片的部分, 里面涉及到了一点小的数学计算(希望读者自己理解下)

    private func loadImages() {
        
         // 根据滚动方向不同设置将要显示的图片下标
        switch scrollDirection {
            
            case .Left:
                currentIndex = (currentIndex + 1) % imagesCount

            case .Right:
                currentIndex = (currentIndex - 1 + imagesCount) % imagesCount
            
        }
        
        leftIndex = (currentIndex - 1 + imagesCount) % imagesCount
        rightIndex = (currentIndex + 1) % imagesCount
        
// 使用closure将imageVIew"传递"给外部的调用者来加载图片, 这样就达到了在使用的时候可以以任何方式来加载图片了
        setupImageForImageView?(imageView: currentImageView, index: currentIndex)
        setupImageForImageView?(imageView: rightImageView, index: rightIndex)
        setupImageForImageView?(imageView: leftImageView, index: leftIndex)
        
        pageControl.currentPage = currentIndex
        if let titles = titlesArray { // 已经添加了textLabel 直接设置文字即可
            textLabel.text = titles[currentIndex]

        }
        
// 始终将currentImageView显示在屏幕上
        scrollView.contentOffset = CGPoint(x: bounds.size.width, y: 0)


    }

实现自动滚动的部分就较简单了, 使用NSTimer, 在倒计时完成的时候的响应方法里面加载图片就ok了, 具体的实现大家阅读源码吧

详细请移步源码, 如果您觉得有帮助,不妨给个star鼓励一下,欢迎关注

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

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,047评论 25 707
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,090评论 4 62
  • 今天6组的小伙伴打卡的时候,我顺便吐槽了一下我今天不知道写什么,小伙伴建议我写随笔。 随笔,并不是像它的名字那样随...
    王小超写写写阅读 837评论 2 0
  • 课程概要 第一期从最基础的了解尤克里里、认识曲谱、指法学习以及音阶学习开始,到能弹奏一些小乐曲,是大家入门学习上手...
    星弦音乐阅读 2,321评论 0 2