mginn
mginn

Reputation: 16114

SwiftUI - How can I pass the current accent color to a sheet?

SwiftUI, as of now, does not pass the current accent color to sheets. In the following example, the accent color of the button in the sheet will not be red.

// Some parent view which sets an accent color, can't change this
struct ContentView: View {
    var body: some View {
        ChildView()
            .accentColor(.red)
    }
}

// A child view that uses the accent color set by the parent
struct ChildView: View {
    @State var showSheet = false
    
    var body: some View {
        VStack {
            Button("this uses red"){
                showSheet = true
            }
            .sheet(isPresented: $showSheet){
                VStack {
                    Button("this will ignore accent color"){ }
                }
            }
        }
    }
}

I'm guessing this is a bug, but I'm looking for a workaround. The problem is, I can't just set .accentColor(.red) or whatever inside of the presented sheet, because my app uses dynamic accent colors depending on a setting. That is to say–I need to be able to pass the accentColor of ChildView on to the sheet, without knowing what it is necessarily.

I'v tried passing .accentColor(.accentColor) to the view in the sheet, which does not work.

Any ideas?

Upvotes: 4

Views: 1790

Answers (1)

There are a number of ways to do this, the following is just one way:

(macos 11.4, xcode 12.5, target ios 14.5 and macCatalyst 11.3.)

struct ContentView: View {
    @State var showSheet = false
    @State var accentColor = Color.red
    
    var body: some View {
        VStack {
            Button("this uses red"){
                showSheet = true
            }.sheet(isPresented: $showSheet){
                TheSheetView(accentColor: $accentColor)
            }
        }.accentColor(accentColor)
    }
}
struct TheSheetView: View {
    @Binding var accentColor: Color
    var body: some View {
        VStack {
            Button("this will not ignore accent color"){ }.accentColor(accentColor)
        }
    }
}

or you could try this:

@main
struct TestErrorApp: App {
    var myAccent = MyAccent()
    var body: some Scene {
        WindowGroup {
            ContentView().environmentObject(myAccent)
        }
    }
}

class MyAccent: ObservableObject {
    @Published var color = Color.red
}

struct ContentView: View {
    @EnvironmentObject var myAccent: MyAccent  // <--- will be available to all child views
    @State var showSheet = false
    
    var body: some View {
        VStack {
            Button("this uses red"){
                showSheet = true
            }.sheet(isPresented: $showSheet){
                TheSheetView().environmentObject(myAccent) // <--- need this for sheets
            }
        }.accentColor(myAccent.color)
    }
}
struct TheSheetView: View {
    @EnvironmentObject var myAccent: MyAccent
    var body: some View {
        VStack {
            Button("this will ignore accent color"){ }.accentColor(myAccent.color)
        }
    }
}

Upvotes: 0

Related Questions