SwiftUIでアプリの外観モードを変更する

昨日書いた通り、最近 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と設定部分を組み込んでおくことで、色セットの変更確認も簡単にできるようになりました。

コメントを残す

メールアドレスが公開されることはありません。

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください