マンガアプリなどのトップページでよく見かけるUIです。これをコレクションビューで実装するメモです。
一番上と一番下のカルーセルはグリッド吸着タイプ、真ん中はフリーです。
ビューコントローラ
ViewController
import UIKit
class ViewController: UIViewController {
var carousel1 : UICollectionView!
var carousel2 : UICollectionView!
var carousel3 : UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
// カルーセルの高さ
let carouselHeight:CGFloat = 200
// CollectionViewのレイアウトを生成.
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
// カルーセル1を生成.
carousel1 = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
carousel1.frame = CGRect(x:0, y:32, width:view.frame.size.width, height:carouselHeight)
carousel1.register(MyCollectionViewCell.self, forCellWithReuseIdentifier: "MyCell")
carousel1.backgroundColor = .clear
carousel1.delegate = self
carousel1.dataSource = self
carousel1.isPagingEnabled = true // セルが吸着する
carousel1.showsHorizontalScrollIndicator = false
carousel1.tag = 0
view.addSubview(carousel1)
// カルーセル2を生成.
carousel2 = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
carousel2.frame = CGRect(x:0, y:carousel1.frame.origin.y + carouselHeight + 10, width:view.frame.size.width, height:carouselHeight)
carousel2.register(MyCollectionViewCell.self, forCellWithReuseIdentifier: "MyCell")
carousel2.backgroundColor = .clear
carousel2.delegate = self
carousel2.dataSource = self
carousel2.isPagingEnabled = false // セルが吸着しない
carousel2.showsHorizontalScrollIndicator = false
carousel2.tag = 1
view.addSubview(carousel2)
// カルーセル3を生成.
carousel3 = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
carousel3.frame = CGRect(x:0, y:carousel2.frame.origin.y + carouselHeight + 10, width:view.frame.size.width, height:carouselHeight)
carousel3.register(MyCollectionViewCell.self, forCellWithReuseIdentifier: "MyCell")
carousel3.backgroundColor = .clear
carousel3.delegate = self
carousel3.dataSource = self
carousel3.isPagingEnabled = true // セルが吸着する
carousel3.showsHorizontalScrollIndicator = false
carousel3.tag = 2
view.addSubview(carousel3)
}
}
extension ViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let pageViewRect = self.view.bounds
return CGSize(width: pageViewRect.width, height: pageViewRect.height-80)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0.0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 0.0
}
}
extension ViewController: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 5
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MyCell", for: indexPath) as! MyCollectionViewCell
switch collectionView.tag
{
case 0:
cell.setViewColor(.cyan)
break
case 1:
cell.setViewColor(.orange)
break
case 2:
cell.setViewColor(.green)
break
default:
break
}
return cell
}
}
extension ViewController: UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
// セルタップ時の挙動
print("僕のタグ番号は\(collectionView.tag)です")
print("Cellインデックスは\(indexPath.row)です")
}
}
コレクションビューを3つ作成しています。コレクションビューのプロパティisPagingEnabled
をtrueにするとグリッド吸着タイプの挙動(ページング)となります。UICollectionViewDelegateFlowLayout
プロトコルにてセルの余白を設定しています。isPagingEnabledの兼ね合いでここでは余白をゼロに設定しています。
データ・ソースや処理の分岐はそれぞれのコレクションビューにタグ番号をセットすることで対応しています。
カスタムセルクラス
MyCollectionViewCell
import UIKit
class MyCollectionViewCell: UICollectionViewCell {
var baseView:UIView?
let paddingSize:CGFloat = 8
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
}
override init(frame: CGRect) {
super.init(frame: frame)
// コンテンツビューに対しパディングをもうけたビューを生成して貼る(ページング吸着対応)
baseView = UIView(frame:CGRect(x:paddingSize,y:paddingSize,width:frame.width-(paddingSize*2),height:frame.height))
self.contentView.addSubview(baseView!)
}
// ベースビューの背景色を変更する
func setViewColor(_ color:UIColor) {
baseView?.backgroundColor = color
}
}
横幅いっぱいのコンテンツビューにひとまわり小さいビューを貼り付けることで余白があるように見せています。こうすることでisPagingEnabled
がtrue時にもきれいにページングしてくれます。