【问题标题】:Radiobuttons in List swiftUIList swiftUI中的单选按钮
【发布时间】:2021-11-17 18:35:21
【问题描述】:

我正在显示来自服务器的数据,并且需要在单选按钮中显示选项。但默认不应选择任何按钮。我能够显示单选按钮。但是,当单击特定按钮时,仅应更改其图像。尽管使用我的代码,所有其他按钮图像也会发生变化。我浏览了一些参考资料SwiftUI - How to change the button's image on click?,但无法正常工作。作为 SwiftUI 的新手,在这里被击中。

struct ListView: View {
    @State var imageName: String = "radio-off"

    var body: some View {
        List(vwModel.OpnChoice.ItemList) { opn in
            VStack(alignment:.leading) {
                ForEach(opn.Choices.indices, id: \.self) { row in
                    Button(action: {
                        print("\(opn.Choices[row].ChoiceId)")
                        self.imageName = "radio-On"
                    }) {
                        Image(imageName)
                            .renderingMode(.original)
                            .resizable()
                            .aspectRatio(contentMode: .fill)
                            .frame(width: 30, height: 30)           
                    }

                    Text(opn.Choices[row].ChoiceName)   
                }
            }
        }
    }
}

【问题讨论】:

  • 请用小写字母命名变量。看到vwModel.OpnChoice.ItemList 而不是将其视为类型非常令人困惑。它显然不是这里的类型,所以应该是vwModel.opnChoice.itemListopn.choices 也一样。还有opn.choices[row].choiceId
  • @Fogmeister ;从服务器我在 ItemList 中得到响应,所以在模型中我将其作为 struct OptionsandChoiceList: Decodable{ let ItemList:[OptionsandChoices] }。
  • 如果我像你所说的那样给予;小写为 itemList ;我没有收到服务器的响应
  • 您的服务器正在返回 JSON。他们可能有也可能没有关于如何命名数据的约定。但是在 Swift 中你可以。属性以小写字母开头。 :D 如果您正在解码 JSON,那么您可以使用 CodingKeys 将 JSON 名称与您的 Swift 对象中的名称相匹配。
  • 查看部分...“映射不同的键名”在这里...hackingwithswift.com/articles/119/codable-cheat-sheet ????????

标签: swiftui radio-button


【解决方案1】:

目前,您正在为整个列表存储一个 @State 属性“imageName”。然后,当点击列表中的任何按钮时,您正在更改该单个属性。这将影响所有按钮。

我建议删除此属性并将某些内容放入 viewModel。

您似乎有一个视图模型,其中包含一个名为 vwModel.opnChoice.itemList 的数组。

有多种方法可以完成这项工作。您可以在 itemList 中停止一个布尔值来说明是否选择了每个项目。但是,当您希望它像单选按钮一样工作时,最好在 vwModel 上拥有一个属性,例如 selectedItem

然后按钮可以做...

vwModel.selectedItemId = opn.choices[row].choiceId

然后你按钮Label 将是......

Image(vsModel.selectedItemId == opn.choices[row].choiceId ? "radio-on" : "radio-off")
  .renderingMode(.original)
  .resizable()
  .aspectRatio(contentMode: .fill)
  .frame(width: 30, height: 30) 

这将允许您在点击按钮时切换按钮并关闭其他按钮。

【讨论】:

    【解决方案2】:

    当您使用索引时,请将@Published 属性添加到包含所选索引的视图模型中。

    然后在按钮动作中设置索引。视图的重绘将选定索引处的按钮设置为打开状态,将其他按钮设置为关闭状态。

    由于我不了解您的环境,这是一个简化的独立视图模型和带有 SF Symbols 图像的视图

    class VMModel : ObservableObject {
        @Published var selectedOption = -1
        
        var numberOfOptions = 5
    }
    
    struct ListView: View {
        
        @StateObject private var vwModel = VMModel()
        
        var body: some View {
            VStack(alignment:.leading) {
                ForEach(0..<vwModel.numberOfOptions, id: \.self) { opn in
                    Button(action: {
                        vwModel.selectedOption = opn
                        print("index \(opn) selected")
                    }) {
                        Image(systemName: opn == vwModel.selectedOption ? "largecircle.fill.circle" : "circle")
                            .renderingMode(.original)
                            .resizable()
                            .aspectRatio(contentMode: .fill)
                            .frame(width: 30, height: 30)
                    }
                    
                }
            }
            
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-12-28
      • 1970-01-01
      • 1970-01-01
      • 2017-07-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多