swiftui - 禁用 SwiftUI SegmentedPickerStyle Picker 中的一个段?

标签 swiftui uisegmentedcontrol

我的 SwiftUI 应用程序有一个分段选择器,我希望能够根据从网络调用中检索到的选项的可用性来禁用一个或多个选项。 View 代码类似于:

    @State private var profileMetricSelection: Int = 0
    private var profileMetrics: [RVStreamMetric] = [.speed, .heartRate, .cadence, .power, .altitude]
    @State private var metricDisabled = [true, true, true, true, true]

    var body: some View {
        VStack(alignment: .leading, spacing: 2.0) {
            ...(some views)...
            Picker(selection: $profileMetricSelection, label: Text("")) {
                ForEach(0 ..< profileMetrics.count) { index in
                    Text(self.profileMetrics[index].shortName).tag(index)
                }
            }.pickerStyle(SegmentedPickerStyle())
            ...(some more views)...
        }
    }


我希望能够做的是修改 metricDisabled数组基于网络数据,因此 View 重绘启用相关段。在 UIKit 中,这可以通过调用 setEnabled(_:forSegmentAt:) 来完成。在 UISegmentedControl 上,但我找不到使用 SwiftUI Picker 执行此操作的方法

我知道我可以将 UISegmentedControl 包装在 UIViewRepresentable 中,但在此之前我只是想检查一下我没有遗漏什么......

最佳答案

你可以使用这个简单的技巧

import SwiftUI

struct ContentView: View {
    @State var selection = 0
    let data = [1, 2, 3, 4, 5]
    let disabled = [2, 3] // at index 2, 3
    var body: some View {

        let binding = Binding<Int>(get: {
            self.selection
        }) { (i) in
            if self.disabled.contains(i) {} else {
                self.selection = i
            }
        }

        return VStack {
            Picker(selection: binding, label: Text("label")) {
                ForEach(0 ..< data.count) { (i) in
                    Text("\(self.data[i])")
                }
            }.pickerStyle(SegmentedPickerStyle())
            Spacer()
        }
    }
}

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

enter image description here

也许像
ForEach(0 ..< data.count) { (i) in
    if !self.disabled.contains(i) {
        Text("\(self.data[i])")
    } else {
        Spacer()
    }
}

可以帮助更好地形象化

enter image description here

注释(基于讨论)

从用户的角度来看,选择器是一种控件,可以处于禁用/启用状态。

从 Picker 中选择的选项不是控制,而是一些值。如果您制作了一个向用户展示的控件列表,其中一些控件可能会被禁用,只是为了通知用户与其关联的操作当前不可用(例如菜单、某些按钮集合等)。

我建议您只在 Picker 中显示可以选择的值。这个值集合可以随时更新。

更新

你喜欢这样的东西吗?

enter image description here

完全没问题......(复制 - 粘贴 - 尝试 - 修改......)
import SwiftUI

struct Data: Identifiable {
    let id: Int
    let value: Int
    var disabled: Bool
}

struct ContentView: View {
    @State var selection = -1
    @State var data = [Data(id: 0, value: 10, disabled: true), Data(id: 1, value: 20, disabled: true), Data(id: 2, value: 3, disabled: true), Data(id: 3, value: 4, disabled: true), Data(id: 4, value: 5, disabled: true)]
    var filteredData: [Data] {
        data.filter({ (item) -> Bool in
            item.disabled == false
        })
    }
    var body: some View {
        VStack {
            VStack(alignment: .leading, spacing: 0) {
                Text("Select from avaialable")
                    .padding(.horizontal)
                    .padding(.top)
                HStack {
                    GeometryReader { proxy in
                        Picker(selection: self.$selection, label: Text("label")) {
                            ForEach(self.filteredData) { (item) in
                                Text("\(item.value.description)").tag(item.id)
                            }
                        }
                        .pickerStyle(SegmentedPickerStyle())
                        .frame(width: CGFloat(self.filteredData.count) * proxy.size.width / CGFloat(self.data.count), alignment: .topLeading)

                        Spacer()
                    }.frame(height: 40)
                }.padding()
            }.background(Color.yellow.opacity(0.2)).cornerRadius(20)
            Button(action: {
                (0 ..< self.data.count).forEach { (i) in
                    self.data[i].disabled = false
                }
            }) {
                Text("Enable all")
            }
            Button(action: {
                self.data[self.selection].disabled = true
                self.selection = -1
            }) {
                Text("Disable selected")
            }.disabled(selection < 0)
            Spacer()
        }
    }
}

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

关于swiftui - 禁用 SwiftUI SegmentedPickerStyle Picker 中的一个段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60528953/

相关文章:

ios - 如何检查项目是否可见 - SwiftUI ScrollView

ios - NSInvalidArgumentException 使用 UISegmentedControl

ios - 为什么我不能在 Swift 中设置我的 UINavigationController 的标题?

swift - 如何在对 SegmentedControl 执行操作后在 PickerView 中设置行

ios - Swift 分段控件和 UITableView

events - 如何使用 SwiftUI 和 Combine 检测 Datepicker 的值变化?

ios - iOS 14(Xcode 12 Beta)中如何从UIKit生命周期转换为SwiftUI生命周期

iphone - 自定义 UISegmentedControl,添加背景图片和选择的段色调颜色

SwiftUI如何在表单中居中放置文本?

SwiftUI 如何对齐两个不同字体大小的文本的底部?