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

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

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

一. 构思

本次主要实现无限循环滚动, 手动滚动, 显示标题, 响应点击事件, 支持加载网络和本地的图片, 同时这个轮播的一点小小的特点是 : 允许你自己使用第三方的图片加载框架(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.3 在ScrollView上添加三个imageView来显示图片, 原理和上面1.2 有点类似, 每次在滚动完成的时候将中间的那个imageView显示在屏幕上, 滚动过程如下

写一个可以使用kingfisher加载图片的轮播器PPTView_第1张图片

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

2. 实现图片循环滚动

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

3. 响应点击事件 给显示在屏幕上的哪一个imageView添加手势, 通过closures(或代理)响应外部点击

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

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

二 实现部分

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

写一个可以使用kingfisher加载图片的轮播器PPTView_第2张图片

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

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鼓励一下,欢迎关注

你可能感兴趣的:(网络,图片,swift,控件)