Как постепенно исчезнуть UIVisualEffectView и / или UIBlurEffect?

Я хочу исчезнуть UIVisualEffectsView с UIBlurEffect и выходить:

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 и исчезнуть, но безуспешно

15 ответов

Решение

Я думаю, что это новое в iOS9, но теперь вы можете установить эффект UIVisualEffectView внутри блока анимации:

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

Установите это nil удалять.

ОЧЕНЬ ВАЖНО - при тестировании этого на симуляторе убедитесь, что для настройки качества графики вашего симулятора установлено высокое качество, чтобы это работало.

В документации Apple (в настоящее время) говорится...

При использовании класса 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.)

Вот решение, которое я выбрал, которое работает на iOS10 и более ранних версиях с использованием Swift 3

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
            }
        }
    }

}

Вы также можете проверить эту суть, чтобы найти пример использования.

Просто обходной путь - поставить UIVisualEffectView в контейнер просмотра и изменения alpha свойство для этого контейнера. Этот подход прекрасно работает для меня в iOS 9. Кажется, он больше не работает в iOS 10.

Вы можете сделать снимок статического базового вида и постепенно увеличивать и уменьшать его, не касаясь непрозрачности вида размытия. Предполагая, что ivar blurView:

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()
    } )
}

Вы можете изменить альфа-канал представления визуальных эффектов без каких-либо проблем, кроме предупреждения в консоли. Представление может выглядеть просто частично прозрачным, а не размытым. Но обычно это не проблема, если вы просто меняете альфа во время анимации.

Ваше приложение не будет зависать или отклоняться из-за этого. Проверьте это на реальном устройстве (или на восьми). Если вы довольны тем, как это выглядит и работает, это нормально. Apple просто предупреждает вас, что она может не выглядеть или работать так же, как представление с визуальными эффектами со значением альфа 1.

Если вы хотите добавить вам 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 вы можете использовать альфа-компонент

Альфа UIVisualEffectView всегда должна быть равна 1. Я думаю, что вы можете добиться эффекта, установив альфа цвета фона.

Источник: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIVisualEffectView/index.html

У меня просто была эта проблема, и я нашел способ разместить UIVisualEffectsView в UIView и анимировать альфа этого UIView.

Это работало хорошо, за исключением того, что, как только альфа изменилась ниже 1,0, она превратилась в сплошной белый и выглядела очень резкой. Чтобы обойти это, вы должны установить свойство layer UIView containerView.layer.allowsGroupOpacity = false и это предотвратит его мигание белым.

Теперь вы можете анимировать / исчезать UIView, содержащий представление визуальных эффектов и любые другие подпредставления, используя его альфа-свойство, и вам не нужно беспокоиться о каких-либо графических сбоях или регистрации предупреждающего сообщения.

Я закончил со следующим решением, используя отдельные анимации для 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 }

Я бы предпочел единственную анимацию, изменяющую альфу, но это позволяет избежать ошибки и, похоже, работает так же хорошо.

Я делаю uiview, который альфа равен 0, и добавляю blurview как подпредставление этого. Так что я могу скрыть / показать или закруглить углы с помощью анимации.

Основываясь на ответе @cc, я изменил его расширение, чтобы размыть вид

расширение UIView {

    func blur() {
        // Размываем текущий вид
        let blurView = UIVisualEffectView(frame: self.bounds)
        self.addSubview(blurView)
        UIView.animate(withDuration:0,25) {
            blurView.effect = UIBlurEffect(style: .dark)
        }
    }

    func unblur() {
        для childView в подпредставлениях {
            охранник пусть effectView = childView как? UIVisualEffectView else { continue }
            UIView.animate(withDuration: 2.5, анимации: {
                effectView.effect = nil
            }) {
                сделал финиш в
                effectView.removeFromSuperview()
            }
        }
    }
}

Улучшение отклика @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() как это переопределит анимацию. Кроме того, при работе на симуляторе поверните графику на более высокий уровень, чтобы увидеть анимацию (Отладка> Переопределение качества графики> Высокое качество).

Обычно я хочу анимировать размытие только тогда, когда я представляю контроллер представления поверх экрана и хочу размыть представление контроллера представления. Вот расширение, которое добавляет 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(), чтобы гарантировать, что он будет удален только после отмены размытия () и т. д., но я до сих пор не нашел необходимости делать эти вещи, поскольку это, как правило, операция типа "забей и забудь".

_visualEffectView.contentView.alpha = 0;

Чтобы изменить альфа UIVisualEffectView, вы должны изменить contentView _visualEffectView. Если вы измените альфа _visualEffectView, вы получите это

<UIVisualEffectView 0x7ff7bb54b490> is being asked to animate its opacity. This will cause the effect to appear broken until opacity returns to 1.
Другие вопросы по тегам