UIVisualEffectView 및 / 또는 UIBlurEffect를 페이드 인 및 아웃하는 방법은 무엇입니까?


92

UIBlurEffect를 사용하여 UIVisualEffectsView를 페이드 인 및 아웃하고 싶습니다.

var blurEffectView = UIVisualEffectView()
blurEffectView = UIVisualEffectView(effect: UIBlurEffect(style: .dark))

나는 UIButton그것을 페이드 인하 기 위해 호출하는 함수 내에서 일반 애니메이션을 사용하고 페이드 아웃과 동일하지만 .alpha = 0& hidden = true:

blurEffectView.hidden = false
UIView.animate(withDuration: 1, delay: 0, options: .curveEaseOut) {
    self.blurEffectView.alpha = 1
}

이제 양방향으로 페이드가 작동하지만 페이드 아웃 할 때 오류가 발생 합니다 .

<UIVisualEffectView 0x7fdf5bcb6e80>불투명도에 애니메이션을 적용하라는 요청을 받고 있습니다. 이렇게하면 불투명도가 1이 될 때까지 효과가 깨져 보입니다.

질문

어떻게 성공적으로 페이드 할 수 UIVisualEffectView없이 들락날락 위반 을하고 페이딩 전환을 가지고?

노트

  • 나는 그것을 UIVisualEffectView안으로 넣고 그것을 UIView페이드 하려고 노력했지만 , 성공하지 못했다.

다음과 같은 방법으로 오류를 피할 수 있습니다. 1. blurEffect에 초기 스타일을 할당하지 않습니다. 즉, var blurEffectView = UIVisualEffectView () 그런 다음 2. 애니메이션 블록 내부의 blurEffectView에 blurEffect를 할당합니다. 3. "blurEffectView에 대한 blurEffect 할당"애니메이션은 blurEffectView.alpha에 대한 조정 대신 수행됩니다. ** 초기 값을 지정하지 않고 다시 추가해도 오류가 발생합니다. 따라서 오류를 방지하는 핵심은 애니메이션 블록까지 blurEffectView에 효과를 할당하지 않는 것입니다.
ObjectiveTC

또한 오류를 방지하려면 blurEffectView에 alpha = 1.0이 있어야합니다. 어떤 식 으로든 알파를 조작하면 오류가 발생합니다. 예를 들어 애니메이션 블록 이전에 blurEffectView.alpha = 0.7로 설정 한 다음 animationBlock에서 blurEffectView.effect = blurEffect를 할당하면 오류가 생성됩니다.
ObjectiveTC

답변:


185

나는 이것이 iOS9에서 새로운 것이라고 생각하지만 이제 UIVisualEffectView애니메이션 블록 내부 의 효과를 설정할 수 있습니다 .

let overlay = UIVisualEffectView()
// Put it somewhere, give it a frame...
UIView.animate(withDuration: 0.5) {
    overlay.effect = UIBlurEffect(style: .light)
}

nil제거 하려면 로 설정 하십시오.

매우 중요-시뮬레이터에서 이것을 테스트 할 때 이것이 작동하도록 시뮬레이터의 그래픽 품질 재정의를 고품질로 설정해야합니다.


1
완벽하게 작동합니다. 감사.
Baza207 15.

큰! 말했듯이 iOS 8에서는 작동하지 않습니다. : /
LinusGeffarth

내가 위에서 쓴 것 때문입니다. 어쨌든 지금 승낙했습니다. @jpros
LinusGeffarth 2015

10
효과를 nil로 설정하여 꽤 "
흐릿함

1
@jpros "흐림"이 무슨 뜻인지 설명해 주시겠습니까?
ndmeiri

19

애플 문서는 (현재) 상태 ...

UIVisualEffectView 클래스를 사용하는 경우 1보다 작은 알파 값을 사용하지 마십시오.

시각적 효과보기 또는 수퍼 뷰에서 알파를 1 미만으로 설정하면 많은 효과가 잘못 보이거나 전혀 표시되지 않습니다.

여기에 몇 가지 중요한 맥락이 누락되었다고 생각합니다 ...

영구 뷰를 위해 1보다 작은 알파 값을 피하는 것이 목적이라고 제안합니다. 내 겸손한 의견으로는 이것은 뷰의 애니메이션에는 적용되지 않습니다.

내 요점은 1보다 작은 알파 값이 애니메이션에 허용된다는 점입니다.

터미널 메시지에 다음과 같이 표시됩니다.

UIVisualEffectView는 불투명도를 애니메이션하도록 요청됩니다. 이렇게하면 불투명도가 1이 될 때까지 효과가 깨져 보입니다.

이것을주의 깊게 읽으면 효과가 깨지는 것처럼 보일 것 입니다. 이것에 대한 나의 요점 :

  • 명백한 단절은 변하지 않는 지속적인 뷰에만 정말로 중요합니다.
  • 지속적 / 변함없는 UIVisualEffect알파 값이 1 미만인 보기는 Apple이 의도 한 / 설계 한대로 표시되지 않습니다. 과
  • 터미널의 메시지는 오류가 아니라 경고 일뿐입니다.

내 문제를 해결하는 데 도움이 된 @jrturton의 답변을 확장하려면 ...

페이드 아웃하려면 UIVisualEffect다음 (Objective-C) 코드를 사용하십시오.

UIView.animateWithDuration(1.0, animations: {
//  EITHER...
    self.blurEffectView.effect = UIBlurEffect(nil)
//  OR...
    self.blurEffectView.alpha = 0
}, completion: { (finished: Bool) -> Void in
    self.blurEffectView.removeFromSuperview()
} )

두 가지 방법을 모두 성공적으로 사용합니다. effect속성 nil설정 및 alpha속성 설정0 .

로 설정하면 애니메이션 끝에 "멋진 플래시"(더 나은 설명을 원 effect하기 위해) nil가 생성 alpha되고0 원활한 전환을 만듭니다.

(구문 오류가 있으면 알려주세요 ... obj-c로 작성합니다.)


귀하의 기여에 감사드립니다. 나는 당신의 요점을 얻습니다. 오류가 이미 :) 당신이 언급 한 정확히 승 / 나를 위해 해결
LinusGeffarth

14

다음은 Swift 3을 사용하여 iOS10 및 이전 버전 모두에서 작동하는 솔루션입니다.

extension UIVisualEffectView {

    func fadeInEffect(_ style:UIBlurEffectStyle = .light, withDuration duration: TimeInterval = 1.0) {
        if #available(iOS 10.0, *) {
            let animator = UIViewPropertyAnimator(duration: duration, curve: .easeIn) {
                self.effect = UIBlurEffect(style: style)
            }

            animator.startAnimation()
        }else {
            // Fallback on earlier versions
            UIView.animate(withDuration: duration) {
                self.effect = UIBlurEffect(style: style)
            }
        }
    }

    func fadeOutEffect(withDuration duration: TimeInterval = 1.0) {
        if #available(iOS 10.0, *) {
            let animator = UIViewPropertyAnimator(duration: duration, curve: .linear) {
                self.effect = nil
            }

            animator.startAnimation()
            animator.fractionComplete = 1
        }else {
            // Fallback on earlier versions
            UIView.animate(withDuration: duration) {
                self.effect = nil
            }
        }
    }

}

이 요점확인 하여 예제 사용법을 찾을 수도 있습니다.


를 사용하여 UIViewPropertyAnimator아이폰 OS에서 작업이 11. 감사 보인다 유일한입니다!
LinusGeffarth

추가하는 것을 잊지 마세요 : import UIKit
Oleksandr

8

해결 방법- UIVisualEffectView컨테이너보기에 넣고 alpha해당 컨테이너의 속성을 변경 합니다. 이 접근 방식은 iOS 9에서 완벽하게 작동합니다. iOS 10에서는 더 이상 작동하지 않는 것 같습니다.


멋있는. 덕분에, 그 :)하려고합니다
LinusGeffarth

1
샘플 코드를 제공 할 수 있습니까? 이것은 작동하지 않는 것 같습니다.
cnotethegr8 2015

iOS 9에서 작동합니다
5hrp

@DerrickHunt 여기도 마찬가지입니다. 해결책을 찾았습니까?
damirstuhec

2
@damirstuhec 프로젝트가 iOS 10 전용 인 경우 새 UIViewPropertyAnimator 클래스를 사용하여 UIBlurView 강도를 애니메이션 할 수 있습니다. 이전 버전을 지원해야하는 경우 위의 코드를 사용하고 #available 키워드를 사용하여 10을 실행하는 장치에 UIViewPropertyAnimator를 사용할 수 있습니다. 도움이 되었기를 바랍니다.
Derrick Hunt

5

콘솔의 경고 외에 문제없이 시각 효과보기의 알파를 변경할 수 있습니다. 보기가 흐릿하지 않고 부분적으로 투명하게 나타날 수 있습니다. 그러나 애니메이션 중에 알파 만 변경하는 경우 일반적으로 문제가되지 않습니다.

이로 인해 앱이 충돌하거나 거부되지 않습니다. 실제 장치 (또는 8 개)에서 테스트하십시오. 외관과 성능에 만족한다면 괜찮습니다. Apple은 알파 값이 1 인 시각 효과보기만큼 보이거나 작동하지 않을 수 있다고 경고했습니다.


5

정적 기본 뷰의 스냅 샷을 찍고 블러 뷰의 불투명도를 건드리지 않고 페이드 인 및 페이드 아웃 할 수 있습니다. blurView의 ivar 가정 :

func addBlur() {
    guard let blurEffectView = blurEffectView else { return }

    //snapShot = UIScreen.mainScreen().snapshotViewAfterScreenUpdates(false)
    let snapShot = self.view.snapshotViewAfterScreenUpdates(false)
    view.addSubview(blurEffectView)
    view.addSubview(snapShot)

    UIView.animateWithDuration(0.25, animations: {
        snapShot.alpha = 0.0
    }, completion: { (finished: Bool) -> Void in
        snapShot.removeFromSuperview()
    } )
}

func removeBlur() {
    guard let blurEffectView = blurEffectView else { return }

    let snapShot = self.view.snapshotViewAfterScreenUpdates(false)
    snapShot.alpha = 0.0
    view.addSubview(snapShot)

    UIView.animateWithDuration(0.25, animations: {
        snapShot.alpha = 1.0
    }, completion: { (finished: Bool) -> Void in
        blurEffectView.removeFromSuperview()
        snapShot.removeFromSuperview()
    } )
}

좋은 아이디어도 있지만 블러 뷰 아래의 비 정적 (움직이는 / 애니메이션) 콘텐츠에는 잘 작동하지 않습니다.
LinusGeffarth

@LinusG. 글쎄, 애플은 블러 뷰 알파를 가지고 놀아서는 안된다고 말한다. CADisplayLink를 사용하여 기본보기의 스크린 샷을 캡처 한 다음 이미지보기 (아마도 실제 경량화)에서 렌더링하고 불투명도를 0으로 변경하면서 상단보기에 표시 할 수 있습니다. 가능하지만 많이 작업.
David H

1
이것은 (지금까지) 내가 iOS 10에서 원하는 것을 달성 할 수 있었던 유일한 방법이었습니다. 매우 어두운 흐림 효과로 전체 화면에서 모달로 페이드 인하는 것입니다. 감사!
Graham

3

UIVisualEffectView를 페이드 인하려면-ios10의 경우 UIViewPropertyAnimator를 사용하십시오.

    UIVisualEffectView *blurEffectView = [[UIVisualEffectView alloc] initWithEffect:nil];
    blurEffectView.frame = self.view.frame;
    blurEffectView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

    UIView *blackUIView = [[UIView alloc]initWithFrame:self.view.frame];
    [bacgroundImageView addSubview:blackUIView];
    [blackUIView addSubview:blurEffectView];
    UIViewPropertyAnimator *animator  = [[UIViewPropertyAnimator alloc] initWithDuration:4.f curve:UIViewAnimationCurveLinear animations:^{
        [blurEffectView setEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleDark]];
    }];

그런 다음 백분율을 설정할 수 있습니다

[animator setFractionComplete:percent];

ios9의 경우 알파 구성 요소를 사용할 수 있습니다.


2
질문에는 "objective-c"가 아니라 "swift"태그가 지정되어 있습니다. Swift에서 답변을 제공하세요. 감사!
Eric Aya

1
Objective C 코드에 감사드립니다. 나열된 다른 예가 많지 않기 때문에 편리하다는 것을 알았습니다.
아담웨어

2

UIVisualEffectView의 알파는 항상 1이어야합니다. 배경색의 알파를 설정하여 효과를 얻을 수 있다고 생각합니다.

출처 : https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIVisualEffectView/index.html


피터, 배경색의 알파 설정 방법을 설명해 주 시겠어요?
Boris Y.

@borisy colorWithAlphaComponent:UIColor인스턴스 에서 메서드를 사용합니다 . 그래도 배경색을 설정하여 동일한 효과를 얻는 방법을 모르겠습니다.
nemesis

배경 알파 성분을 변경하여 예상대로 작동하지 않습니다
Honghao 장

1

알파가 0 인 uiview를 만들고 그 하위 뷰로 blurview를 추가합니다. 그래서 애니메이션으로 모서리를 숨기거나 표시하거나 둥글게 할 수 있습니다.


1

나는 UIVisualEffectView및 내용에 대해 별도의 애니메이션을 사용하여 다음 솔루션으로 끝났습니다 . 이 viewWithTag()메서드를 사용 UIView하여 UIVisualEffectView.

let blurEffectView = UIVisualEffectView()
// Fade in
UIView.animateWithDuration(1) { self.blurEffectView.effect = UIBlurEffect(style: .Light) }    
UIView.animateWithDuration(1) { self.blurEffectView.viewWithTag(1)?.alpha = 1 }
// Fade out
UIView.animateWithDuration(1) { self.blurEffectView.effect = nil }    
UIView.animateWithDuration(1) { self.blurEffectView.viewWithTag(1)?.alpha = 0 }

알파를 변경하는 단일 애니메이션을 선호하지만 이것은 오류를 피하고 잘 작동하는 것 같습니다.


1

방금이 문제가 발생했고 해결 방법은 UIView에 UIVisualEffectsView를 수용하고 해당 UIView의 알파에 애니메이션을 적용하는 것이 었습니다.

알파가 1.0 이하로 변경 되 자마자 흰색으로 변하고 매우 부끄러워 보였다는 점을 제외하면 잘 작동했습니다. 이 문제를 해결하려면 UIView의 레이어 속성을 설정해야합니다.containerView.layer.allowsGroupOpacity = false 이렇게하면 흰색으로 깜박이지 않습니다.

이제 알파 속성을 사용하여 시각적 효과보기 및 기타 하위보기를 포함하는 UIView를 애니메이션화 / 페이드 아웃 할 수 있으며 그래픽 결함이나 경고 메시지 로깅에 대해 걱정할 필요가 없습니다.


0
_visualEffectView.contentView.alpha = 0;

UIVisualEffectView의 알파를 변경하려면 _visualEffectView의 contentView를 변경해야합니다. _visualEffectView의 알파를 변경하면 다음을 얻을 수 있습니다.

<UIVisualEffectView 0x7ff7bb54b490> is being asked to animate its opacity. This will cause the effect to appear broken until opacity returns to 1.

0

일반적으로 화면에 뷰 컨트롤러를 표시 할 때만 블러를 애니메이션하고 표시하는 뷰 컨트롤러를 흐리게 처리하고 싶습니다. 다음은이를 용이하게하기 위해 blur () 및 unblur ()를 뷰 컨트롤러에 추가하는 확장입니다.

extension UIViewController {

   func blur() {
       //   Blur out the current view
       let blurView = UIVisualEffectView(frame: self.view.frame)
       self.view.addSubview(blurView)
       UIView.animate(withDuration:0.25) {
           blurView.effect = UIBlurEffect(style: .light)
       }
   }

   func unblur() {
       for childView in view.subviews {
           guard let effectView = childView as? UIVisualEffectView else { continue }
           UIView.animate(withDuration: 0.25, animations: {
                effectView.effect = nil
           }) {
               didFinish in
               effectView.removeFromSuperview()
           }
       }
   }
}

물론 사용자가 효과 스타일을 선택하고, 지속 시간을 수정하고, 애니메이션이 완료 될 때 무언가를 호출하고, blur ()에서 추가 된 시각 효과보기에 태그를 지정하여이를 unblur ( ) 등이 있지만 지금까지 이러한 작업을 수행 할 필요성을 찾지 못했습니다. 이는 "불타고 잊어 버리는"유형의 작업 인 경향이 있기 때문입니다.


"사격 후 잊기"는 정말 공감합니다! Ha
LinusGeffarth

0

@cc의 답변에 따라 뷰를 흐리게 처리하도록 확장을 수정했습니다.

extension UIView {

    func blur () {
        // 현재 뷰를 흐리게합니다.
        let blurView = UIVisualEffectView (frame : self.bounds)
        self.addSubview (blurView)
        UIView.animate (withDuration : 0.25) {
            blurView.effect = UIBlurEffect (스타일 : .dark)
        }
    }

    func unblur () {
        for childView in subviews {
            guard let effectView = childView as? UIVisualEffectView else {계속}
            UIView.animate (withDuration : 2.5, 애니메이션 : {
                effectView.effect = nil
            }) {
                didFinish in
                effectView.removeFromSuperview ()
            }
        }
    }
}

0

@ Tel4tel 및 @cc 응답 개선, 여기에 매개 변수와 간단한 설명이있는 확장이 있습니다.

extension UIView {

    // Perform a blur animation in the whole view
    // Effect tone can be .light, .dark, .regular...
    func blur(duration inSeconds: Double, effect tone: UIBlurEffectStyle) {
        let blurView = UIVisualEffectView(frame: self.bounds)
        self.addSubview(blurView)
        UIView.animate(withDuration: inSeconds) {
            blurView.effect = UIBlurEffect(style: tone)
        }
    }

    // Perform an unblur animation in the whole view
    func unblur(duration inSeconds: Double) {
        for childView in subviews {
            guard let effectView = childView as? UIVisualEffectView else { continue 
        }
            UIView.animate(withDuration: inSeconds, animations: {
                effectView.effect = nil
            }){
                didFinish in effectView.removeFromSuperview()
            }
        }
    }
}

그럼 당신은 그것을처럼 사용할 수 있습니다 view.blur(duration: 5.0, effect: .light) 또는 view.unblur(duration: 3.0)

viewDidLoad()애니메이션을 재정의하므로 사용하지 마십시오 . 또한 시뮬레이터에서 실행할 때 애니메이션을 볼 수 있도록 그래픽을 더 높은 수준으로 전환합니다 (디버그> 그래픽 품질 재정의> 고품질).

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.