🚠

SwiftUIでラジオボタンを作ってみる

2024/01/06に公開

読んでほしい人

  • SwiftUIを勉強してる人
  • ラジオボタンを使ってみたい

記事の内容

公式ドキュメントを見てみたが、そのままでは使えなかった💦
なので、よくあるUIを作りたいと思い技術記事を書くことにしました。

まずは海外の人のを参考にしてみた。こちらはコードが長い😅

構造体を定義する
import SwiftUI


//MARK:- Single Radio Button Field
struct RadioButtonField: View {
    let id: String
    let label: String
    let size: CGFloat
    let color: Color
    let textSize: CGFloat
    let isMarked:Bool
    let callback: (String)->()
    
    init(
        id: String,
        label:String,
        size: CGFloat = 20,
        color: Color = Color.black,
        textSize: CGFloat = 14,
        isMarked: Bool = false,
        callback: @escaping (String)->()
        ) {
        self.id = id
        self.label = label
        self.size = size
        self.color = color
        self.textSize = textSize
        self.isMarked = isMarked
        self.callback = callback
    }
    
    var body: some View {
        Button(action:{
            self.callback(self.id)
        }) {
            HStack(alignment: .center, spacing: 10) {
                Image(systemName: self.isMarked ? "largecircle.fill.circle" : "circle")
                    .renderingMode(.original)
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .frame(width: self.size, height: self.size)
                Text(label)
                    .font(Font.system(size: textSize))
                Spacer()
            }.foregroundColor(self.color)
        }
        .foregroundColor(Color.white)
    }
}
状態を管理するコード
import SwiftUI
//MARK:- Group of Radio Buttons
enum Gender: String {
    case male = "男性"
    case female = "女性"
}

struct RadioButtonGroups: View {
    let callback: (String) -> ()
    
    @State var selectedId: String = ""
    
    var body: some View {
        VStack {
            radioMaleMajority
            radioFemaleMajority
        }
    }
    
    var radioMaleMajority: some View {
        RadioButtonField(
            id: Gender.male.rawValue,
            label: Gender.male.rawValue,
            isMarked: selectedId == Gender.male.rawValue ? true : false,
            callback: radioGroupCallback
        )
    }
    
    var radioFemaleMajority: some View {
        RadioButtonField(
            id: Gender.female.rawValue,
            label: Gender.female.rawValue,
            isMarked: selectedId == Gender.female.rawValue ? true : false,
            callback: radioGroupCallback
        )
    }
    
    func radioGroupCallback(id: String) {
        selectedId = id
        callback(id)
    }
}
アプリを実行するコード
import SwiftUI

struct ContentView: View {
    var body: some View {
        HStack {
                    Text("性別")
                        .font(Font.headline)
                    RadioButtonGroups { selected in
                        print("Selected Gender is: \(selected)")
                    }
                }.padding()
        .padding()
    }
}




struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

スクリーンショット:

簡単な方法で作るならこちらの記事が参考になります:
https://zenn.dev/fijii_rin/articles/a66cf09dbc99a2

ContentView.swiftに書くだけで使える
import SwiftUI

struct ContentView: View {
    
    @State private var selectedIndex = 0
    
    private let selectNames = ["男性", "女性", "その他"]
    
    var body: some View {
        VStack {
            Spacer()
            
            ForEach(0..<selectNames.count, id: \.self, content: { index in
                HStack {
                    Text(selectNames[index])
                    
                    Image(systemName: selectedIndex == index ? "checkmark.circle.fill" : "circle")
                        .foregroundColor(.blue)
                }
                .frame(height: 40)
                
                .onTapGesture {
                    selectedIndex = index
                }
            })
            
            Spacer()
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

補足情報

公式のラジオボタンの解説がありましが、コードは使えないようです?
https://developer.apple.com/documentation/swiftui/view/horizontalradiogrouplayout()

AIに聞いてみたらこんな回答がくる:

SwiftUIのPickerには、iOSではradioGroupというピッカースタイルは存在しません。そのため、radioGroupを使用しようとするとエラーが発生します。

「うわ〜使えないじゃん!」

最後に

公式のコードがそのまま使えなかったので絶望しましたが、こんなときは、人の技術記事を見るしかないですね。公式ドキュメントを見るとかいう人いるけど、バージョン古かったり中途半端なものがあるので、Mediumを見てみるといいかもですね。

参考にした海外の記事:
https://thinkdiff.net/how-to-create-radio-button-and-group-in-swiftui-46b34e0ba69a

Discussion