この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
こんにちは!
モバイルアプリサービス部の田中孝明です。
今回はリスト表示→グリッド表示の切り替えをアニメーション付きで行うTIPSをサンプルプログラム付きで書き記します。
商品一覧を閲覧する機能を作る際、商品の写真を強調して見せたいモードと商品名とサマリーを見せたいモードの切り替えを行いたいとの要望がありました。
その際の実装例として考案したものをまとめてみました。
サンプルプログラム
以下に公開しています。
実装例
便宜上、商品の写真だけ見せたいモードをグリッド表示、商品名とサマリーを見せたいモードをリスト表示と呼称します。
上記のモードをアニメーション付きで切り替えるためにはUICollectionViewを利用します。
UICollectionViewのUICollectionViewFlowLayoutを表示したいモードに合わせて切り替えることで、UITableViewのようにも利用することができます。
下記はリスト表示のUICollectionViewFlowLayoutです。
こうすると、UITableViewのような見た目にすることができます。
let layout = UICollectionViewFlowLayout()
layout.itemSize = CGSize(width: rect.size.width, height: 60)
layout.minimumLineSpacing = 0
layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
return layout
下記はグリッド表示のUICollectionViewFlowLayoutです。
let layout = UICollectionViewFlowLayout()
layout.itemSize = CGSize(width: (rect.size.width - 30) / 2, height: (rect.size.width - 30) / 2)
layout.minimumLineSpacing = 5
layout.minimumInteritemSpacing = 0
layout.sectionInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
return layout
あとはUICollectionViewCellを定義します。
ポイントとしてはリスト表示、グリッド表示共に同じUICollectionViewCellを利用します。
Autolayoutの制約(NSLayoutConstraint)をIBOutletで紐付けておくことで、表示変更時に制約を変更できるようにしておきます。
class ToggleCollectionCell: UICollectionViewCell {
private var savedItem: Item?
@IBOutlet weak var idLabel: UILabel!
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var thumbnailImageView: UIImageView!
@IBOutlet weak var bottomView: UIView!
@IBOutlet weak var nameLabelCenterXLayoutConstraint: NSLayoutConstraint!
@IBOutlet weak var nameLabelCenterYLayoutConstraint: NSLayoutConstraint!
func configureWithItem(item: Item, cellType: CellType) {
savedItem = item
updateConstraintsWithCellType(cellType)
}
func updateConstraintsWithCellType(cellType: CellType) {
if let item = savedItem {
idLabel?.text = item.id
nameLabel?.text = item.name
}
switch cellType {
case .List:
backgroundColor = UIColor.whiteColor()
idLabel.textColor = UIColor.redColor()
nameLabel.textColor = UIColor.blackColor()
nameLabelCenterXLayoutConstraint?.constant = -100
nameLabelCenterYLayoutConstraint?.constant = 0
bottomView.hidden = false
case .Grid:
backgroundColor = UIColor.darkGrayColor()
idLabel.textColor = UIColor.blueColor()
nameLabel.textColor = UIColor.brownColor()
nameLabelCenterXLayoutConstraint?.constant = 0
nameLabelCenterYLayoutConstraint?.constant = 50
bottomView.hidden = true
}
}
}
各表示のレイアウトによってはかなりコードが煩雑になるかもですが。。。
あとは上記の設定を表示モード切り替え処理でUIViewのanimateWithDurationを利用すればAutolayoutの制約に従ってUICollectionViewCellがアニメーションしながら表示が切り替わります。
@IBAction func didTapToggleButtonItem(sender: AnyObject) {
switch cellType {
case .List:
cellType = .Grid
case .Grid:
cellType = .List
}
UIView.animateWithDuration(0.5, animations: { [weak self] in
guard let `self` = self else { return }
self.collectionView?.collectionViewLayout = self.cellType.layoutFromSuperviewRect(self.collectionView!.frame)
self.collectionView?.visibleCells().forEach { cell in
guard let _cell = cell as? ToggleCollectionCell else { return }
_cell.updateConstraintsWithCellType(self.cellType)
}
}, completion: { [weak self] _ in
guard let `self` = self else { return }
self.toggleButtonItem.title = self.cellType.toggleButtonItemTitle
})
}
最後に
今回のネタに関しては利用シーンが限定されているとは思います。
AutolayoutとUIViewのanimateWithDurationの組み合わせを使えばある程度のアニメーションを作成することが可能であることが今回のTIPSになります。