SwiftUI:如何在SwiftUI中实现单选按钮

时间:2019-10-30 07:08:04

标签: ios swift swiftui

我正在创建一个简单的表单应用程序。这样,我有复选框和单选按钮,但是我不知道该怎么做。

我已完成以下代码来动态更改所选选项的颜色。但是可以选择多个值。我只需从单选按钮等5个值中选择一个即可。

例如: 我正在点击第二个单选按钮。现在,如果我选择第四个单选按钮,则应该取消选择第二个单选按钮,而应该选择第四个单选按钮。


struct DCTableCell: View {

    @Binding var dcValue: String

    @State var isSelected: Bool = false

    var body: some View {


        Button(action: {
            print("Tapped")
            self.isSelected.toggle()
        }){
            ZStack {
                RoundedRectangle(cornerRadius: 8)
                    .stroke(self.isSelected ? Color.init("borderSelected"): Color.init("border"))
                    .frame(height: 56)
                    .foregroundColor(.clear)

                HStack {
                    Text(dcValue)
                        .font(.custom("Montserrat", size: 16))
                        .fontWeight(.medium)
                        .foregroundColor(self.isSelected ? Color.init("borderSelected") : .white)
                        .padding()

                    Spacer()

                    ZStack {
                        Circle()
                            .stroke(self.isSelected ? Color.init("borderSelected") : Color("circleBorder"))
                            .frame(width: 18, height: 18)
                            .padding()

                        Circle()
                            .frame(width: 10, height: 10)
                            .foregroundColor(self.isSelected ? Color.init("borderSelected"): Color.clear)

                    }
                }
            }
        }
    }
}

3 个答案:

答案 0 :(得分:1)

检查一下...一个易于使用的iOS SwiftUI RadiobuttonGroup

您可以像这样使用它:

RadioButtonGroup(items: ["Rome", "London", "Paris", "Berlin", "New York"], selectedId: "London") { selected in
                print("Selected is: \(selected)")
            }

这是代码:

struct ColorInvert: ViewModifier {

    @Environment(\.colorScheme) var colorScheme

    func body(content: Content) -> some View {
        Group {
            if colorScheme == .dark {
                content.colorInvert()
            } else {
                content
            }
        }
    }
}

struct RadioButton: View {

    @Environment(\.colorScheme) var colorScheme

    let id: String
    let callback: (String)->()
    let selectedID : String
    let size: CGFloat
    let color: Color
    let textSize: CGFloat

    init(
        _ id: String,
        callback: @escaping (String)->(),
        selectedID: String,
        size: CGFloat = 20,
        color: Color = Color.primary,
        textSize: CGFloat = 14
        ) {
        self.id = id
        self.size = size
        self.color = color
        self.textSize = textSize
        self.selectedID = selectedID
        self.callback = callback
    }

    var body: some View {
        Button(action:{
            self.callback(self.id)
        }) {
            HStack(alignment: .center, spacing: 10) {
                Image(systemName: self.selectedID == self.id ? "largecircle.fill.circle" : "circle")
                    .renderingMode(.original)
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .frame(width: self.size, height: self.size)
                    .modifier(ColorInvert())
                Text(id)
                    .font(Font.system(size: textSize))
                Spacer()
            }.foregroundColor(self.color)
        }
        .foregroundColor(self.color)
    }
}

struct RadioButtonGroup: View {

    let items : [String]

    @State var selectedId: String = ""

    let callback: (String) -> ()

    var body: some View {
        VStack {
            ForEach(0..<items.count) { index in
                RadioButton(self.items[index], callback: self.radioGroupCallback, selectedID: self.selectedId)
            }
        }
    }

    func radioGroupCallback(id: String) {
        selectedId = id
        callback(id)
    }
}

struct ContentView: View {
    var body: some View {
        HStack {
            Text("Example")
                .font(Font.headline)
                .padding()
            RadioButtonGroup(items: ["Rome", "London", "Paris", "Berlin", "New York"], selectedId: "London") { selected in
                print("Selected is: \(selected)")
            }
        }.padding()
    }
}

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

struct ContentViewDark_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
        .environment(\.colorScheme, .dark)
        .darkModeFix()
    }
}

enter image description here

答案 1 :(得分:0)

好吧,这不是理想的解决方案,但它可以起作用,希望可以睁大眼睛改善您的生活。我给每个RadioButton分配一个ID,并且当所选ID更改时会更新:

struct DCTableCell: View {

    var id: Int
    @Binding var dcValue: String
    @Binding var selectedID: Int

    var body: some View {
        Button(action: {
            print("Tapped")
            self.selectedID = self.id
        }){
            ZStack {
                RoundedRectangle(cornerRadius: 8)
                    .stroke(self.id == self.selectedID ? Color.blue : Color.white)
                    .frame(height: 56)
                    .foregroundColor(.clear)

                HStack {
                    Text(dcValue)
                        .font(.custom("Montserrat", size: 16))
                        .fontWeight(.medium)
                        .foregroundColor(self.id == self.selectedID ? .blue : .white)
                        .padding()

                    Spacer()

                    ZStack {
                        Circle()
                            .stroke(self.id == self.selectedID ? Color.blue : .black)
                            .frame(width: 18, height: 18)
                            .padding()

                        Circle()
                            .frame(width: 10, height: 10)
                            .foregroundColor(self.id == self.selectedID ? Color.blue: Color.clear)

                    }
                }
            }
        }
    }
}

这里是如何使用它。也许您应该创建一个包含ID和要传递的字符串的数组。

struct ContentView: View {
    @State var str = "lolz"
    @State var selectedID = -1

    var body: some View {
        VStack {
            ForEach((1...5), id: \.self) { index in
                DCTableCell(id: index, dcValue: self.$str, selectedID: self.$selectedID)
            }
        }
    }
}

我希望这会有所帮助!

答案 2 :(得分:0)

我有一个类似的解决方案,将标签用作可哈希标记,这使其非常简单。因此,您只需要设置外层CustomDCPicker,就像常规选择器一样即可。

                 UIHostingController(rootView: CustomDCPicker())

        struct CustomDCPicker: View {
            @State var dcValue: String = ""
            var body: some View {
                VStack{
                    Text(dcValue).bold()
                    DCTable.init(dcValue: $dcValue, Labels: ["sample1","sample2","sample3","sample4","sample5"])
                }
            }
        }

        struct DCTable: View {
            @Binding var dcValue: String
            var Labels: [String] = []
        var body: some View {
            ForEach(Labels, id:\.self){
                DCTableCell(dcValue: self.$dcValue, myLabel: $0)
            }
        }
        }

        struct DCTableCell: View {
            @Binding var dcValue: String
            var isSelected: Bool {
                get{   self.dcValue == self.myLabel}
            }
            var myLabel : String
            var body: some View {
                Button(action: {
                    print("Tapped")
                    self.dcValue = self.myLabel
                }){
                    ZStack {
                        RoundedRectangle(cornerRadius: 8.0)
                            .stroke(self.isSelected ? Color.red: Color.yellow)
                            .frame(height: 56)
                            .foregroundColor(.clear)

                        HStack {
                            Text(myLabel)
                                //.font(.custom("Montserrat", size: 16))
                                .fontWeight(.medium)
                                .foregroundColor(self.isSelected ? Color.red : .black)
                                .padding()

                            Spacer()

                            ZStack {
                                Circle()
                                    .stroke(self.isSelected ? Color.red : Color.black)
                                    .frame(width: 18, height: 18)
                                    .padding()

                                Circle()
                                    .frame(width: 10, height: 10)
                                    .foregroundColor(self.isSelected ? Color.red: Color.clear)

                            }
                        }
                    }
                }
            }
        }