Search code examples
swiftuipicker

SwiftUI Picker label


I have a code like this. like the code there is Image and label in content of picker. i want to when i tap on a picker option display only the label. but the problem is that both image and label will show up on the picker label. how should i fix this?

HStack {
    Picker(selection: $selectedVenueType) {
        ForEach(types, id:\.self) { type in
            HStack {
                Text(type)
                    .font(.footnote)
                    .foregroundStyle(.black)
                Spacer()
                if type != "Select venue type" {
                    Image(getImage(type: type))
                        .resizable()
                        .aspectRatio(contentMode: .fit)
                        .frame(width: UIScreen.main.bounds.height*0.04, height: UIScreen.main.bounds.height*0.04)
                }
            }
            .tag(type)
            .frame(width: UIScreen.main.bounds.width*0.78)
        }
    } label: {
        HStack {
            Text("selectedVenueType")
                .font(.footnote)
                .foregroundStyle(.black)
                .labelStyle(.titleOnly)
        }
        .frame(width: UIScreen.main.bounds.width*0.78, height: UIScreen.main.bounds.height*0.05)
    }
    .pickerStyle(MenuPickerStyle())
        .frame(width: UIScreen.main.bounds.width*0.78, height: UIScreen.main.bounds.height*0.05)
        .background(Color.white)
        .tint(Color.black)
        .cornerRadius(14) // Adjust the corner radius as needed
        .shadow(color: Color(red: 0.27, green: 0.27, blue: 0.27, opacity: 0.2), radius: 2, x: 0, y: 1)
}

This is the code of my picker.


Solution

  • Embed the Picker in a Menu. You have much more control over the label of a menu, than the title of the picker's button.

    Here is an example:

    struct ContentView: View {
        
        @State var selection: PickerOption = options[0]
        
        var body: some View {
            Menu {
                Picker("Options", selection: $selection) {
                    ForEach(options, id: \.self) { option in
                        Label(option.title, systemImage: option.systemImage)
                    }
                }
            } label: {
                // you can control a lot more things here
                // e.g. make it only show the selected item's title
                // and the "up-down" symbol
                HStack {
                    Text(selection.title)
                    Image(systemName: "chevron.up.chevron.down")
                        .imageScale(.small)
                }
            }
    
        }
    }
    
    struct PickerOption: Hashable {
        let title: String
        let systemImage: String
    }
    
    
    let options = [
        PickerOption(title: "Option 1", systemImage: "circle"),
        PickerOption(title: "Option 2", systemImage: "rectangle"),
    ]
    

    Output:

    enter image description here enter image description here

    Side note: I would not recommend using the size of UIScreen to lay out your views.