Yo,Come on ~ DJ ~Drop the beat,yoyo 我们公司小,开发人又少,iOS APP要赶早。临危受命我可以,安卓工程师跑不了,佛教临时抱也有点难,赶鸭子上架所谓敏捷免不了,要 告诉我自己CV战士不能做一辈子,还是励志慢慢要变屌,及时记录,学习刻苦,这样就好!
我有freeStyle,好吧~最近《中国有嘻哈》看多了。
言归正传,要实现一个轮播图,开始一点想法都没有,本想找个第三方框架,调下API就好了,可是网上搜了几篇文章发现也没没有太难,自己写一个能用的似乎也行吧。
1.基本和思路框架和文章一样一样的:就是要呈现几张图,就把几张图的宽度总和计算出,把这个和设置给ScrollView的contentSize。
class MyBannerView :UIScrollView ,UIScrollViewDelegate{
var imageCount:Int = 0 //图片总数
var pageIndicator:UIPageControl? //指示器引用
var currentPage = 0 //当前页面索引
//调用该方法,传入图片
func prepareMyBannerView(imageStrArraysNames imageName:[String]) {
imageCount = imageName.count
//遍历image集合,构造布局
for i in 0...(imageName.count - 1) {
//建造 UIImageView
let imageView = UIImageView(frame: CGRect(x:CGFloat(i) * self.bounds.width,y:0,width:self.bounds.width, height:self.bounds.height) )
/* //以后用
//添加点击监听 UITapGestureRecognizer
imageView.isUserInteractionEnabled = true //可交互开关打开
let tapRecongnizer = UITapGestureRecognizer(
target:self,action:#selector(clickImage(_:))
)
imageView.addGestureRecognizer(tapRecongnizer)
*/
self.addSubview(imageView)
//设置轮播图图片
imageView.image = UIImage(named: imageName[i])
}
//设置ScrollView的内在容量
self.contentSize = CGSize(width:CGFloat(imageName.count ) * self.bounds.width, height :self.bounds.height)
self.bounces = false //设置吸附属性
self.isPagingEnabled = true //设置书页效果
self.showsHorizontalScrollIndicator = false //不要水平默认指示器
//单独创建第n+1张轮播图,和第一张图片是同一张图
let imageView = UIImageView(frame:CGRect(x:CGFloat(imageName.count) * self.bounds.width,y:0,
width : self.bounds.width,height : self.bounds.height))
/*
imageView.isUserInteractionEnabled = true //可交互开关打开
let tapRecongnizer = UITapGestureRecognizer(
target:self,action:#selector(clickImage(_:))
)
imageView.addGestureRecognizer(tapRecongnizer)
*/
imageView.image = UIImage(named:imageName[0])
self.addSubview(imageView)
}
2.实现UIScrollViewDelegate协议,在重写方法中计算当前页索引和指示器索引
//手动翻页调用
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let cPage = self.contentOffset.x / self.bounds.width
if let indicator = pageIndicator{
indicator.currentPage = Int(cPage)
currentPage = Int(cPage)
}
currentPage %= imageCount
}
//自动播放时,调用该方法
func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
currentPage += 1
if let indicator = pageIndicator{
indicator.currentPage = currentPage % imageCount
}
currentPage %= imageCount
}
/**
和外部的Indicator绑定
*/
func bindPageIndicator(indicatorPageController indicator :UIPageControl ) {
pageIndicator = indicator
pageIndicator?.backgroundColor = UIColor.init(red: 0, green: 0, blue: 0, alpha: 0.25)
pageIndicator?.numberOfPages = imageCount
//设置代理
self.delegate = self
}
3.让他loop起来,定时器
/**
创建轮播图定时器
*/
func bannerLoop() {
let timer = Timer.scheduledTimer(timeInterval: 3, target: self, selector: #selector(self.timerManager), userInfo: nil, repeats: true)
//这句话实现多线程,如果你的ScrollView是作为TableView的headerView的话,在拖动tableView的时候让轮播图仍然能轮播就需要用到这句话
RunLoop.current.add(timer, forMode: RunLoopMode.commonModes)
}
//定时器回调
func timerManager() {
//设置偏移量
self.setContentOffset(CGPoint(x:self.contentOffset.x + self.bounds.width, y:0), animated: true)
//当偏移量达到最后一张的时候,让偏移量置零
if self.contentOffset.x == CGFloat(self.bounds.width) * CGFloat(imageCount) {
self.contentOffset = CGPoint(x:0,y: 0)
}
}
4.每一张图片设置点击事件
//在prepareMyBannerView(imageStrArraysNames:)中
//for循环里面
//添加点击监听 UITapGestureRecognizer
imageView.isUserInteractionEnabled = true //可交互开关打开
let tapRecongnizer = UITapGestureRecognizer(
target:self,action:#selector(clickImage(_:))
)
imageView.addGestureRecognizer(tapRecongnizer)
写一个协议
/**
这个东西是图片点击的接口协议
*/
public protocol MyBannerImageClickedDelegate : NSObjectProtocol {
func imageClicked(clickItem item :Int) -> Void
}
持有协议引用
var myViewClickDelegate :MyBannerImageClickedDelegate? //图片点击代理回调
在图片点击事件方法里面调用协议的方法
//图片的点击监听会调用
func clickImage(_ sender :UITapGestureRecognizer){
//print(#function)
if let clickDelegate = self.myViewClickDelegate{
clickDelegate.imageClicked(clickItem: currentPage)
}
}
5.最后加个小方法:复位
//各种位置归零
func resetBannerPosition(){
//当前页面索引
currentPage = 0
//指示器
pageIndicator?.currentPage = 0
//重置偏移量
self.contentOffset = CGPoint(x:0,y: 0)
}
最后呢,使用这个MyBannerView
/**
使用方法:banner-----------
//如若需要图片点击事件监听,让UIViewController实现MyBannerImageClickedDelegate和它的方法
比如:
//响应轮播banner的item的回调方法
func imageClicked(clickItem item :Int){
print("click is \(item)")
self.performSegue(withIdentifier: "showNews", sender: self)
}
//在viewdidload()里面-------------------------
//整一个父UIView作为容器
let cardView = UIView(frame : CGRect(x: 0, y: 0, width: view.bounds.width, height: 200))
//构造Banner 指定大小
let banner = MyBannerView(frame : CGRect(x: 0, y: 0, width: view.bounds.width, height: 200))
//设置轮播图片
banner.prepareMyBannerView(imageStrArraysNames: ["img_banner_1","img_banner_2","img_banner_3"])
//构造指示器,指定指示器大小
let indicator = UIPageControl(frame: CGRect(x: view.bounds.width/2 - 50, y: 160, width: 100, height: 30))
//绑定指示器
banner.bindPageIndicator(indicatorPageController: indicator)
//轮播图循环起来
banner.bannerLoop()
//设置一个点击事件的监听吧
banner.myViewClickDelegate = self
//把指示器和banner添加到父布局里面
cardView.addSubview(banner)
cardView.addSubview(indicator)
view.addSubview(cardView)
//在viewWillAppear()中-------------------------
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
//页面出现之前,重置banner位置
banner?.resetBannerPosition()
}
*/
这真是一个简单的实现!这篇文章的思路看上去更好: