[英]SwiftUI: How to implement Radio button in SwiftUI
我正在創建一個簡單的表單應用程序。 在那,我有復選框和單選按鈕,但我不知道該怎么做。
我已經完成了以下代碼來動態更改所選選項的顏色。 但它可以是 select 多個值。 我只需要 select 5 個值中的一個值,例如單選按鈕。
例如:我正在點擊第二個單選按鈕。 現在如果我 select 第四個單選按鈕,第二個應該取消選擇,第四個應該被選中。
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)
}
}
}
}
}
}
看看這個...一個易於使用的 SwiftUI RadiobuttonGroup 用於 iOS
你可以像這樣使用它:
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()
}
}
好的,這不是一個理想的解決方案,但它可以工作,並希望讓您大開眼界,以改善您所擁有的。 我給每個 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)
}
}
}
}
我希望這有幫助!
我有一個類似的解決方案,將標簽用作可散列標簽,使其非常直接。 所以你只需要設置外層: 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)
}
}
}
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.