import Foundation
protocol EHWelcomeScrollViewDelegate: class {
/// 點擊第幾個
func scrollView(_ scrollView:EHWelcomeScrollView,didSelectIndex:Int)
/// 顯示下一個
func displayNext(_scrollView:EHWelcomeScrollView)
}
class EHWelcomeScrollView : UIView {
// MARK: - 公有屬性
/// 內容視圖
var arrImages:[UIImage]
/// 是否豎屏顯示scrollview,默認是no
var isScrollDirectionPortrait:Bool = false
/// pageControl
lazy var pageControl:UIPageControl = {
let pageControl = UIPageControl()
return pageControl
}()
/// 隱藏pageControl
var hidePageControl:Bool = false {
didSet{
self.pageControl.isHidden = hidePageControl
}
}
/// 定時器時間間距
var timerInterval:Int = 3
/// 是否可以手動滑動
var scrollEnabled:Bool = false
/// 代理
weak var delegate:EHWelcomeScrollViewDelegate?
// MARK: - 私用屬性
/// 無限滾動圖片數量
fileprivate let ImageViewCount:Int = 3
/// 滾動視圖
fileprivate lazy var scrollView: UIScrollView = {
let scrollView = UIScrollView()
scrollView.showsHorizontalScrollIndicator = false
scrollView.showsVerticalScrollIndicator = false
scrollView.isPagingEnabled = true
scrollView.bounces = false
scrollView.delegate = self
return scrollView
}()
fileprivate var timer:Timer?
fileprivate lazy var isFirstLoad: Bool = false
init(images:[UIImage]){
self.arrImages = images
super.init(frame: .zero)
_setupUI()
_layoutUI()
_bind()
// 設置頁碼
self.pageControl.numberOfPages = arrImages.count;
self.pageControl.currentPage = 0;
// 設置內容
displayImage()
// 開始定時器
startTimer()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
addTap()
scrollView.isScrollEnabled = scrollEnabled
if isScrollDirectionPortrait { //豎向滾動
self.scrollView.contentSize = CGSize(width: 0, height: CGFloat(ImageViewCount) * self.bounds.size.height)
}else{
self.scrollView.contentSize = CGSize(width: CGFloat(ImageViewCount) * self.bounds.size.height, height:0 )
}
for i in 0..<ImageViewCount {
if i < self.scrollView.subviews.count {
let v = self.scrollView.subviews[i]
if (self.isScrollDirectionPortrait) {//豎向滾動時imageview的frame
v.frame = CGRect(x: 0, y: CGFloat(i) * self.scrollView.frame.size.height, width: self.scrollView.frame.size.width, height: self.scrollView.frame.size.height)
} else {//橫向滾動時imageview的frame
v.frame = CGRect(x: CGFloat(i) * self.scrollView.frame.size.width, y: 0, width: self.scrollView.frame.size.width, height: self.scrollView.frame.size.height)
}
}
}
}
fileprivate func addTap(){
let tap = UITapGestureRecognizer(target: self, action: #selector(tapCallback))
tap.cancelsTouchesInView = false
self.addGestureRecognizer(tap)
}
deinit {
#if DEBUG
print("EHInfiniteRollScrollView is deinit ")
#endif
}
}
// MARK: - Private
extension EHWelcomeScrollView {
fileprivate func _setupUI(){
// 滾動視圖
self.addSubview(scrollView)
// 控件
for _ in 0..<ImageViewCount {
let v = UIImageView()
scrollView.addSubview(v)
}
// 頁碼視圖
self.addSubview(pageControl)
}
fileprivate func _layoutUI(){
scrollView.snp.makeConstraints { (make) in
make.edges.equalToSuperview()
}
pageControl.snp_makeConstraints { (make) in
make.centerX.equalTo(self)
make.width.equalTo(80)
make.height.equalTo(20)
//kun調試
make.bottom.equalTo(-EHScale_Value(110))
}
}
fileprivate func _bind(){
}
}
// MARK: - Public
extension EHWelcomeScrollView {
/// 停止定時器
func stopTimer(){
if self.timer != nil {
self.timer!.invalidate()
//需要手動設置timer爲nil,因爲定時器被系統強引用了,必須手動釋放
self.timer = nil
}
}
///啓動定時器
func startTimer(){
if arrImages.count > 1 {
stopTimer()
self.timer?.invalidate()
self.timer = nil
let timer = Timer(timeInterval: TimeInterval(self.timerInterval), target: self, selector: #selector(displayNextImage), userInfo: nil, repeats: true)
RunLoop.main.add(timer, forMode: .commonModes)
self.timer = timer
}else{
stopTimer()
}
}
}
// MARK: - Action
extension EHWelcomeScrollView {
@objc fileprivate func tapCallback(){
self.delegate?.scrollView(self, didSelectIndex: self.pageControl.currentPage)
}
}
// MARK: - Action
extension EHWelcomeScrollView :UIScrollViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
// 當兩張圖片同時顯示在屏幕中,找出佔屏幕比例超過一半的那張圖片
var page:Int = 0
var minDistance:CGFloat = CGFloat(MAXFLOAT)
for i in 0..<self.scrollView.subviews.count {
let v = self.scrollView.subviews[i]
var distance:CGFloat = 0
if (self.isScrollDirectionPortrait) {
distance = fabs(v.frame.origin.y - scrollView.contentOffset.y)
} else {
distance = fabs(v.frame.origin.x - scrollView.contentOffset.x)
}
if (distance < minDistance) {
minDistance = distance
page = v.tag
}
}
self.pageControl.currentPage = page
}
//用手開始拖拽的時候,就停止定時器,不然用戶拖拽的時候,也會出現換頁的情況
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
stopTimer()
}
//用戶停止拖拽的時候,就啓動定時器
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
startTimer()
}
//手指拖動scroll停止的時候,顯示下一張圖片
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
displayImage()
}
//定時器滾動scrollview停止的時候,顯示下一張圖片
func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
displayImage()
}
@objc func displayImage(){
// 設置圖片,三個控件無限顯示
for i in 0..<ImageViewCount {
if i < self.scrollView.subviews.count {
let imgv = self.scrollView.subviews[i] as! UIImageView
imgv.alpha = 1
var index = self.pageControl.currentPage
/**
* 滾到第一張,並且是程序剛啓動是第一次加載圖片,index才減一。
加上這個判斷條件,是爲了防止當程序第一次加載圖片時,此時第一張圖片的i=0,那麼此時index--導致index<0,進入下面index<0的判斷條件,讓第一個imageview顯示的是最後一張圖片
*/
if i == 0 ,self.isFirstLoad == true {
index -= 1
}else if i == 2 {//滾到最後一張圖片,index加1
index += 1
}
if index < 0 {//如果滾到第一張還繼續向前滾,那麼就顯示最後一張
index = self.pageControl.numberOfPages-1
}else if index >= self.pageControl.numberOfPages {//滾動到最後一張的時候,由於index加了一,導致index大於總的圖片個數,此時把index重置爲0,所以此時滾動到最後再繼續向後滾動就顯示第一張圖片了
index = 0
}
imgv.tag = index
if index < arrImages.count{
let image = arrImages[index]
imgv.image = image
}
}
}
self.isFirstLoad = true
// 偏移一個scrollview的高度或者寬度,讓scrollview顯示中間的imageview
if self.isScrollDirectionPortrait {
self.scrollView.contentOffset = CGPoint(x: 0, y: self.scrollView.frame.size.height)
} else {
self.scrollView.contentOffset = CGPoint(x: self.scrollView.frame.size.width, y: 0)
}
}
@objc func displayNextImage(){
self.delegate?.displayNext(_scrollView: self)
//過渡動畫
UIView.animate(withDuration: 0.5, animations: {
if self.scrollView.subviews.count > 1 {
let v = self.scrollView.subviews[1]
v.alpha = 0
if self.isScrollDirectionPortrait {
self.scrollView.contentOffset = CGPoint(x: 0, y: 2 * self.scrollView.frame.size.height)
} else {
self.scrollView.contentOffset = CGPoint(x: 2 * self.scrollView.frame.size.width, y: 2 * 0)
}
}
}) { (finished) in
if finished {
self.displayImage()
}
}
}
}
iOS-Swift無限輪播圖
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.