LoginSignup
31

More than 5 years have passed since last update.

グリッド形式とリスト形式の表示切り替え

Last updated at Posted at 2016-09-13

はじめに

グリッド形式とリスト形式を切り替える画面は、たまに見ますよね。
今回は、CollectionViewを利用したサンプルをご紹介します。

完成イメージ

output.gif

実装手順

  1. グリッド形式のレイアウトを作成する
  2. リスト形式のレイアウトを作成する
  3. カスタムCollectionViewCellを作成する
  4. レイアウトを作成する
  5. セグメントコントロールで表示形式を切り替える

実装してみます

1. グリッド形式のレイアウトを作成する

2列毎にレイアウトします。

GridFlowLayout.swift
import UIKit

class GridFlowLayout: UICollectionViewFlowLayout {

    let itemHeight: CGFloat = 160

    override var itemSize: CGSize {
        set {
            self.itemSize = CGSizeMake(itemWidth(), itemHeight)
        }
        get {
            return CGSizeMake(itemWidth(), itemHeight)
        }
    }

    override init() {
        super.init()
        setupLayout()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setupLayout()
    }

    func setupLayout() {
        minimumInteritemSpacing = 1
        minimumLineSpacing = 1
        scrollDirection = .Vertical
    }

    func itemWidth() -> CGFloat {
        return (CGRectGetWidth(collectionView!.frame)/2)-1
    }

    override func targetContentOffsetForProposedContentOffset(proposedContentOffset: CGPoint) -> CGPoint {
        return collectionView!.contentOffset
    }
}

2. リスト形式のレイアウトを作成する

グリッド形式のレイアウトとほぼ同じコードで冗長ですが、
1列毎にレイアウトします。

ListFlowLayout.swift
import UIKit

class ListFlowLayout: UICollectionViewFlowLayout {

    var itemHeight: CGFloat = 160

    override var itemSize: CGSize {
        set {
            self.itemSize = CGSizeMake(itemWidth(), itemHeight)
        }
        get {
            return CGSizeMake(itemWidth(), itemHeight)
        }
    }

    override init() {
        super.init()
        setupLayout()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setupLayout()
    }

    func setupLayout() {
        minimumInteritemSpacing = 0
        minimumLineSpacing = 1
        scrollDirection = .Vertical
    }

    func itemWidth() -> CGFloat {
        return CGRectGetWidth(collectionView!.frame)
    }

    override func targetContentOffsetForProposedContentOffset(proposedContentOffset: CGPoint) -> CGPoint {
        return collectionView!.contentOffset
    }
}

3. カスタムCollectionViewCellを作成する

ImageViewがあるだけのセルを作ります。

import UIKit

class ImageCollectionViewCell: UICollectionViewCell {
    @IBOutlet weak var imageView: UIImageView!

    static var identifier: String {
        get {
            return String(self)
        }
    }
}

4. レイアウトを作成する

SegmentedControlとCollectionViewを配置します。

なお、SegmentedControlは、
グリッド形式とリスト形式を切り替えるために利用します。

また、CollectionViewのみを利用し、TableViewは利用しません。

スクリーンショット 2016-09-12 15.27.35.png

5. セグメントコントロールで表示形式を切り替える

5.1. Viewのタイプを定義する

グリッド形式とリスト形式の2パターンを定義します。

ViewController.swift
enum ViewType {
    case grid
    case list
}

5.2. セグメントコントロールのイベントを受けて、レイアウトを切り替える

CollectionViewのsetCollectionViewLayoutメソッドを利用して、
所定のレイアウト(grid or list)に変更します。

アニメーションをつけると、それっぽくなります。

class ViewController: UIViewController {

    @IBOutlet weak var typeSegmentControl: UISegmentedControl!
    @IBOutlet weak var collectionView: UICollectionView!

    let gridFlowLayout = GridFlowLayout()
    let listFlowLayout = ListFlowLayout()

    var fileNames = [String]()

    override func viewDidLoad() {
        super.viewDidLoad()
        setup()
    }

    private func setup() {

        //テストデータ
        for i in 1...10 {
            fileNames.append("\(i)")
        }

        collectionView.collectionViewLayout = gridFlowLayout
    }

    //セグメントコントロールで表示形式を切り替えます
    @IBAction func onDidTappedType(sender: UISegmentedControl) {

        switch sender.selectedSegmentIndex {
        case ViewType.grid.hashValue:
            changeView(gridFlowLayout)
            break

        case ViewType.list.hashValue:
            changeView(listFlowLayout)
            break

        default:
            break
        }
    }

    //Viewを切り替えます
    private func changeView(flowLayout: UICollectionViewFlowLayout) {

        UIView.animateWithDuration(0.2) { [weak self] () -> Void in
            self?.collectionView.collectionViewLayout.invalidateLayout()
            self?.collectionView.setCollectionViewLayout(flowLayout, animated: true)
        }
    }
}

extension ViewController: UICollectionViewDataSource {

    func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return fileNames.count
    }

    func collectionView(collectionView: UICollectionView,
                        cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {

        let cell = collectionView.dequeueReusableCellWithReuseIdentifier(ImageCollectionViewCell.identifier,
                                                                         forIndexPath: indexPath) as! ImageCollectionViewCell

        cell.imageView.image = UIImage(named: "\(fileNames[indexPath.row])"+".jpg")
        return cell
    }
}

まとめ

グリッド形式とリスト形式を切り替えるには、
TableViewとCollectionViewを併用する方法もありますが、
シンプルなレイアウトなら、CollectionViewの列数を調整しても良さそうです。

参考

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
31