7

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

Clement M
  • 709
  • 6
  • 14

1 Answers1

-1

This effect which you talk about is a blur effect. In iOS 16's lock widgets you can use Material as background which results in blurring the background (wallpaper) and since you can cover it with "something", you can make result as Apple has. You can work with RGB of view as well as with its opacity:

struct MaterialView: View {
    var body: some View {
        VStack(spacing: 0) {
            HStack(spacing: 0) {
                Color(red: 0, green: 0, blue: 0)
                Color(red: 0.1, green: 0.1, blue: 0.1)
                Color(red: 0.2, green: 0.2, blue: 0.2)
                Color(red: 0.3, green: 0.3, blue: 0.3)
                Color(red: 0.4, green: 0.4, blue: 0.4)
            }
            HStack(spacing: 0) {
                Color.white.opacity(0)
                Color.white.opacity(0.1)
                Color.white.opacity(0.2)
                Color.white.opacity(0.3)
                Color.white.opacity(0.4)
            }
        }
            .background(.ultraThinMaterial) // <-- HERE
    }
}

struct MaterialView_Previews: PreviewProvider {
    static var previews: some View {
        MaterialView()
            .previewContext(WidgetPreviewContext(family: .accessoryCircular))
    }
}

Result:

enter image description here

Available materials as described in the documentation:

enter image description here

Robert Dresler
  • 10,580
  • 2
  • 22
  • 40
  • I think you misunderstood my question. I know how to use the blur effect. My question is about how to reproduce the effect Apple does on the Lock Screen but outside the context of the Lock Screen. – Clement M Sep 27 '22 at 07:59