How to recreate the iOS 16 Lock Screen Widget Vibrant effect in SwiftUI 4.0?

Viewed 632

I am looking for a way to reproduce the "Vibrant" iOS 16 effect that occurs on Lock Screen Widget on iOS 16 because my app should be able to display a preview of the widget while the user is the creation process.

Examples: See the 4 round widgets on the center screen below.

See the 4 round widgets on the center screen.

Here is what Apple documentation says about this effect:

Vibrant: For Lock Screen widgets, iOS desaturates text, images, and gauges into monochrome and creates a vibrant effect by coloring your content appropriately for the Lock Screen background. People can also color the Lock Screen to a colored tint. from Apple Documentation

I don't know how to reproduce that effect. Did a try with that code but not satisfied:

MyOriginalView()
    .compositingGroup()
    .saturation(0.0)
    .blendMode(.plusLighter) // or .blendMode(.hardLight)

Here is more precise explanation of the vibrant effet from iOS 16 that I would like to reproduce.

Using the source view and a parameter color, the source view is converted to gray scale. White pixels seems to be rendered using the parameter color, where black pixel use a blurred transparent darker color based on the parameter color.

See below an example of view transformation.

View Transformation example

Here is some code to create a Test image and to have the iOS 16 widget render from this view. This is exactly the effect I want to mimic in my app.

SwiftUI 4.0 Code (iOS16+): (You will need to add a Widget Target for the code to compile I think)

import SwiftUI
import WidgetKit

struct SourceView: View {
    var body: some View {
        VStack (spacing: 0) {
            Color.black
            HStack (spacing: 0) {
                Color.black
                Color.black.opacity(0.75)
                Color.black.opacity(0.5)
                Color.black.opacity(0.25)
                Color.black.opacity(0.0)
            }
            HStack (spacing: 0) {
                Color.red
                Color.blue
                Color.green
                Color.yellow
                Color.white
            }
            HStack (spacing: 0) {
                Color.white.opacity(0.0)
                Color.white.opacity(0.25)
                Color.white.opacity(0.5)
                Color.white.opacity(0.75)
                Color.white
            }
            Color.white
        }
        .aspectRatio(1, contentMode: .fit)
        .mask(Circle())
    }
}


struct SourceView_Previews: PreviewProvider {
    static var previews: some View {
        SourceView()
            .padding(20)
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            .background(LinearGradient(colors: [Color(white:0.96), Color(white:0.6)], startPoint: .topLeading, endPoint: .bottomTrailing))
            .ignoresSafeArea()
    }
}

@available(iOS 16.0, *)
struct VibrantEffectDemonstration_Previews: PreviewProvider {
    static var previews: some View {
        SourceView()
        .previewContext(WidgetPreviewContext(family: .accessoryCircular))
    }
}

This code will render: enter image description here

Any help appreciated!

Thanks

0 Answers
Related