Contrast for texts in widgets with image backgrounds transparent mode

Hello,

in my widget the user displays images filling the whole widget with overlayed texts (via ZStack). Via shadows or text background color the text gets better readable.

However, when a user chooses transparent or tinted colors for the home screen, the text is barely or not readable anymore since e.g. white text on white image background. How to resolve this issue?

Are you using @Environment(\.widgetRenderingMode) var widgetRenderingMode already? If not, add that to your widget view, and change how the widget looks depending on the various values of widgetRenderingMode, i.e.:

var body: some View {
    ZStack {
       switch renderingMode {
        case .fullColor:
           Text("Full color")
        case .accented:
           ZStack {
               Circle(...)
               VStack {
                   Text("Accented")
                       .widgetAccentable()
                   Text("Normal")
               }
           }
        case .vibrant:
           Text("Full color")
        default:
           ...
        }
    }
}

Also, on images, there's a modifier: .widgetAccentedRenderingMode() with options like .accentedDesaturated. Take a look at how each of those values affects your widget, and you might find out the right combination that works in each of the various Home Screen modes. Note that this is only available from iOS 18 onwards.

Also note (from the dev documentation) if the Image is a subview for a group that has widgetAccentable(true) applied, this modifier may conflict.

It's quicker to check the various looks in Xcode previews than it is to build and deploy to an iPhone and customise the Home Screen each time, just to save you some time.

Thanks for your quick reply!

However, this doesn't resolve the issue. In transparent mode all texts and also background colors (even when they are black) gets converted to white or a very light color, so there is no more contrast between the background (image) and text because it's not possible to add e.g. a black background behind the text to have it better readable.

The only workarounds I have found is to darken the images, so that there is more contrast, what I want to avoid. Another option is to save the images with the rendered black texts as a single image object, then the contrast between texts and background images remain.

However, I would prefer to have some native solutions within WidgetKit.

ZStack {
   Image(...) // light coloured or white image
   VStack {  
       Text("Normal") // text gets white or light coloured
           .foregroundStyle(Color.black) // gets white or very light coloured
           .frame(maxWidth: .infinity,
                  maxHeight: .infinity,
                  alignment: .bottomLeading)
           // .background(.black) //  gets white or light coloured
    }
 }

Right, but the code you've posted isn't making use of any of the suggestions I made - which are from WidgetKit. Those bits of WidgetKit are there to aid you in displaying the widget in the correct style for the appearance currently selected.

Look at how Apple's own Podcasts widgets or Weather widgets act on the Home Screen in Clear and Tinted modes; they have no gradient or background. The recommended style for a widget background in Clear or Tinted modes is to have a clear background, i.e. no image, so you should either not display your image, or set its opacity to a low number and tweak it until it looks good.

Preview your widget in Xcode, change the display mode to Clear or Tinted, then add the modifier .widgetAccentedRenderingMode(.accentedDesaturated)to the Image. Does it improve your widget?

With the posted code I just wanted to show the simplified principal structure of the views to get a better picture. Additionally, I have added an image to better illustrate the issue.

No setting of widgetAccentedRenderingMode or widgetAccentable with considering widgetRenderingMode makes the contrast between the text and the image better. (When user has transparent mode enabled). And I have really played around a lot!

You have mentioned the photos widget, this is the most similar to the one I have. They typically doesn't show any text. Very seldom there is a text but on a dark image. So I guess, they check if the image is dark and only in this case show a white text.

What would you do in my case?

But I can't help you if I don't know how that widget has been created. How are the four images displayed? What modifiers are you using? Is that in Clear or Tinted mode?!

I've suggested the code from WidgetKit that you can use to change the appearance of the image in the different widget styles. Can you maybe apply them to the four images in the widget and show us what it looks like in Clear and Tinted modes?

.vibrant mode is used when a widget is on the Lock Screen, in StandBy, and also in Tinted and Clear modes, and you either don't show an image background, or - if your widget requires an image, like Apple's Photos widget - then you need to desaturate your image and accent your text.

Try some different options, post the code used, and a screenshot of how it looks.

Contrast for texts in widgets with image backgrounds transparent mode
 
 
Q