UIVisualEffectViewやUIBlurEffectをフェードインまたはフェードアウトするにはどうすればよいですか?


92

UIBlurEffectをイン/アウトしてUIVisualEffectsViewをフェードインしたい:

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

で呼び出される関数内で通常のアニメーションを使用しUIButtonてフェードインします。フェードアウトと同じですが、.alpha = 0hidden = 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.アニメーションブロック内でblurEffectをblurEffectViewに割り当てます。3. blurEffectView.alphaの調整の代わりに、「blurEffectからblurEffectViewへの割り当て」をアニメーション化します。**初期値を割り当ててnilにしてから追加し直しても、エラーが表示されます。したがって、エラーを防ぐための鍵は、アニメーションブロックまで、エフェクトを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 2015年

すごい!あなたが言ったように、しかし、iOS 8では動作しません:/
LinusGeffarth '11

まあ、まさに私が上で書いたもののためです。とにかく今それを承認しました。@jpros
LinusGeffarth

10
エフェクトをnilに設定して、かなり「ぼかす」こともできます
jpros

1
@jpros「ぼかし」の意味を説明していただけませんか?
ndmeiri 2016年

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

を設定するeffectnil、アニメーションの最後に(わかりやすくするために)「素敵なフラッシュ」alpha0作成されますが、を設定すると、スムーズな移行が作成されます。

(構文エラーがあれば教えてください... obj-cで記述します。)


あなたの貢献をありがとう。私はあなたの要点を理解します。エラーは私のためにすでに解決されていますw /正確にあなたが言ったとおりです:)
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
            }
        }
    }

}

この要点を確認して、使用例を見つけることもできます。


UIViewPropertyAnimatoriOS 11で動作するように見えるのは、を使用することだけです。これをありがとう!
LinusGeffarth 2017

追加することを忘れないでください:UIKitのインポート
Oleksandr

8

ただの回避策- UIVisualEffectViewコンテナービューに入れalpha、そのコンテナーのプロパティを変更します。このアプローチは、iOS 9では完全に機能します。iOS10では機能しなくなったようです。


涼しい。ありがとう、それを試してみます:)
LinusGeffarth 2015

1
サンプルコードを提供できますか?これは機能していないようです。
cnotethegr8 2015年

iOSの9で私の作品
5hrp

@DerrickHunt同じです。解決策は見つかりましたか?
damirstuhec 2016

2
@damirstuhecプロジェクトがiOS 10のみの場合、新しいUIViewPropertyAnimatorクラスを使用してUIBlurViewの強度をアニメーション化できます。古いバージョンをサポートする必要がある場合は、上記のコードと#availableキーワードを使用して、10を実行しているデバイスにUIViewPropertyAnimatorを使用できます。
デリックハント

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 2015

@LinusG。まあ、アップルはぼかしビューのアルファで遊んではいけないと言っています。CADisplayLinkを使用してベースビューのスクリーンショットを取得し、それらをイメージビュー(おそらく実際に作成したもの-本当に軽量)にレンダリングして、不透明度を0に変更しながらそれらをトップビューに表示できます。可能ですが、多くの作業。
デビッドH

1
これが(これまでのところ)私がiOS 10で望んでいたことを実現する唯一の方法でした-非常に暗いぼかし効果で、モーダルをフルスクリーンでフェードインします。ありがとう!
グラハム

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コードをありがとう。他の例はほとんどリストされていなかったので、便利だと思いました。
Adam Ware

2

UIVisualEffectViewのアルファは常に1である必要があります。背景色のアルファを設定することで効果を実現できると思います。

ソース:https : //developer.apple.com/library/ios/documentation/UIKit/Reference/UIVisualEffectView/index.html


ピーター、背景色のアルファの設定方法を教えてください。
Boris Y.

@borisy colorWithAlphaComponent:UIColorインスタンスでメソッドを使用します。ただし、背景色を設定して同じ効果を得る方法はわかりません。
宿敵

背景のアルファコンポーネントを変更すると、期待どおりに機能しない
Honghao Zhang

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

私はこの問題を抱えていて、それを回避する方法は、UIVisualEffectsViewをUIViewに格納し、そのUIViewのアルファをアニメーション化することでした。

これはうまくいきましたが、アルファが1.0未満に変更されるとすぐに、真っ白に変わり、非常に不快に見えました。containerView.layer.allowsGroupOpacity = falseこれを回避するには、UIViewのレイヤープロパティを設定する必要があります。これにより、白く点滅しなくなります。

これで、alphaプロパティを使用して、視覚効果ビューとその他のサブビューを含む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( )などですが、これは「ファイアアンドフォーゲット」タイプの操作になる傾向があるため、これまでこれらのことを実行する必要があるとは思いませんでした。


「火と忘れ」はとても親切です!ハ
LinusGeffarth

0

@ccの回答に基づいて、ビューをぼかすように拡張機能を変更しました

拡張UIView {

    func blur(){
        //現在のビューをぼかします
        let letView = UIVisualEffectView(frame:self.bounds)
        self.addSubview(blurView)
        UIView.animate(withDuration:0.25){
            blurView.effect = UIBlurEffect(style:.dark)
        }
    }

    func unblur(){
        サブビューのchildViewの場合{
            ガードさせますeffectView = childView as?UIVisualEffectView else {続行}
            UIView.animate(withDuration:2.5、animations:{
                effectView.effect = nil
            }){
                終わりました
                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.