SwiftUI自定义选择器标签未呈现。

11

更新至iOS 15和Xcode 13后,我的应用程序中的选择器不再显示自定义标签。在iOS 14设备上运行应用程序,选择器可以正常渲染。

以下是当前实现的代码片段,截图显示了在iOS 15模拟器中的外观。

    @State var selectedNumber: Int = 0
    
    var body: some View {
        Picker(selection: $selectedNumber, label: customLabel) {
            ForEach(0..<10) {
                Text("\($0)")
            }
        }
    }
    
    var customLabel: some View {
        HStack {
            Image(systemName: "paperplane")
            Text(String(selectedNumber))
            Spacer()
            Text("⌵")
                .offset(y: -4)
        }
        .foregroundColor(.white)
        .font(.title)
        .padding()
        .frame(height: 32)
        .background(Color.blue)
        .cornerRadius(16)
    }

screenshot


1
使用一个菜单,里面包含一个Picker,就像我在这里回答的一样:https://stackoverflow.com/a/68897763/1601849 - Adam
3个回答

18

@Adam提供的答案有效。以下是我为解决此问题所做的步骤,以防其他人遇到类似问题。

@State var selectedNumber: Int = 0

var body: some View {
    Menu {
        Picker(selection: $selectedNumber, label: EmptyView()) {
            ForEach(0..<10) {
                Text("\($0)")
            }
        }
    } label: {
        customLabel
    }
}

var customLabel: some View {
    HStack {
        Image(systemName: "paperplane")
        Text(String(selectedNumber))
        Spacer()
        Text("⌵")
            .offset(y: -4)
    }
    .foregroundColor(.white)
    .font(.title)
    .padding()
    .frame(height: 32)
    .background(Color.blue)
    .cornerRadius(16)
}

3
这个方法似乎不能自动将列表居中于所选值。这是长列表超出屏幕的问题。 - Quentin Hayot
在使用Xcode 14.1的watchOS中,这个解决方案不起作用,标签只有在选择器处于活动状态时才会显示。 - lewis

3
您可以使用菜单选项作为标签。
Menu("Drop Your Label Here") {
        Picker("Please choose a color", selection: $selectedColor)
        {
            ForEach(colors, id: \.self) {
                Text($0)
            }
        }
        
    }
    //.foregroundColor(Color.init("Red"))
    .foregroundColor(Color.red)
}.frame(width: 300, height: 60)

对于寻找watchOS解决方案的人,“'Menu'在watchOS中不可用”。 - lewis

0

我一直在努力解决这个问题,但它仍然存在(xcode 14 beta iOS 16)。我想出了这个解决方案,希望能对某些人有所帮助,直到苹果解决此问题。

如果选择的项目不在数组中,则标签将不会显示。因此,我将标签添加到数组中,并使同一标签成为所选项目的值。这将导致标签始终显示,因此当用户单击弹出列表时,如果您想要删除标签,则可以执行此操作。

@State private var items = ["please select an option","Option1","Option2","Option3","Option4","Option5"]
@State private var selectedItem = "please select an option"   

var body: some View {

Picker(selection: $selectedItem, label: Text(selectedItem)) {
    ForEach(items, id: \.self) {
        Text($0)
    }
    }.onTapGesture(){
        if items.contains("please select an option") {
            items.remove(at: 0)
        }   
    }   

}

如果你有一个自己的对象数组而不是字符串,请使用 Int { hashValue } 作为你的对象的 ID。

struct myStruct: Hashable, Identifiable {
    var id: Int { hashValue } //UUID is not going to work for this issue
        let myValue:String
        let myOtherValue:String
}

@State private var structItems = [myStruct(myValue: "0", myOtherValue: "please select an option"),
                                      myStruct(myValue: "1", myOtherValue: "Option1"),
                                      myStruct(myValue: "2", myOtherValue: "Option2"),
                                      myStruct(myValue: "3", myOtherValue: "Option3"),
                                      myStruct(myValue: "4", myOtherValue: "Option4"),
                                      myStruct(myValue: "5", myOtherValue: "Option5")]
@State private var selectedStructItem = myStruct(myValue: "0", myOtherValue: "please select an option")


var body: some View {

Picker(selection: $selectedStructItem, label: Text(selectedStructItem.myOtherValue)) {
    ForEach(structItems, id: \.id) { val in
        Text(val.myOtherValue).tag(val)
    }
    }.onTapGesture(){
        if structItems.contains(myStruct(myValue: "0", myOtherValue: "please select an option")) {
                        structItems.remove(at: 0)
                }
    }


}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接