[Auto-Scrolling]自動輪播
Go to see → Manual-scrolling手動滑動輪播效果
介紹
使用元件:collection view, image view, page control
使用函數: scheduledTimer(timeInterval:target:selector:, userInfo: repeats:)
, selectItem(at:animated:scrollPosition:)
輪播效果製作
一、向右輪播到最後一張圖片時,會往左拉,回到第一張。
import UIKit
class ViewController: UIViewController,UICollectionViewDelegate,UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
@IBOutlet weak var bannerCollectionView: UICollectionView!
@IBOutlet weak var pageControl: UIPageControl!
var time:Timer?
//紀錄目前banner播放到第幾個cell
var imageIndex = 0
var banners = ["1","2","3"]
override func viewDidLoad() {
super.viewDidLoad()
bannerCollectionView.delegate = self
bannerCollectionView.dataSource = self
configureCellSize()
//每兩秒輪播下一個圖片
time = Timer.scheduledTimer(timeInterval: 2, target: self, selector: #selector(changeBanner), userInfo: nil, repeats: true)
}
func configureCellSize(){
if let layout = bannerCollectionView.collectionViewLayout as? UICollectionViewFlowLayout{
layout.scrollDirection = .horizontal
}
}
@objc func changeBanner(){
//imageIndex加一轉動圖片到下一張
imageIndex += 1
if imageIndex == banners.count{
imageIndex = 0
}
//用imageIndex去產生一個indexPath
let indexPath = IndexPath(item: imageIndex, section: 0)
//讓collectionView去選indexPath
bannerCollectionView.selectItem(at: indexPath, animated: true, scrollPosition: .centeredHorizontally)
}
//MARK: - Collection view
func numberOfSections(in collectionView: UICollectionView) -> Int {
1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
banners.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "BannerCollectionViewCell", for: indexPath) as! BannerCollectionViewCell
let indexPath = banners[indexPath.item]
cell.bannerImageView.contentMode = .scaleAspectFill
cell.bannerImageView.image = UIImage(named: "\(indexPath)")
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return bannerCollectionView.bounds.size
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
}
二、向右輪播到最後一張圖時,繼續向右播第一張圖
- 先在儲存圖片的banners陣列裡多加最後一筆資料,新增的資料就是陣列裡的第一筆資料。
var banners = ["1","2","3","1"]
2. 用imageIndex
記錄圖片為第幾張,並帶入selectItem
函式,將圖片顯示在cell所屬的位置上。
當跑到最後一張圖時,也就是剛剛自行新增的最後一筆資料,設定imageIndex
為 0,selectItem
動畫效果設為 false,並重新呼叫自己changeBanner()
。
import UIKit
class ViewController: UIViewController,UICollectionViewDelegate,UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
@IBOutlet weak var bannerCollectionView: UICollectionView!
@IBOutlet weak var pageControl: UIPageControl!
var time:Timer?
//紀錄目前banner播放到第幾個cell
var imageIndex = 0
var banners = ["1","2","3","1"]
override func viewDidLoad() {
super.viewDidLoad()
bannerCollectionView.delegate = self
bannerCollectionView.dataSource = self
configureCellSize()
pageControl.numberOfPages = banners.count - 1
pageControl.backgroundStyle = .prominent
//每兩秒輪播下一個圖片
time = Timer.scheduledTimer(timeInterval: 2, target: self, selector: #selector(changeBanner), userInfo: nil, repeats: true)
}
func configureCellSize(){
if let layout = bannerCollectionView.collectionViewLayout as? UICollectionViewFlowLayout{
layout.scrollDirection = .horizontal
}
}
@objc func changeBanner(){
var indexPath:IndexPath
//imageIndex加一轉動圖片到下一張
imageIndex += 1
//在banner陣列裡再加入第一筆圖片名稱,當不是最後一筆資料時
if imageIndex < banners.count{
//用imageIndex去產生一個indexPath
indexPath = IndexPath(item: imageIndex, section: 0)
//讓collectionView去選indexPath
bannerCollectionView.selectItem(at: indexPath, animated: true, scrollPosition: .centeredHorizontally)
pageControl.currentPage = imageIndex
//當imageIndex是banner陣列裡的最後一筆資料時,將page control設為0,是第一張圖也是第一個page control圈圈
if imageIndex == banners.count - 1{
pageControl.currentPage = 0
}
}
else
{
//當banner數量等於banner陣列的最後一筆資料,回到第一筆資料,page control也回到第一個圈
imageIndex = 0
pageControl.currentPage = 0
indexPath = IndexPath(item: imageIndex, section: 0)
//不要動畫先回到第一張圖
bannerCollectionView.selectItem(at: indexPath, animated: false, scrollPosition: .centeredHorizontally)
//再重新輪播
changeBanner()
}
}
//MARK: - Collection view
func numberOfSections(in collectionView: UICollectionView) -> Int {
1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
banners.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "BannerCollectionViewCell", for: indexPath) as! BannerCollectionViewCell
let indexPath = banners[indexPath.item]
cell.bannerImageView.contentMode = .scaleAspectFill
cell.bannerImageView.image = UIImage(named: "\(indexPath)")
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return bannerCollectionView.bounds.size
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
}
Reference
My GitHub
Übung macht den Meister