LoginSignup
8
12

More than 5 years have passed since last update.

【Swift4】多段カルーセルの実装【iOS】

Posted at

マンガアプリなどのトップページでよく見かけるUIです。これをコレクションビューで実装するメモです。

完成イメージ
bbbb.gif

一番上と一番下のカルーセルはグリッド吸着タイプ、真ん中はフリーです。

ビューコントローラ

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時にもきれいにページングしてくれます。

8
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
12