轮播图控件

前言:最近写了电商项目,公司以前没有 iOS 开发,一切从零开始,一些常用的组件都没有,只好自己弄一个了。

实现轮播的要点:

网上有很多写无线循环轮播的,具体的原理我就不细细描述的了,只说些注意事项:

1、无线循环
2、自动循环
3、手动切换自动循环,定时器问题
4、添加点击事件
5、图片异步加载和缓存机制问题
6、PageControl 和 ScrollView 的联动

基本原理:

将三个 UIImageView 添加到 ScrollView 上,首先将 ScrollView 上最中间的 UIImageView 显示出来,然后,当我们手动滑动 ScrollView 结束,进行图片的切换和 PageControl 控制。

无线循环

需要在 ScrollView 的代理方法 scrollViewDidEndDecelerating 进行图片切换操作,代码如下:

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        let x = scrollView.contentOffset.x              // 滑动 x 偏移
        // 控制 PageControl 联动
        if x < scrollView.bounds.width {
            self.updateNumberOfPages(false)
        } else if x > scrollView.bounds.width {
            self.updateNumberOfPages(true)
        }
        // 切换图片
        self.updateImage()
        // 重置 ScrollView 的偏移量
        scrollView.setContentOffset(CGPoint(x: scrollView.bounds.width, y: 0.0), animated: false)
    }

更新 ImageView 上图片的代码,我这里考虑了下 传进来图片Url数组为空和只有一个的情况下:

// MARK: - Update Image
    
    private func updateImage() {
        let count = pageControl.numberOfPages
        if count == 0 {
            return
        } else if (count == 1) {
            currentImage.kf.setImage(with: URL(string: images[0]))
        } else {
            let currentIndex = pageControl.currentPage
            if currentIndex == 0 {
                leftImage.kf.setImage(with: URL(string: images[count - 1]))
                rightImage.kf.setImage(with: URL(string: images[currentIndex + 1]))
            } else if currentIndex == count - 1 {
                leftImage.kf.setImage(with: URL(string: images[currentIndex - 1]))
                rightImage.kf.setImage(with: URL(string: images[0]))
            } else {
                leftImage.kf.setImage(with: URL(string: images[currentIndex - 1]))
                rightImage.kf.setImage(with: URL(string: images[currentIndex + 1]))
            }
            currentImage.kf.setImage(with: URL(string: images[currentIndex]))
        }
    }

更新 PageControl 当前页,代码如下:

    // MARK:  - Update PageControl NumberOfPages
    
    private func updateNumberOfPages(_ isAdd: Bool) -> Void {
        if isAdd {
            if pageControl.currentPage == pageControl.numberOfPages - 1 {
                pageControl.currentPage = 0
            } else {
                pageControl.currentPage = pageControl.currentPage + 1
            }
        } else {
            if pageControl.currentPage == 0 {
                pageControl.currentPage = pageControl.numberOfPages - 1
            } else {
                pageControl.currentPage = pageControl.currentPage - 1
            }
        }
        print(pageControl.currentPage)
    }

自动循环

开启定时器实现自动循环,代码如下:

timer = Timer.scheduledTimer(timeInterval: animated, target: self, selector: #selector(timerAction), userInfo: nil, repeats: true);
// 一定要将定时器加入 mainRunLoop 中,否则滑动 ScrollView 会影响定时器。
RunLoop.main.add(timer!, forMode: .commonModes)

@objc private func timerAction() {
        self.updateNumberOfPages(true)
        self.updateImage()
        scroll.setContentOffset(CGPoint(x: scroll.frame.size.width * 2.0, y: 0.0), animated: true)
}

图片异步加载和缓存机制问题

我这使用第三方类库 Kingfisher

currentImage.kf.setImage(with: URL(string: images[currentIndex]))

添加点击事件

这里我是代理进行回调,小伙伴不喜欢可以采用闭包进行回调,我这里不说了。

let tap = UITapGestureRecognizer(target: self, action: #selector(tapClick))
 currentImage.addGestureRecognizer(tap)

@objc func tapClick() {
        delegate?.HCarouselTapClick(pageControl.currentPage)
}

最后,小伙伴不想自己写或者上面没看懂可以下载代码:
HSwift
找到 HCarousel.swfit 文件就是了,不喜勿喷。

你可能感兴趣的:(轮播图控件)