Search code examples
iosswiftios17

iPhone status bar items automatically swap dark/light per the background - how to use this ability on a symbol?


The items in the status bar now work like this on an iPhone:

enter image description here

(The white bar moving up and down is just a square of white I put in a scroll view.)

The SF symbols know to change from light/dark depending on the background.

Here's a symbol I added to a button.

It does not have the automatic light/dark behavior.

enter image description here

Is there a way to get the same effect on my own button or SF symbol using something Apple provides?

(Please note that I know how to tediously program this manually on my own. I'm wondering if we have access to the same calls Apple does? Apple has so many systems now it's impossible to find or know them all!)

One thought I had was, could I make a status bar item (or something like that) but actually not place it on the status bar?


Solution

  • You can get quite close to the same effect if you use Color.white as foreground color and then apply either BlendMode.exclusion or BlendMode.difference.

    • For black and white backgrounds, this works the same as the native symbols in the iOS header.
    • For colored backgrounds, you get the inverted color. If you know the background will be colored then BlendMode.colorDodge might be a better choice.

    Like this:

    var body: some View {
        ScrollView {
            VStack(spacing: 0) {
                Color.white
                    .frame(height: 200)
                Color.black
                    .frame(height: 200)
                Color.blue
                    .frame(height: 200)
                Color.red
                    .frame(height: 200)
                Color.yellow
                    .frame(height: 200)
                Color(UIColor.systemBackground)
                    .frame(height: 1000)
            }
        }
        .overlay(alignment: .topTrailing) {
            Image(systemName: "xmark")
                .resizable()
                .scaledToFit()
                .frame(width: 25, height: 25)
                .padding(.top, 80)
                .padding(.horizontal)
                .foregroundColor(.white)
                .blendMode(.exclusion)
    //            .blendMode(.difference) // works same as .exclusion
    //            .blendMode(.colorDodge) // for colored backgrounds
        }
        .ignoresSafeArea()
    }
    

    Animation