在做iOS开发中,图片轮播是一个比较频繁的需求了。网上也有很多比较好的实现,有使用2个、3个UIImageView的,也有使用UICollectionView的。这里我要讲的是如何用一个UIImageView实现一个图片轮播控件,当然加载网络图片是必须的。闲话少说,直接进入正题:

构建UI

在轮播控件中只需要一个UIImageView和一个UIPageControl即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
lazy var imageView: UIImageView = {
let imageV = UIImageView()
    imageV.userInteractionEnabled = true
    imageV.translatesAutoresizingMaskIntoConstraints = false
    return imageV
}()
 
lazy var pageControl: UIPageControl = {
let pageC = UIPageControl()
    pageC.currentPage = 0
    pageC.translatesAutoresizingMaskIntoConstraints = false
    return pageC
}()

添加好约束即可。然后需要给图片添加一个左划和右划手势,以及一个点击的手势

1
2
3
4
5
6
7
8
9
10
11
private func addGesture() {
let left = UISwipeGestureRecognizer(target: self, action: #selector(self.swipGesterHandelr(_:)))
    left.direction = .Left
  self.imageView.addGestureRecognizer(left)        
    let right = UISwipeGestureRecognizer(target: self, action: #selector(self.swipGesterHandelr(_:)))
    right.direction = .Right
    self.imageView.addGestureRecognizer(right)
        
    let tap = UITapGestureRecognizer(target: self, action: #selector(self.tapGesterHandelr(_:)))
    self.imageView.addGestureRecognizer(tap)
}

创建并启动定时器

既然是轮播,那么就必须得有一个定时器吧,当你使用定时器的时候,就一定要注意定时器的销毁。当进入界面时就要启动定时器,当离开界面时就要销毁定时器。我以前使用过别人写的轮播控件,当我已经离开界面进入下一个界面时,定时器竟然还在运行,这样是不对的。其实实现起来很简单:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public override func willMoveToWindow(newWindow: UIWindow?) {
super.willMoveToWindow(newWindow)
        
    guard let _ = newWindow else {
        stopTimer()
            return
    }
    refreshTimer()
}

private func stopTimer() {
timer?.invalidate()
   timer = nil
}

private func refreshTimer() {
if timer == nil && autoScrollEnable {
    timer = NSTimer.scheduledTimerWithTimeInterval(timeInterval, target: self, selector: #selector(self.timeAction), userInfo: nil, repeats: true)
    }
}

自动轮播的实现

其实这里才是重点的好吧,一个UIImageView要实现轮播效果是很简单的,只需要使用系统的CATransition就可以了,来,上代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
@objc private func timeAction() {
scrollWithDirection(.Left)
}

private func scrollWithDirection(direction: ScrollDirection) {
switch direction {
case .Left:
index += 1
if index > imageCounts - 1 {
index = 0
}
case .Right:
index -= 1
if index < 0 {
index = imageCounts - 1
}
}

if images.count > 0 {
self.imageView.image = images[index]
}
else {
if let url = NSURL(string: imageURLStringGroup[index]) {
self.imageView.hu_setImageWithURL(url, placeholderImage: placeholderImage)
}
}

addScrollAnimationWithDirection(direction)
}

private func addScrollAnimationWithDirection(direction: ScrollDirection) {
let animation = CATransition()
animation.duration = 0.4
animation.type = kCATransitionPush

switch direction {
case .Left:
animation.subtype = kCATransitionFromRight
case .Right:
animation.subtype = kCATransitionFromLeft
}

self.imageView.layer.addAnimation(animation, forKey:"scroll")
self.pageControl.currentPage = index
}

代码非常简单,所以就不一一解释了。现在我们已经构建好了UI,创建并启动了定时器(而且能成功销毁),并成功添加了手势,这样这个图片轮播控件就可以正常工作了。但是在我们成功给轮播图设置图片后,我们得做些其他的工作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public var images: [UIImage] = [] {
    willSet {
    imageCounts = newValue.count
        imageView.image = newValue.first
        pageControl.numberOfPages = newValue.count
    }
}
    
public var imageURLStringGroup: [String] = [] {
willSet {
    imageCounts = newValue.count
            
        guard let url = NSURL(string: newValue.first!) else {
        return
        }
        imageView .hu_setImageWithURL(url, placeholderImage: placeholderImage)
        pageControl.numberOfPages = newValue.count
}
}

现在就可以使用了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
override func viewDidLoad() {
super.viewDidLoad()
        
    let images = ["a.jpg", "b.jpg","c.jpg","d.jpg",].flatMap {
    return UIImage(named: $0)
    }
        
    let cycleView = HUScrollCycleView(frame: CGRectMake(0, 64, self.view.frame.size.width, 200))
    self.view.addSubview(cycleView)
    cycleView.delegate = self
    cycleView.images = images
    cycleView.currentPageIndicatorTintColor = UIColor.redColor()
//  cycleView.placeholderImage = UIImage(named:"a.jpg")
//  cycleView.imageURLStringGroup = ["http://1.7feel.cc/yungou/statics/uploads/banner/20160715/85964915563838.jpg",
//                                         "http://1.7feel.cc/yungou/statics/uploads/banner/20160715/20274054563730.jpg",
//                                         "http://1.7feel.cc/yungou/statics/uploads/banner/20160715/40912708563719.jpg",
//                                         "http://1.7feel.cc/yungou/statics/uploads/touimg/20160718/img193.jpg"];
    }

最后附上GitHub地址。HUScrollCycle中的网络图片下载并没有使用其他第三方库,这里我使用的是以前用Objective-C写的HUWebImageDownloader,它在我维护的一个图片浏览器第三方库HUPhotoBrowser中使用的,它支持网络图片和本地相册图片的浏览和多选,有兴趣的童鞋可以点这里
所以你完全可以放心使用HUScrollCycle而不用担心对你项目产生影响。你只要按照上面的链接中的方法正确的导入HUScrollCycle-Bridging-Header.h就可以正常使用了。