Swift 3.0 实现图片轮播器

Swift 3.0 实现图片轮播器

一般手机App中都有轮播图的功能,最近学习Swift,就用Swift重新写了图片轮播器。
图片轮播器的实现方法一般分为两种:一种是用三张图片,通过改变显示的数据源来达到轮播的效果;另一种是通过在数据源的起始和结束位置分别插入数据源的最后一个元素和第一个元素,通过多增加的数据来达到轮播效果。第二种方法,本人认为太浪费性能,虽然也能实现轮播的效果,但是不建议使用,今天主要介绍第一种的实现原理和实现效果。
废话不多说,直接上代码
**定义PageControl显示样式**
enum UIPageControlShowStyle {
case UIPageControlShowStyleNone   // 不显示(默认值)
case UIPageControlShowStyleLeft   // 左侧
case UIPageControlShowStyleCenter // 中间
case UIPageControlShowStyleRight  // 右侧

}
在Swift中回调可以使用代理和闭包两种方法
定义点击回调的代理方法
protocol AdViewDelegate:NSObjectProtocol {
func callBack(_ index:NSInteger)
}
类的主要实现代码
class AdView: UIView,UIScrollViewDelegate {
fileprivate var moveTimer:Timer? // 私有可选型变量定时器
// 懒加载有以下两种写法,如果没有特殊操作,建议使用第一种
fileprivate lazy var adScrollView: UIScrollView = UIScrollView() // 私有懒加载变量滚动视图
fileprivate lazy var pageControl: UIPageControl = { // 私有懒加载变量pageControl
let page = UIPageControl()
return page
}()
var dataArray:[String]? { // 数据源数组(一般传模型对象数组)
didSet{ // 设置完成后调用
if dataArray != nil && (dataArray?.count)!>1 {
adScrollView.isScrollEnabled = true
leftImageIndex = dataArray!.count-1
centerImageIndex = 0
rightImageIndex = 1
leftImageView?.image = UIImage(named:dataArray![leftImageIndex])
centerImageView?.image = UIImage(named: dataArray![centerImageIndex])
rightImageView?.image = UIImage(named: dataArray![rightImageIndex])
startTime()
pageControl.numberOfPages = dataArray!.count
if pageControlShowStyle == .UIPageControlShowStyleNone {
pageControl.isHidden = true
return
}
var pageX:CGFloat = 0
switch pageControlShowStyle {
case .UIPageControlShowStyleLeft:
pageX = 10
case .UIPageControlShowStyleCenter:
pageX = (frame.size.width-CGFloat(20*dataArray!.count))/2
case .UIPageControlShowStyleRight:
pageX = frame.size.width - CGFloat(10)
default:
break
}
pageControl.frame = CGRect(x: pageX, y: frame.size.height-CGFloat(35), width: CGFloat(20*dataArray!.count), height: 20)
pageControl.isHidden = false
}
else{
adScrollView.isScrollEnabled = false
if dataArray?.count == 1 {
centerImageIndex = 0
centerImageView?.image = UIImage(named: dataArray![centerImageIndex])
}
}
}
}
var pageControlShowStyle:UIPageControlShowStyle = .UIPageControlShowStyleNone // 默认值
var adTitleStyle:AdTitleShowStyle = .AdTitleShowStyleNone // 默认值
var placeHoldImage:UIImage? { // 可选型变量默认图片
didSet{
if placeHoldImage != nil {
centerImageView?.image = placeHoldImage
adScrollView.isScrollEnabled = false
}
}
}
var adMoveTime:CGFloat = 3 // 广告轮播时间
var callBack:((_ index: NSInteger) -> ())? // 点击回调,参数是点击的索引值
weak var delegate:AdViewDelegate? // 广告点击的代理
fileprivate var leftImageView:UIImageView? // 私有型变量左侧图片
fileprivate var centerImageView:UIImageView? // 私有型变量中间图片
fileprivate var rightImageView:UIImageView? // 私有型变量右侧图片
fileprivate var leftImageIndex:NSInteger = 0 // 私有型变量左侧图片索引
fileprivate var centerImageIndex:NSInteger = 0 // 私有型变量当前图片索引
fileprivate var rightImageIndex:NSInteger = 0 // 私有型变量右侧图片索引
override init(frame: CGRect) {
super.init(frame: frame)
let w = frame.size.width
let h = frame.size.height
adScrollView.frame = frame
adScrollView.bounces = false
adScrollView.showsHorizontalScrollIndicator = false
adScrollView.showsVerticalScrollIndicator = false
adScrollView.isPagingEnabled = true
adScrollView.contentOffset = CGPoint(x: w, y: 0)
adScrollView.contentSize = CGSize(width: w*3, height: h)
adScrollView.delegate = self
addSubview(adScrollView)
leftImageView = UIImageView(frame: frame)
adScrollView.addSubview(leftImageView!)
centerImageView = UIImageView(frame: CGRect(x: w, y: 0, width: w, height: h))
centerImageView?.isUserInteractionEnabled = true
centerImageView?.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(tapClick)))
adScrollView.addSubview(centerImageView!)
rightImageView = UIImageView(frame: CGRect(x: w*2, y: 0, width: w, height: h))
adScrollView.addSubview(rightImageView!)
addSubview(pageControl)
}
required init?(coder aDecoder: NSCoder) {
fatalError(“init(coder:) has not been implemented”)
}
@objc func tapClick(){
callBack?(centerImageIndex)
delegate?.callBack(centerImageIndex)
}
}

// MARK: - 开启/暂停/重新开始/停止定时器
extension AdView{
func startTime()
{
if moveTimer != nil
{
stopTime()
}
else
{
moveTimer = Timer.scheduledTimer(timeInterval: TimeInterval(adMoveTime), target: self, selector: #selector(startLoopScroll), userInfo: nil, repeats: true)
}
}
func pauseTime() {
moveTimer?.fireDate = Date.distantFuture
}
func replayTime() {
moveTimer?.fireDate = Date(timeIntervalSinceNow: TimeInterval(adMoveTime))
}
func stopTime()
{
if moveTimer != nil
{
moveTimer?.invalidate()
moveTimer = nil
}
}
}
// MARK: - 开始循环滚动
extension AdView{
@objc func startLoopScroll() {
adScrollView.setContentOffset(CGPoint(x: frame.size.width*2, y: 0), animated: true)
perform(#selector(scrollViewDidEndDecelerating), with: self, afterDelay: 0.4)
}
}
// MARK: - scrollView的代理方法
extension AdView{
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
pauseTime()
}
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
replayTime()
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
if adScrollView.contentOffset.x == 0 {
centerImageIndex = centerImageIndex-1
leftImageIndex = leftImageIndex-1
rightImageIndex = rightImageIndex-1
if leftImageIndex == -1 {
leftImageIndex = dataArray!.count-1
}
if centerImageIndex == -1 {
centerImageIndex = dataArray!.count-1
}
if rightImageIndex == -1 {
rightImageIndex = dataArray!.count-1
}
}
else if adScrollView.contentOffset.x == frame.size.width*2 {
centerImageIndex = centerImageIndex+1
leftImageIndex = leftImageIndex+1
rightImageIndex = rightImageIndex+1
if leftImageIndex == dataArray!.count {
leftImageIndex = 0
}
if centerImageIndex == dataArray!.count {
centerImageIndex = 0
}
if rightImageIndex == dataArray!.count {
rightImageIndex = 0
}
}
else{
return
}
leftImageView?.image = UIImage(named:dataArray![leftImageIndex])
centerImageView?.image = UIImage(named: dataArray![centerImageIndex])
rightImageView?.image = UIImage(named: dataArray![rightImageIndex])
pageControl.currentPage = centerImageIndex
adScrollView.setContentOffset(CGPoint(x: frame.size.width, y: 0), animated: false)
}
}
主要实现思路就是:新建一个可以可以容纳三个控件宽度的ScrollView,设置它们默认的X坐标分别为0、一个控件宽度、两个控件宽度,ScrollView默认的偏移量为一个控件宽度。通过定时器让ScrollView以动画的形式从一个控件宽度的偏移量偏移到两个控件宽度的位置同时在延迟0.4秒后执行替换数据和恢复默认位置的操作(也就是把ScrollView的偏移量设置回一个控件的宽度),为下一次动画操作做准备。并且考虑到性能,在ScrollView的开始拖拽方法中暂停定时器,在ScrollView的停止拖拽方法中重新开始定时器。

使用方法如下
import UIKit

class ViewController: UIViewController,AdViewDelegate {

override func viewDidLoad() {
    super.viewDidLoad()

    let ad:AdView = AdView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.width/2))
    ad.backgroundColor = UIColor.green
    ad.placeHoldImage = UIImage(named: "idex_banner")
    ad.pageControlShowStyle = .UIPageControlShowStyleCenter
    view.addSubview(ad)
    // 一般在请求完成之后给数组赋值
    ad.dataArray = ["banner0","banner1","banner3","banner4"]
    ad.callBack = { (index) ->()  in
        print("闭包回调 点击的索引\(index)")
    }
    ad.delegate = self
}
func call(_ index: NSInteger) {
    print("代理回调 点击的索引\(index)")
}

}

大家可以看下在Swift下的语法,包括闭包的回调、定时器的使用等等。语法和OC还是有很大区别的,小弟也是在学习中,希望和大家共勉。

猜你喜欢

转载自blog.csdn.net/miaogehehe/article/details/53160149