この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
SwiftUIでSegmented Control的なものを使いたいと思い、調べた記録をまとめています。
環境
- Xcode 13.2.1
作ったもの
Pickerを使う
SwiftUIでSegemented Control的なものを表現したい時にはPicker
を使います。もちろん自作するという手もありますが、今回はPicker
を使用して表現する方法にしました。
Pickerとは
セットされた相互に排他的な値の選択をコントロールできるものになります。
struct Picker<Label, SelectionValue, Content> where Label : View, SelectionValue : Hashable, Content : View
- Label
Picker
のラベル。このラベルは、Form
やList
内でPicker
を使用すると表示されます。
- SelectionValue
- 何が選択されているかの値
- Content
Picker
の中身
ただ、このPicker
をそのまま使用するだけではSegemented Control的な表現はできません。
pickerStyle(.segmented)
Segemented Control的な表現をするためには、PickerStyle
を.segemented
に指定してあげる必要があります。
PickerStyle
には、下記のようにたくさん種類がありますので是非試してみてください。
サンプルコード
.segmented
のスタイルを使用したサンプルコードを準備しました。
import SwiftUI
struct ContentView: View {
enum Friends: String, CaseIterable, Identifiable {
case ossa = "オッサ"
case ossan = "オッサン"
var id: String { rawValue }
}
@State private var selectedFriend = Friends.ossa
var body: some View {
Picker("友達", selection: $selectedFriend) {
ForEach(Friends.allCases) {
friend in
Text(friend.rawValue).tag(friend)
}
}
.pickerStyle(.segmented)
.padding()
}
}
プレビュー
上記のコードのプレビューはこのようになっています。
色とフォントを変更する
colorMultiplyを使用する
.colorMultiply(_:)
を使用することでPicker
で選択中の色を設定出来ます。
var body: some View {
Picker("友達", selection: $selectedFriend) {
ForEach(Friends.allCases) {
friend in
Text(friend.rawValue).tag(friend)
}
}
.colorMultiply(.green)
.pickerStyle(.segmented)
.padding()
}
しかし、これだと限定的なカスタムしか出来ません。今後対応されて色々なカスタムが可能になると嬉しいですね。
UISegmentedControl.appearance()を設定する
やはりUIKitに頼るしかないのか、、ということで、
Segmented Control風Picker
の色やフォントを変更する為に、UISegmentedControl.appearance()
を設定します。init
メソッドを追加し、メソッド内でappearanceの設定をしてあげます。
// 追加
init() {
let appearance = UISegmentedControl.appearance()
let font = UIFont.boldSystemFont(ofSize: 17)
let foregroundColor = UIColor.systemGreen
// 選択時の背景色
appearance.selectedSegmentTintColor = foregroundColor
// 通常時のフォントとフォント色
appearance.setTitleTextAttributes([
.font: font,
.foregroundColor: foregroundColor
], for: .normal)
// 選択時のフォントとフォント色
appearance.setTitleTextAttributes([
.font: font,
.foregroundColor: UIColor.white
], for: .selected)
}
var body: some View {
// 省略
}
これでSegmented Control風Picker
のカスタムが出来ました。
おわりに
SwiftUIだけでPicker
のカスタムが出来ず、UIKitの力を借りました。ですが、もしSwiftUIだけで完結する方法をご存知の方いましたら優しく教えていただけると幸いです。
まぁ、自分でView
をカスタムして作ればいいんでしょうけどね。