Edited at

[iOS] マテリアルデザインのタブ風UI


はじめに

今更ですが、マテリアルデザインのタブ風の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)
}