ios objective-c ios8 uivisualeffectview uiblureffect

ios - Menos desenfoque con `Visual Effect View with Blur`?



objective-c ios8 (6)

El título prácticamente lo pregunta todo ...

Estoy jugando con la Vista de Visual Effect View with Blur iOS8 Visual Effect View with Blur . Se trata de un UIImageView que muestra una foto de fondo seleccionable por el usuario. La vista que se coloca en el ContentView en sí es mi propia vista personalizada, muestra un tipo de gráfico / calendario. La mayor parte de dicho gráfico de calendario es transparente. El desenfoque que se aplica a la foto detrás de él es muy pesado. Me gustaría dejar pasar más detalles. Pero Apple solo parece dar tres valores enlatados:

typedef enum { UIBlurEffectStyleExtraLight, UIBlurEffectStyleLight, UIBlurEffectStyleDark } UIBlurEffectStyle;

He monjeado con diferentes alfas y colores de fondo de UIVisualEffectView (aunque la documentación advierte contra eso), pero eso no hace más que empeorar las cosas.


Agregue un BlurEffectView a una vista con alfa <1 de view

func addBlurEffectView() -> Void { if !UIAccessibilityIsReduceTransparencyEnabled() { let viewContainer = UIView() viewContainer.frame = self.view.bounds viewContainer.alpha = 0.5 let blurEffect = UIBlurEffect(style: .dark) let blurEffectView = UIVisualEffectView(effect: blurEffect) blurEffectView.layer.zPosition = -0.5; blurEffectView.frame = self.view.bounds; blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight] viewContainer.addSubview(blurEffectView) self.view.addSubview(viewContainer) self.view.sendSubview(toBack: viewContainer) } }


Es una pena que Apple no haya proporcionado ninguna opción para el efecto de desenfoque. Pero esta solución funcionó para mí: animar el efecto de desenfoque y pausarlo antes de completarlo.

func blurEffectView(enable enable: Bool) { let enabled = self.blurView.effect != nil guard enable != enabled else { return } switch enable { case true: let blurEffect = UIBlurEffect(style: .ExtraLight) UIView.animateWithDuration(1.5) { self.blurView.effect = blurEffect } self.blurView.pauseAnimation(delay: 0.3) case false: self.blurView.resumeAnimation() UIView.animateWithDuration(0.1) { self.blurView.effect = nil } } }

y las extensiones UIView para pausar (con un retraso) y reanudar la animación de la vista

extension UIView { public func pauseAnimation(delay delay: Double) { let time = delay + CFAbsoluteTimeGetCurrent() let timer = CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault, time, 0, 0, 0, { timer in let layer = self.layer let pausedTime = layer.convertTime(CACurrentMediaTime(), fromLayer: nil) layer.speed = 0.0 layer.timeOffset = pausedTime }) CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, kCFRunLoopCommonModes) } public func resumeAnimation() { let pausedTime = layer.timeOffset layer.speed = 1.0 layer.timeOffset = 0.0 layer.beginTime = layer.convertTime(CACurrentMediaTime(), fromLayer: nil) - pausedTime } }


Esta respuesta se basa en la excelente respuesta anterior de Mitja Semolic . Lo convertí en swift 3, agregué una explicación a lo que sucedía en los comentarios, lo convertí en una extensión de un UIViewController para que cualquier VC lo pueda llamar a voluntad, agregué una vista no difuminada para mostrar la aplicación selectiva y agregué un bloque de finalización para que el controlador de vista llamante puede hacer lo que quiera al completar el desenfoque.

import UIKit //This extension implements a blur to the entire screen, puts up a HUD and then waits and dismisses the view. extension UIViewController { func blurAndShowHUD(duration: Double, message: String, completion: @escaping () -> Void) { //with completion block //1. Create the blur effect & the view it will occupy let blurEffect = UIBlurEffect(style: UIBlurEffectStyle.light) let blurEffectView = UIVisualEffectView()//(effect: blurEffect) blurEffectView.frame = self.view.bounds blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight] //2. Add the effect view to the main view self.view.addSubview(blurEffectView) //3. Create the hud and add it to the main view let hud = HudView.getHUD(view: self.view, withMessage: message) self.view.addSubview(hud) //4. Begin applying the blur effect to the effect view UIView.animate(withDuration: 0.01, animations: { blurEffectView.effect = blurEffect }) //5. Halt the blur effects application to achieve the desired blur radius self.view.pauseAnimationsInThisView(delay: 0.004) //6. Remove the view (& the HUD) after the completion of the duration DispatchQueue.main.asyncAfter(deadline: .now() + duration) { blurEffectView.removeFromSuperview() hud.removeFromSuperview() self.view.resumeAnimationsInThisView() completion() } } } extension UIView { public func pauseAnimationsInThisView(delay: Double) { let time = delay + CFAbsoluteTimeGetCurrent() let timer = CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault, time, 0, 0, 0, { timer in let layer = self.layer let pausedTime = layer.convertTime(CACurrentMediaTime(), from: nil) layer.speed = 0.0 layer.timeOffset = pausedTime }) CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer, CFRunLoopMode.commonModes) } public func resumeAnimationsInThisView() { let pausedTime = layer.timeOffset layer.speed = 1.0 layer.timeOffset = 0.0 layer.beginTime = layer.convertTime(CACurrentMediaTime(), from: nil) - pausedTime } }

Confirmé que funciona tanto con iOS 10.3.1 como con iOS 11


Esto funciona para mí

Puse UIVisualEffectView en una UIView antes de agregar a mi vista.

Hago que esta función sea más fácil de usar. Puede usar esta función para hacer borrosa cualquier área en su vista.

func addBlurArea(area: CGRect, style: UIBlurEffectStyle) { let effect = UIBlurEffect(style: style) let blurView = UIVisualEffectView(effect: effect) let container = UIView(frame: area) blurView.frame = CGRect(x: 0, y: 0, width: area.width, height: area.height) container.addSubview(blurView) container.alpha = 0.8 self.view.insertSubview(container, atIndex: 1) }

Por ejemplo, puede hacer borrosa toda su vista llamando:

addBlurArea(self.view.frame, style: UIBlurEffectStyle.Dark)

Puedes cambiar Dark a tu estilo de desenfoque deseado y 0.8 al valor alpha deseado


La razón por la que está recibiendo un borroso intenso es que el estilo del efecto de desenfoque afecta el nivel de brillo de la imagen, no la cantidad de desenfoque aplicado.

Desafortunadamente, aunque Apple claramente tiene la capacidad de controlar la cantidad de desenfoque aplicado mediante programación, intente arrastrar lentamente en la plataforma de lanzamiento para ver la transición de difuminado de Spotlight. No veo ninguna API pública para pasar una cantidad de desenfoque a UIBlurEffect .

Esta publicación afirma que ajustar el color de fondo alfa generará la cantidad de desenfoque. Merece la pena intentarlo, pero no veo dónde está documentado: ¿Cómo se desvanece un UIVisualEffectView y / o UIBlurEffect dentro y fuera?


Sí tu puedes.

Aquí hay un ejemplo de UIImageView con efecto de desenfoque. Recuerde agregar una imagen al UIImageView.

Ajuste la cantidad de desenfoque con blurEffectView.alpha = 0.8 (de 0 a 1)

import UIKit class BlurEffectImageView: UIImageView { override func awakeFromNib() { addBlurEffect() super.awakeFromNib() } private func addBlurEffect(){ let blurEffect = UIBlurEffect(style: .light) let blurEffectView = UIVisualEffectView(effect: blurEffect) blurEffectView.alpha = 0.8 blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight] blurEffectView.translatesAutoresizingMaskIntoConstraints = false addSubview(blurEffectView) NSLayoutConstraint(item: blurEffectView, attribute: .centerX, relatedBy: .equal, toItem: self, attribute: .centerX, multiplier: 1.0, constant: 0).isActive = true NSLayoutConstraint(item: blurEffectView, attribute: .centerY, relatedBy: .equal, toItem: self, attribute: .centerY, multiplier: 1.0, constant: 0).isActive = true NSLayoutConstraint(item: blurEffectView, attribute: .height, relatedBy: .equal, toItem: self, attribute: .height, multiplier: 1.0, constant: 0).isActive = true NSLayoutConstraint(item: blurEffectView, attribute: .width, relatedBy: .equal, toItem: self, attribute: .width, multiplier: 1.0, constant: 0).isActive = true }

}