SwiftUI - Pickerを使ったアイコンの選択と色の選択

1. アイコンを選択できるようにする

image

簡易的ですが、ユーザーがアイコン(SF Symbols)を選択できるようにする画面を作成してみたのでまとめておこうと思います。

はじめに、好きなアイコンを「SF Symbols」から選択し、配列にしておきます。

let iconSet: [String] = ["camera", "book", "phone", "car", "house"]

上記で作成した配列をPickerを使用して選択できるようにします。Pickerは色々な種類がありますが、ここではNavigationView + Formを使用しています。Pickerについては以前の記事にまとめています。

@Stateで配列のインデックス番号を入れた変数を用意し、その変数をPickerselectionに入れアイコンを選択できるようにします。

struct ContentView: View {
  @State private var iconIndex = 0 //初期値
  
  let iconSet: [String] = ["camera", "book", "phone", "car", "house"]
  
  var body: some View {
    NavigationView {
      Form {
        Picker("Icon", selection: $iconIndex) {
          ForEach(0 ..< iconSet.count) {i in
            HStack {
              //Image(systemName: String)
              Image(systemName: self.iconSet[i])
              Text(self.iconSet[i])
            }
            .tag(i)
          }
        }
      }
      .navigationTitle("Icon Select")
      .navigationBarTitleDisplayMode(.inline)
    }
  }
}

..< - 終了値を含まない

2. 選択したアイコンを表示する

選択したアイコンを表示する場所をForm内に追加します。

struct ContentView: View {
  @State private var iconIndex = 0
  
  let iconSet: [String] = ["camera", "book", "phone", "car", "house"]
  
  var body: some View {
    NavigationView {
      Form {
        //選択したアイコンを表示
        HStack {
          Spacer()

          Image(systemName: self.iconSet[iconIndex])
            .resizable()
            .scaledToFit()
            .frame(height: 100.0)

          Spacer()
        }
        .padding(.vertical, 50.0)

        //アイコンを選択
        Picker("Icon", selection: $iconIndex) {
          ForEach(0 ..< iconSet.count) {i in
            HStack {
              Image(systemName: self.iconSet[i])
              Text(self.iconSet[i])
            }
            .tag(i)
          }
        }
      }
      .navigationTitle("Icon Select")
      .navigationBarTitleDisplayMode(.inline)
    }
  }
}

.resizable() - スペースに合わせて画像のサイズを変更するモードを設定
.scaledToFit() - アスペクト比を維持しながら拡大縮小する

3. アイコンの色を選択できるようにする

作り方はアイコンの選択と同じなので、アイコンの色も選択できるようにしたいと思います。違うところは、Color型が必要なところです。色の名前も一緒に表示したかったので構造体を定義しています。

//vvv
struct ColorSet {
  let name: String
  let color: Color
}

struct ContentView: View {
  @State private var iconIndex = 0
  @State private var colorIndex = 0 //<<<

  let iconSet: [String] = ["camera", "book", "phone", "car", "house"]

  //vvv
  let colorSet = [
    ColorSet(name: "red", color: .red),
    ColorSet(name: "blue", color: .blue),
    ColorSet(name: "green", color: .green),
    ColorSet(name: "yellow", color: .yellow)
  ]
  
  var body: some View {
    NavigationView {
      Form {
        //選択したアイコンを表示
        HStack {
          Spacer()

          Image(systemName: self.iconSet[iconIndex])
            .resizable()
            .scaledToFit()
            .frame(height: 100.0)
            .foregroundColor(colorSet[colorIndex].color) //<< 色を適用

          Spacer()
        }
        .padding(.vertical, 50.0)

        //アイコンを選択
        Picker("Icon", selection: $iconIndex) {
          ForEach(0 ..< iconSet.count) {i in
            HStack {
              Image(systemName: self.iconSet[i])
              Text(self.iconSet[i])
            }
            .tag(i)
          }
        }

        //アイコンの色を選択
        Picker("Color", selection: $colorIndex) {
          ForEach(0 ..< colorSet.count) { i in
            HStack {
              Image(systemName: "circle.fill")
                .foregroundColor(colorSet[i].color)
              Text(self.colorSet[i].name)
            }
            .tag(i)
          }
        }
      }
      .navigationTitle("Icon Select")
      .navigationBarTitleDisplayMode(.inline)
    }
  }
}

resizable(capInsets:resizingMode:) | Apple Developer Documentation
scaledtofit() | Apple Developer Documentation