最近開始學(xué)習(xí)Swift殴边,想將公司從OC轉(zhuǎn)移到這上面來(lái)靖榕,畢竟Swift發(fā)展勢(shì)頭迅猛欧聘。于是想將公司原有經(jīng)常用的UI及工具控件重新寫一遍根吁,有利于自己對(duì)Swift的了解员淫!
效果圖如下
使用代碼
let imgArray = [
"http://www.netbian.com/d/file/20150519/f2897426d8747f2704f3d1e4c2e33fc2.jpg",
"http://www.netbian.com/d/file/20130502/701d50ab1c8ca5b5a7515b0098b7c3f3.jpg",
NSURL(string: "http://www.netbian.com/d/file/20110418/48d30d13ae088fd80fde8b4f6f4e73f9.jpg")!,
UIImage(named: "carouse_1")!,
UIImage(named: "carouse_2")!,
UIImage(named: "carouse_3")!
]
self.silenceCarouselView = SilenceCarouselView(
frame: CGRectMake(0, 0, UIScreen.mainScreen().bounds.size.width, 200),
imageArray: imgArray,
silenceCarouselViewTapBlock: { (carouselView, index) in
print(index)
});
結(jié)構(gòu)
此輪播效果實(shí)現(xiàn)的結(jié)構(gòu)如下:
UIView兩個(gè)子View:UIScrollView、UIPageControl
UIScrollView兩個(gè)子UIImageView
原理
UIScrollView的寬度:width
UIScrollView的高度:height
兩個(gè)UIImageView: currentImgView击敌、otherImgView介返,并且他們的寬高與UIScrollView的寬高相等
UIScrollview:
// 設(shè)置內(nèi)容寬度為3倍的尺寸
self.scrollView?.contentSize = CGSizeMake(self.bounds.size.width * 3, self.bounds.size.height)
兩個(gè)UIImageView的位置:
// 設(shè)置顯示的位置
self.scrollView?.contentOffset = CGPointMake(self.bounds.size.width, 0)
左右滑動(dòng)時(shí)改變otherImgView的frame屬性讓其分別移至currentImgView的左或右兩端,并設(shè)置圖片,滑動(dòng)結(jié)束后交換兩張圖片的內(nèi)容并設(shè)置重置UIScrollview的滾動(dòng)位置
/**
定義手指滑動(dòng)方向枚舉
- DirecNone: 沒(méi)有動(dòng)
- DirecLeft: 向左
- DirecRight: 向右
*/
enum CarouselViewDirec {
case DirecNone
case DirecLeft
case DirecRight
}
// 監(jiān)聽scrollView滾動(dòng)事件
public func scrollViewDidScroll(scrollView: UIScrollView) {
// 設(shè)置手指滑動(dòng)方向
self.currentDirec = scrollView.contentOffset.x > scrollView.bounds.size.width ? .DirecLeft : .DirecRight;
// 向右滑
if self.currentDirec == .DirecRight {
// 將其他圖片顯示到左邊
self.otherImgView!.frame = CGRectMake(0, 0, scrollView.bounds.size.width, scrollView.bounds.size.height);
// 下一索引-1
self.nextIndex = self.currIndex - 1
// 當(dāng)索引 < 0 時(shí), 顯示最后一張圖片
if self.nextIndex < 0 {
self.nextIndex = self.imageArray!.count - 1
}
}
// 向左滑動(dòng)
else if self.currentDirec == .DirecLeft {
// 將其他圖片顯示到右邊
self.otherImgView!.frame = CGRectMake(CGRectGetMaxX(self.currentImgView!.frame), 0, scrollView.bounds.size.width, scrollView.bounds.size.height);
// 設(shè)置下一索引
self.nextIndex = (self.currIndex + 1) % self.imageArray!.count
}
// 去加載圖片
self.loadImg(self.otherImgView!, index: self.nextIndex)
}
/**
設(shè)置整個(gè)輪播圖片的顯示邏輯
*/
private func reloadImg() -> (){
self.currentDirec = .DirecNone;//清空滾動(dòng)方向
//判斷最終是滾到了右邊還是左邊
let index = self.scrollView!.contentOffset.x / self.scrollView!.bounds.size.width;
//等于1表示最后沒(méi)有滾動(dòng),返回不做任何操作
if index == 1 {return}
//當(dāng)前圖片索引改變
self.currIndex = self.nextIndex;
self.pageControl!.currentPage = self.currIndex
// 將當(dāng)前圖片的位置放到中間
self.currentImgView!.frame = CGRectMake(self.scrollView!.bounds.size.width, 0, self.scrollView!.bounds.size.width, self.scrollView!.bounds.size.height)
// 將其他圖片對(duì)象的圖片給當(dāng)前顯示的圖片
self.currentImgView!.image = self.otherImgView!.image
// 設(shè)置視圖滾到中間位置
self.scrollView!.contentOffset = CGPointMake(self.scrollView!.bounds.size.width, 0)
}
/**
加載圖片
- parameter imgView: 需要加載圖片的 UIImageView
- parameter index: 加載圖片的索引
*/
private func loadImg(imgView:UIImageView,index:Int){
let imgData = self.imageArray![index]
// 如果是字符串類型沃斤,就去拼接URL
if imgData is String {
// MARK: - 此處可以換成別的網(wǎng)絡(luò)圖片加載邏輯
imgView.kf_setImageWithURL(NSURL(string: imgData as! String)!, placeholderImage: nil)
}
// 如果是NSURL類型則直接去加載
else if imgData is NSURL {
// MARK: - 此處可以換成別的網(wǎng)絡(luò)圖片加載邏輯
imgView.kf_setImageWithURL(imgData as! NSURL, placeholderImage: nil)
}
// 圖片類型
else if imgData is UIImage {
imgView.image = imgData as? UIImage
}
// 其他未找到為空
else{
imgView.image = nil
}
}
至此已經(jīng)實(shí)現(xiàn)圖片無(wú)限滾動(dòng)圣蝎,接下來(lái)實(shí)現(xiàn)自動(dòng)輪播
/**
初始化計(jì)時(shí)器
*/
private func initTimer() -> (){
//如果只有一張圖片,則直接返回衡瓶,不開啟定時(shí)器
if self.imageArray!.count <= 1 {
return
}
//如果定時(shí)器已開啟捅彻,先停止再重新開啟
if timer != nil {
timer?.invalidate()
}
timer = NSTimer.scheduledTimerWithTimeInterval(self.time, target: self, selector: #selector(SilenceCarouselView.timerFunction), userInfo: nil, repeats: true)
// timer?.fire()
NSRunLoop.currentRunLoop().addTimer(self.timer!, forMode: NSDefaultRunLoopMode)
}
/**
定時(shí)調(diào)用的方法
*/
func timerFunction() -> (){
//動(dòng)畫改變scrollview的偏移量就可以實(shí)現(xiàn)自動(dòng)滾動(dòng)
self.scrollView?.setContentOffset(CGPointMake(self.scrollView!.bounds.size.width * 2, 0), animated: true)
}
//MARK: - UIScrollView代理方法
public func scrollViewWillBeginDragging(scrollView: UIScrollView) {
// 開始拖動(dòng)時(shí)停止自動(dòng)輪播
self.timer?.invalidate()
}
public func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) {
// 結(jié)束拖動(dòng)時(shí)開啟自動(dòng)輪播
self.initTimer()
}
public func scrollViewDidEndScrollingAnimation(scrollView: UIScrollView) {
// 帶動(dòng)畫的設(shè)置scrollview位置后會(huì)調(diào)用此方法
self.reloadImg() // 設(shè)置圖片
}
public func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
// 結(jié)束滾動(dòng)時(shí)重置方向
self.currentDirec = .DirecNone
// 設(shè)置圖片
self.reloadImg()
}
以上就是大概的原理邏輯代碼,如需要源碼請(qǐng)查看Demo-github
我只想實(shí)現(xiàn)最簡(jiǎn)單的功能鞍陨,因?yàn)檫@樣方便日后的擴(kuò)展修改,當(dāng)封裝的東西越多,你想改的難度和時(shí)間成本就越高诚撵,所有我就從簡(jiǎn)了缭裆! (如果你想實(shí)現(xiàn)更多的功能,把代碼拿走寿烟,你的代碼你做主3和铡)
1、參考資料:高效圖片輪播筛武,兩個(gè)ImageView實(shí)現(xiàn)(來(lái)自:推酷)
2缝其、輪播控件中用到的第三方框架:onevcat 的 Kingfisher 網(wǎng)路圖片加載框架