系統(tǒng)CheckBox(Toggle組件)開關(guān)無法改造,系統(tǒng)提供的Picker組件可以采用RadioGroupPickerStyle()來實現(xiàn)單選,但UI過于單一。需要單選按鈕可以分組且選中和非選中icon可自定義方便擴(kuò)展,直接上代碼
RadioButton.swift
import Foundation
import SwiftUI
public struct RadioButton<Image, Label> : View where Image : View, Label : View {
let id: String
@Binding var selectedId: String
@ViewBuilder var image: (Bool) -> Image
@ViewBuilder var label: () -> Label
public init(id: String, selectedId: Binding<String>, @ViewBuilder image: @escaping (Bool) -> Image, @ViewBuilder label: @escaping () -> Label) {
self.id = id;
self._selectedId = selectedId
self.image = image
self.label = label
}
public var body: some View {
Button {
self.selectedId = id
} label: {
HStack {
image(id == self.selectedId)
label()
}
.contentShape(Rectangle())
}
.buttonStyle(.plain)
}
}
調(diào)用舉例
@State private var radioSelected: String = "0" //獲取選中值且起到分組作用
@State private var radioSelected2: String = "0"
var body: some View {
VStack(spacing: 10) {
//===================組一
RadioButton(id: "0", selectedId: $radioSelected) { check in
Image(systemName: check ? "record.circle.fill" : "circle")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 14, height: 14, alignment: .center)
.foregroundColor(check ? Color.accentColor : Color.gray)
} label: {
Text("選項A")
.font(.system(size: 14))
}
RadioButton(id: "1", selectedId: $radioSelected) { check in
Image(systemName: check ? "record.circle.fill" : "circle")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 14, height: 14, alignment: .center)
.foregroundColor(check ? Color.accentColor : Color.gray)
} label: {
Text("選項B")
.font(.system(size: 14))
}
//===================組二
RadioButton(id: "0", selectedId: $radioSelected2) { check in
Image(systemName: check ? "checkmark.circle.fill" : "circle")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 14, height: 14, alignment: .center)
.foregroundColor(check ? Color.accentColor : Color.gray)
} label: {
Text("選項A")
.font(.system(size: 14))
}
RadioButton(id: "1", selectedId: $radioSelected2) { check in
Image(systemName: check ? "checkmark.circle.fill" : "circle")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 14, height: 14, alignment: .center)
.foregroundColor(check ? Color.accentColor : Color.gray)
} label: {
Text("選項B")
.font(.system(size: 14))
}
}
}