Search code examples
swiftuibackgroundbackground-colorpicker

How to set background colour of Picker control?


I have a picker control (SwiftUI) and I am having trouble setting the background colour correctly.

In the below, I have set the background as GREEN, but notice there is a slightly darker overlayed colour around the text itself.

See the word "One" below. There is a dark overlay over the text component of the picker control.

This behaviour is only seen on a physical iPhone, but it is not shown on the simulator.

enter image description here

Complete code of example is below.

The effect I am trying to achieve is like that shown on the simulator, where the background green colour of the picker control is exactly the same as the background green colour of the Text view above it.

Is it achievable to have a picker control WITHOUT having this darker overlay colour around the text portion of the control?

import SwiftUI

struct Test: View {
    var items = ["One", "Two", "Three", "Four"]
    @State private var selection = "One"

    var body: some View {
        VStack {
            Text("Text")
                .foregroundStyle(.white)
                .frame(width: 150, height: 35)
                .background(.green)
        
            Picker("Please choose an item", selection: $selection) {
                ForEach(items, id: \.self) {
                    Text($0)
                }
            }
            .frame(width: 150, height: 35)
            .background(.green)
            .tint(.white)
        
            Text("You selected: \(selection)")
            Spacer()
        }
        .padding(.top,50)
    }
}

#Preview {
    Test()
}

Solution

  • This effect is probably because button shapes has been turned on in the accessibility settings. I can reproduce it on a simulator by turning button shapes on.

    It would be possible to mask out the effect by using an overlay. Taps could be allowed to pass through to the underlying picker by using .allowsHitTesting(false). However, using an overlay in this way is probably not a good idea, for a couple of reasons:

    • The shaded area is in fact the only area that is receptive to taps. The picker does not respond to taps in the area outside of the shaded region, even when button shapes is turned off. So the button shape actually serves a useful purpose in identifying the tappable area.

    • An overlay would not provide any kind of button-pressed effect.

    If you really want to avoid the effect and, perhaps more significantly, make the control receptive to tap gestures over its full width, then a custom picker might be the best solution. One approach would be to use a Menu to emulate the picker functionality, see the answer to Increase size of Picker / drop down when displaying symbols with large font for an example.