Using multicolor symbols on light/dark backgrounds in Strings

64 views Asked by At

I'm struggling to use sf-symbols with different background colours. I've discovered I can set a View to light or dark mode (e.g. to render a black symbol white when used on a dark background) but this does not appear to work when I embed the symbol in a string.

// Black background
            HStack {
                Image(systemName: "heart.fill")
                Image(systemName: "suit.club.fill")
                Text("=> \(Image(systemName: "suit.spade.fill")) <=")
            }
            .symbolRenderingMode(.multicolor)
            .environment(\.colorScheme, .dark)
            .frame(width: 200, height: 50).background(.black)
     
 // White background
            HStack {
                Image(systemName: "heart.fill")
                Image(systemName: "suit.club.fill")
                Text("=> \(Image(systemName: "suit.spade.fill")) <=")
 
            }
            .symbolRenderingMode(.multicolor)
            .environment(\.colorScheme, .light)
            .frame(width: 200, height: 50).background(.white)

screenshot

As you can see in this screenshot the symbol (spades) in the Text view is not rendered according to the environment modifier even though the previous symbol (clubs) is.

One workaround is to display the Text as a concatonation of Strings and Images, but I'd rather avoid this so that I don't run into translation issues. Any suggestions?

PS: This is primarily for use in visionOS which according to Apple does not have dark mode but renders text nevertheless in dark mode, whereas I want to have dark text on a light background.

2

There are 2 answers

1
dorianDevTech On

One way of inverting the color while using a Text() view can be by using the .invertColor() modifier ⬇️

Text("\(Image(systemName: "suit.club.fill"))").colorInvert()

This will show you your spade ♠️ SF Symbol in white (show below behind yours): ⬇️ Spade SF Symbol shown in "white" color - end of the row

But by reading your code I'll suggest you to continue using the Image() view just like you did for your other SF Symbols.

0
alanrick On

I'm not happy with this solution, but it does sort of work in visionOS.

The workaround is to avoid the use of Images where possible and use emoji's instead. I'm disappointed but I don't see a way out of this if I want the string to be a translatable phrase, rather than concatenated bits and pieces. With iOS it's not a problem when the text is superimposed on the background. But in visionOS I want to have a solid background (not Glass).

So the solution looks like:

       VStack {
                Text("♣️ and ❤️ are best")
                    .foregroundColor(.black)
       }
       .frame(width: 200, height: 50).background(.white)

visionOS screenshot