見出し画像

SwiftUIでカスタムなSegmentedControlを実装する

SwiftUIでSegmented Controlを使おうとすると、PickerSegmentedPickerStyleを適用すれば一番楽だが、細かくデザイン調整しようとすると現状UISegmentedControl.appearance()を指定するしかなく、調整できる要素も少ないのが難点。そこで自前でカスタムなSegmented Controlを実装してみた。

Pickerで実装する場合

Pickerの場合、selectionに選択中の要素を渡して、pickerStyleにSegmentedPickerStyleを指定するだけでよい。

Picker("SegmentControl", selection: $selectedType) {
    ForEach(SegmentType.allCases) { segment in
        Text(segment.title)
    }
}
.pickerStyle(.segmented)

しかし、フォントサイズやフォントカラー、選択中のセグメントのカラー、余白などは現状モディファイアで細かく指定することはできない。UISegmentedControl.appearance()で一部を指定することはできるが、他の利用箇所にも影響が出てしまう。

init() {
    let appearance = UISegmentedControl.appearance()
    let font = UIFont.boldSystemFont(ofSize: 12)

    // 選択時の背景色
    appearance.selectedSegmentTintColor = .black.withAlphaComponent(0.75)

    // 通常時のフォントとフォント色
    appearance.setTitleTextAttributes([.font: font, .foregroundColor: UIColor.black], for: .normal)

    // 選択時のフォントとフォント色
    appearance.setTitleTextAttributes([.font: font, .foregroundColor: UIColor.white], for: .selected)
}

カスタム実装の場合

Segmented Controlをカスタム実装する場合、基本的にHStackでButtonを並べて、それぞれのセグメントで通常時と選択時で重ねるUIを表示・非表示したり、ベースカラーやフォントカラーを切り替えればよい。また、Pickerでは指定できなかったpaddingやcornerRaduis、選択中のセグメントのカラーを別々にするなどのカスタマイズもできるようになる。

サンプルコードではselectedSegmentをwithAnimationでアニメーションさせているが、Pickerのようにスライドアニメーションを実装することもできる。

参考


この記事が気に入ったらサポートをしてみませんか?