Как постепенно исчезнуть 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.