Is it possible to override dark mode for a form only?

Viewed 225

What I want to achieve is a form with a different background color. But I want the items inside always using the light mode variant (dark text colors). But not the complete view. I've searched for it but couldn't find any solution.

I've tried listRowBackground to change background of the items which works and preferredColorScheme to use the light mode but that will make the complete view in light mode:

...

Form {

    DatePicker(selection: $date, displayedComponents: .date) { ... }
        .listRowBackground(Color.yellow)

    TextField("Name", text: $name)
        .listRowBackground(Color.yellow)

    Picker("amount", selection: $amount) {
        ForEach(amounts, id: \.self) {
            Text($0)
        }
    }
    .listRowBackground(Color.yellow)

    Button(action: { ... }) {
        Label("More", systemImage: "chevron.up")
    }
    .listRowBackground(Color.yellow)

}
.preferredColorScheme(.light)

...
2 Answers

You can use .environment to force the color scheme of the view:

.environment(\.colorScheme, .light)

If you don't want to do this for the whole form, you can inject it to the nested views only:

Form {
    Group {
        DatePicker(selection: $date, displayedComponents: .date) { ... }
            .listRowBackground(Color.yellow)

        TextField("Name", text: $name)
            .listRowBackground(Color.yellow)

        Picker("amount", selection: $amount) {
            ForEach(amounts, id: \.self) {
                Text($0)
            }
        }
        .listRowBackground(Color.yellow)

        Button(action: { ... }) {
            Label("More", systemImage: "chevron.up")
        }
        .listRowBackground(Color.yellow)
    }
    .environment(\.colorScheme, .light)
}

(or to a single view only)

Form {
    // ...

    TextField("Name", text: $name)
        .listRowBackground(Color.yellow)
        .environment(\.colorScheme, .light)

    // ...
}

You can use foregroundColor(Color.black) or accentColor(Color.black) for this work:

enter image description here


import SwiftUI

struct ContentView: View {
    
    @State private var string: String = String()
    
    @State var selectedColor: Int = 2
    let colorArray: [String] = ["Black", "Blue", "Gray", "Green"]

    
    var body: some View {
        
        VStack(spacing: 20) {
            
            Text("This text has a dark text color!")
                .foregroundColor(Color.black)
                .padding()
    
            TextField("Enter your text here. . .", text: $string)
                .background(Color.red)
                .foregroundColor(Color.black)

            Picker(selection: $selectedColor, label: Text(String())) {

                ForEach(colorArray.indices, id: \.self) { index in

                    Text(colorArray[index])
                        .foregroundColor(Color.black)
                    
                }

            }

            
            Text("This text has a normal text color!")
                .foregroundColor(Color.primary)
                .padding()
            
        }
        .padding()
        .background(Color.red)
        .cornerRadius(10)
  
    }
}
Related