programing

Swift에서 배경을 흐리게 하는 방법이 있습니까?UI?

telebox 2023. 8. 25. 23:29
반응형

Swift에서 배경을 흐리게 하는 방법이 있습니까?UI?

뷰의 배경을 흐리려고 하지만 이를 달성하기 위해 UIKit에 침입할 필요는 없습니다(예: a).UIVisualEffectView) 문서를 뒤졌지만 아무 데도 가지 못했습니다. 라이브 클립으로 배경을 만들고 효과를 적용할 수 있는 방법이 없는 것 같습니다.제가 틀렸나요 아니면 잘못된 방법으로 조사하고 있나요?

네이티브 스위프트UI 방식:

그냥 추가.blur()다음과 같이 흐리게 해야 하는 모든 항목에 대한 수식어:

Image("BG")
   .blur(radius: 20)

Blur Demo 보기의 위쪽과 아래쪽을 메모합니다.

수 있습니다.Group여러 뷰를 함께 흐리게 표시합니다.


시각적 효과 보기:

국장님을 모셔오시면 됩니다UIVisualEffectViewUIKit에서:

VisualEffectView(effect: UIBlurEffect(style: .dark))

이 작은 구조로:

struct VisualEffectView: UIViewRepresentable {
    var effect: UIVisualEffect?
    func makeUIView(context: UIViewRepresentableContext<Self>) -> UIVisualEffectView { UIVisualEffectView() }
    func updateUIView(_ uiView: UIVisualEffectView, context: UIViewRepresentableContext<Self>) { uiView.effect = effect }
}

VEV Demo


iOS 15: 재료

iOS 사전 정의된 재료는 다음과 같은 라인 코드로 사용할 수 있습니다.

.background(.ultraThinMaterial)

Demo

스위프트에서 그것을 달성할 방법을 찾지 못했습니다.아직 UI이지만 UI를 사용할 수 있습니다.UIViewRepresentable의전

struct BlurView: UIViewRepresentable {

    let style: UIBlurEffect.Style

    func makeUIView(context: UIViewRepresentableContext<BlurView>) -> UIView {
        let view = UIView(frame: .zero)
        view.backgroundColor = .clear
        let blurEffect = UIBlurEffect(style: style)
        let blurView = UIVisualEffectView(effect: blurEffect)
        blurView.translatesAutoresizingMaskIntoConstraints = false
        view.insertSubview(blurView, at: 0)
        NSLayoutConstraint.activate([
            blurView.heightAnchor.constraint(equalTo: view.heightAnchor),
            blurView.widthAnchor.constraint(equalTo: view.widthAnchor),
        ])
        return view
    }

    func updateUIView(_ uiView: UIView,
                      context: UIViewRepresentableContext<BlurView>) {

    }

}

데모:

struct ContentView: View {

    var body: some View {
        NavigationView {
            ZStack {
                List(1...100) { item in
                    Rectangle().foregroundColor(Color.pink)
                }
                .navigationBarTitle(Text("A List"))
                ZStack {
                    BlurView(style: .light)
                        .frame(width: 300, height: 300)
                    Text("Hey there, I'm on top of the blur")

                }
            }
        }
    }

}

사용한ZStack그 위에 의견을 덧붙입니다.

ZStack {
 // List
 ZStack {
    // Blurred View
    // Text
 }
}

결국 이렇게 됩니다.

enter image description here

가장 간단한 방법은 Richard Mullinix의 다음과 같습니다.

struct Blur: UIViewRepresentable {
    var style: UIBlurEffect.Style = .systemMaterial

    func makeUIView(context: Context) -> UIVisualEffectView {
        return UIVisualEffectView(effect: UIBlurEffect(style: style))
    }

    func updateUIView(_ uiView: UIVisualEffectView, context: Context) {
        uiView.effect = UIBlurEffect(style: style)
    }
}

그런 다음 코드의 배경과 같은 곳에서 사용합니다.

    //...
    MyView()
        .background(Blur(style: .systemUltraThinMaterial))

iOS 15의 새로운 기능,SwiftUI와 동등한 훌륭할 정도로 단순합니다.UIVisualEffectView그것이 결합된ZStack,그background()수식어 및 다양한 내장 재료.

ZStack {
    Image("niceLook")

    Text("Click me")
        .padding()
        .background(.thinMaterial)
}

여러 재료 유형 중 하나를 사용하여 재료의 "두께"(배경 내용이 얼마나 빛나는지)를 조정할 수 있습니다.두께가 가장 얇은 것부터 두꺼운 것까지 다음과 같습니다.

.ultraThinMaterial
.thinMaterial
.regularMaterial
.thickMaterial
.ultraThickMaterial

@mojtaba에서 언급했듯이, 설정할 때 이미지 상단에 흰색 음영이 나타나는 것은 매우 특이합니다.resizable()흐림과 함께 ().

간단한 방법은 이미지 패딩을 -ve로 올리는 것입니다.

 var body: some View {

        return
            ZStack {

                Image("background_2").resizable()
                    .edgesIgnoringSafeArea(.all)
                    .blur(radius: 5)
                    .scaledToFill()
                    .padding(-20) //Trick: To escape from white patch @top & @bottom


        }
  }

결과:

저는 이 문제를 해결하기 위한 흥미로운 해킹을 발견했습니다.우리는 사용할 수 있습니다.UIVisualEffectView그것의 배경을 라이브로 "녹음"하는 것.하지만 이 "스냅샷"은 다음과 같은 효과를 발휘합니다.UIVisualEffectView다음을 사용하여 이 효과를 적용하지 않을 수 있습니다.UIViewPropertyAnimator.

저는 이 해킹의 부작용을 발견하지 못했습니다.여기에서 제 솔루션을 찾을 수 있습니다: my GitHub Gist.

코드

/// A View in which content reflects all behind it
struct BackdropView: UIViewRepresentable {

    func makeUIView(context: Context) -> UIVisualEffectView {
        let view = UIVisualEffectView()
        let blur = UIBlurEffect()
        let animator = UIViewPropertyAnimator()
        animator.addAnimations { view.effect = blur }
        animator.fractionComplete = 0
        animator.stopAnimation(false)
        animator.finishAnimation(at: .current)
        return view
    }
    
    func updateUIView(_ uiView: UIVisualEffectView, context: Context) { }
    
}

/// A transparent View that blurs its background
struct BackdropBlurView: View {
    
    let radius: CGFloat
    
    @ViewBuilder
    var body: some View {
        BackdropView().blur(radius: radius)
    }
    
}

사용.

ZStack(alignment: .leading) {
    Image(systemName: "globe")
        .resizable()
        .frame(width: 200, height: 200)
        .foregroundColor(.accentColor)
        .padding()
    BackdropBlurView(radius: 6)
        .frame(width: 120)
}

Usage example

@State private var amount: CGFLOAT = 0.0

var body: some View {
    VStack{
       Image("Car").resizable().blur(radius: amount, opaque: true)
    }
}

블러 기능과 함께 "불투명: 참"을 사용하면 흰색 노이즈가 제거됩니다.

매우 유용하지만 유감스럽게도 개인적인 수업이 있습니다(감사합니다 Apple).CABackdropLayer

아래 레이어의 복사본을 그립니다. 사용할 때 유용하다는 것을 알았습니다.blend mode또는 필터, 블러 효과에도 사용할 수 있습니다.

코드

open class UIBackdropView: UIView {

  open override class var layerClass: AnyClass {
    NSClassFromString("CABackdropLayer") ?? CALayer.self
  }
}

public struct Backdrop: UIViewRepresentable {

  public init() {}

  public func makeUIView(context: Context) -> UIBackdropView {
    UIBackdropView()
  }

  public func updateUIView(_ uiView: UIBackdropView, context: Context) {}
}

public struct Blur: View {

  public var radius: CGFloat
  public var opaque: Bool

  public init(radius: CGFloat = 3.0, opaque: Bool = false) {
    self.radius = radius
    self.opaque = opaque
  }

  public var body: some View {
    Backdrop()
      .blur(radius: radius, opaque: opaque)
  }
}

사용.

struct Example: View {

  var body: some View {
    ZStack {
      YourBelowView()
      YourTopView()
        .background(Blur())
        .background(Color.someColor.opacity(0.4))
    }
  }
}

원천

때때로 우리는 투명한 흐림 효과가 필요합니다.여기에 해결책이 있을 것입니다.

struct TransparentBlurView: UIViewRepresentable {
    typealias UIViewType = UIVisualEffectView

    func makeUIView(context: Context) -> UIVisualEffectView {
        let view = UIVisualEffectView(effect: UIBlurEffect(style: .systemUltraThinMaterialLight))

        return view
    }

    func updateUIView(_ uiView: UIVisualEffectView, context: Context) {
        DispatchQueue.main.async {
            if let backdropLayer  = uiView.layer.sublayers?.first {
                backdropLayer.filters?.removeAll(where: { filter in
                    String(describing: filter) != "gaussianBlur"
                })
            }
        }
    }
}

enter image description here

Button("Test") {}
        .background(Rectangle().fill(Color.red).blur(radius: 20))

언급URL : https://stackoverflow.com/questions/56610957/is-there-a-method-to-blur-a-background-in-swiftui

반응형