はじめに
今更ですが、マテリアルデザインのタブ風のUIサンプルを作成しました。
完成イメージは、下記のとおりです。
UIの構造
UIの構造は、下記の3階層です。
ここまでは、通常のCollectionViewの作り方と同様です。
MenuView (UIView)
- CollectionView
-- MenuCell (UICollectionViewCell)
ポイント
ポイントは、選択中のタブインジケータです。
NSLayoutAnchorを使うと、よい感じになりました。
なお、下記のサンプルは、タブを4個表示する場合の例です。
MenuBar.swift
var horizontalBarLeftAnchorConstranit: NSLayoutConstraint?
/// 選択中のインジケータを更新する
func collectionView(_ collectionView: UICollectionView,
didSelectItemAt indexPath: IndexPath) {
let x = CGFloat(indexPath.item) * frame.width / 4
horizontalBarLeftAnchorConstranit?.constant = x
}
/// 選択中のインジケータを設定する
private func setupHorizontalBar() {
let horizontalBarView = UIView()
horizontalBarView.backgroundColor = .white //インジケータの色
horizontalBarView.translatesAutoresizingMaskIntoConstraints = false
addSubview(horizontalBarView)
horizontalBarLeftAnchorConstranit = horizontalBarView.leftAnchor.constraint(equalTo: self.leftAnchor)
horizontalBarLeftAnchorConstranit?.isActive = true
horizontalBarView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
horizontalBarView.widthAnchor.constraint(equalTo: self.widthAnchor, multiplier: 1/4).isActive = true
//インジケータの高さ
horizontalBarView.heightAnchor.constraint(equalToConstant: 4).isActive = true
}
おまけ
選択中のタブインジケータにアニメーションをつけると、よりクールになります。
MenuBar.swift
func collectionView(_ collectionView: UICollectionView,
didSelectItemAt indexPath: IndexPath) {
let x = CGFloat(indexPath.item) * frame.width / 4
horizontalBarLeftAnchorConstranit?.constant = x
//アニメーションをつける
UIView.animate(withDuration: 0.75,
delay: 0,
usingSpringWithDamping: 1,
initialSpringVelocity: 1,
options: .curveEaseOut,
animations: {
self.layoutIfNeeded()
}, completion: nil)
}