昨日書いた通り、最近 SwiftUIで遊んでます。Viewから呼び出される小さいViewを用意するのが楽そうです。
で、自分のアプリの外観モードをシステムに合わせたり、ダークにしたり、設定機能を用意して変更可能にするには…? という感じで色々調べてたどり着いた結果を残します。
結論的には、.preferredColorScheme を使うのが良さそうです。
設定は Pickerで行うことにして、selection に渡す値をとかを用意しました。
enum Theme:Int { // Pickerで使える型が必要
case system = 0 // 無くても平気だろうけど念のため
case light
case dark
var value:ColorScheme? {
switch self {
case .system: return nil
case .light: return .light
case .dark: return .dark
}
}
}
Pickerを使った選択機能を Viewにまとめました。アプリに記憶させたいので、かつての UserDefaultsの代わり? の @AppStorageへ保存できるようにします。
struct SelectColorSchemeView: View {
@AppStorage("theme") var theme:Theme = .system
var title:String = ""
var body: some View {
HStack {
if title.count > 0 { Text(title) }
Picker(selection: $theme, label: Text("")) {
Text("light").tag(Theme.light)
Text("system").tag(Theme.system)
Text("dark").tag(Theme.dark)
}.pickerStyle(SegmentedPickerStyle())
}
}
}
@AppStorageを使うことで、他の Viewでも値が変更されたらすぐ反映されるので楽チンです。設定Viewを呼ばなくても前回指定した値が有効になっていることを確認するため、設定画面ボタンみたいなのを用意して開閉してるっぽくしました。
struct ContentView: View {
@AppStorage("theme") var theme:Theme = .system
@State var isSetting = false
var body: some View {
VStack {
Spacer()
HStack {
Button (isSetting ? "Close" : "Setting") {
isSetting.toggle()
}
Spacer()
if isSetting {
SelectColorSchemeView()
}
}.border(.gray, width: 1)
}.preferredColorScheme(theme.value)
}
}
Assetsでダークモードとかに対応した色セットを作ることができますが、この Viewと設定部分を組み込んでおくことで、色セットの変更確認も簡単にできるようになりました。