// Copyright © 2020 Metabolist. All rights reserved. // Taken from Apple's Fruta example code import SwiftUI struct VisualEffectBlur: View { var blurStyle: UIBlurEffect.Style var vibrancyStyle: UIVibrancyEffectStyle? var content: Content init(blurStyle: UIBlurEffect.Style = .systemMaterial, vibrancyStyle: UIVibrancyEffectStyle? = nil, @ViewBuilder content: () -> Content) { self.blurStyle = blurStyle self.vibrancyStyle = vibrancyStyle self.content = content() } var body: some View { Representable( blurStyle: blurStyle, vibrancyStyle: vibrancyStyle, content: ZStack { content }) .accessibility(hidden: Content.self == EmptyView.self) } } extension VisualEffectBlur { struct Representable: UIViewRepresentable { var blurStyle: UIBlurEffect.Style var vibrancyStyle: UIVibrancyEffectStyle? var content: Content func makeUIView(context: Context) -> UIVisualEffectView { context.coordinator.blurView } func updateUIView(_ view: UIVisualEffectView, context: Context) { context.coordinator.update(content: content, blurStyle: blurStyle, vibrancyStyle: vibrancyStyle) } func makeCoordinator() -> Coordinator { Coordinator(content: content) } } } extension VisualEffectBlur.Representable { class Coordinator { let blurView = UIVisualEffectView() let vibrancyView = UIVisualEffectView() let hostingController: UIHostingController init(content: Content) { hostingController = UIHostingController(rootView: content) hostingController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight] hostingController.view.backgroundColor = nil blurView.contentView.addSubview(vibrancyView) blurView.autoresizingMask = [.flexibleWidth, .flexibleHeight] vibrancyView.contentView.addSubview(hostingController.view) vibrancyView.autoresizingMask = [.flexibleWidth, .flexibleHeight] } func update(content: Content, blurStyle: UIBlurEffect.Style, vibrancyStyle: UIVibrancyEffectStyle?) { hostingController.rootView = content let blurEffect = UIBlurEffect(style: blurStyle) blurView.effect = blurEffect if let vibrancyStyle = vibrancyStyle { vibrancyView.effect = UIVibrancyEffect(blurEffect: blurEffect, style: vibrancyStyle) } else { vibrancyView.effect = nil } hostingController.view.setNeedsDisplay() } } } extension VisualEffectBlur where Content == EmptyView { init(blurStyle: UIBlurEffect.Style = .systemMaterial) { self.init(blurStyle: blurStyle, vibrancyStyle: nil) { EmptyView() } } } struct VisualEffectBlur_Previews: PreviewProvider { static var previews: some View { ZStack { LinearGradient( gradient: Gradient(colors: [.red, .blue]), startPoint: .topLeading, endPoint: .bottomTrailing ) VisualEffectBlur(blurStyle: .systemUltraThinMaterial, vibrancyStyle: .fill) { Text("Hello World!") .frame(width: 200, height: 100) } } .previewLayout(.sizeThatFits) } }