前言:最近写了电商项目,公司以前没有 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 文件就是了,不喜勿喷。