Criando uma vista de sobreposição de desfoque

Respostas:

552

Você pode usar UIVisualEffectViewpara alcançar esse efeito. Esta é uma API nativa que foi ajustada para desempenho e excelente duração da bateria, além de ser fácil de implementar.

Rápido:

//only apply the blur if the user hasn't disabled transparency effects
if !UIAccessibility.isReduceTransparencyEnabled {
    view.backgroundColor = .clear

    let blurEffect = UIBlurEffect(style: .dark)
    let blurEffectView = UIVisualEffectView(effect: blurEffect)
    //always fill the view
    blurEffectView.frame = self.view.bounds
    blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]

    view.addSubview(blurEffectView) //if you have more UIViews, use an insertSubview API to place it where needed
} else {
    view.backgroundColor = .black
}

Objetivo-C:

//only apply the blur if the user hasn't disabled transparency effects
if (!UIAccessibilityIsReduceTransparencyEnabled()) {
    self.view.backgroundColor = [UIColor clearColor];

    UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
    UIVisualEffectView *blurEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
    //always fill the view
    blurEffectView.frame = self.view.bounds;
    blurEffectView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

    [self.view addSubview:blurEffectView]; //if you have more UIViews, use an insertSubview API to place it where needed
} else {
    self.view.backgroundColor = [UIColor blackColor];
}

Se você estiver apresentando esse controlador de exibição de maneira modal para desfocar o conteúdo subjacente, será necessário definir o estilo de apresentação modal como Contexto Atual e definir a cor de plano de fundo para limpar, para garantir que o controlador de exibição subjacente permaneça visível assim que for apresentado no topo.

Jordan H
fonte
7
Como um esclarecimento ao insertSubView:belowSubView:comentário neste código, tenho usado o seguinte para definir o borrão como o fundo do ponto de vista:view.insertSubview(blurEffectView, atIndex: 0)
Michael Voccola
2
Com referência à resposta acima, é necessário verificar "if (! UIAccessibilityIsReduceTransparencyEnabled ())" ou podemos ignorar isso?
GKK
3
Se você está apresentando seu controlador de exibição, certifique-se de mudar modalPresentationStyle = .overCurrentContext juntamente com configuração cor de fundo tão clara
Shardul
3
Works Awesome !!! Precisa de uma única alteração: [self.view insertSubview: blurEffectView atIndex: 1];
Abhishek Thapliyal
2
No iOS 11, acho que não é necessário verificar manualmente UIAccessibilityIsReduceTransparencyEnabled().
Nate Whittaker
284

Imagem principal

Como essa imagem na captura de tela é estática, você pode usar a CIGaussianBlurpartir da imagem principal (requer iOS 6). Aqui está um exemplo: https://github.com/evanwdavis/Fun-with-Masks/blob/master/Fun%20with%20Masks/EWDBlurExampleVC.m

Lembre-se, isso é mais lento que as outras opções nesta página.

#import <QuartzCore/QuartzCore.h>

- (UIImage*) blur:(UIImage*)theImage
{   
    // ***********If you need re-orienting (e.g. trying to blur a photo taken from the device camera front facing camera in portrait mode)
    // theImage = [self reOrientIfNeeded:theImage];

    // create our blurred image
    CIContext *context = [CIContext contextWithOptions:nil];
    CIImage *inputImage = [CIImage imageWithCGImage:theImage.CGImage];

    // setting up Gaussian Blur (we could use one of many filters offered by Core Image)
    CIFilter *filter = [CIFilter filterWithName:@"CIGaussianBlur"];
    [filter setValue:inputImage forKey:kCIInputImageKey];
    [filter setValue:[NSNumber numberWithFloat:15.0f] forKey:@"inputRadius"];
    CIImage *result = [filter valueForKey:kCIOutputImageKey];

    // CIGaussianBlur has a tendency to shrink the image a little, 
    // this ensures it matches up exactly to the bounds of our original image
    CGImageRef cgImage = [context createCGImage:result fromRect:[inputImage extent]];

    UIImage *returnImage = [UIImage imageWithCGImage:cgImage];//create a UIImage for this function to "return" so that ARC can manage the memory of the blur... ARC can't manage CGImageRefs so we need to release it before this function "returns" and ends.
    CGImageRelease(cgImage);//release CGImageRef because ARC doesn't manage this on its own.

    return returnImage;

    // *************** if you need scaling
    // return [[self class] scaleIfNeeded:cgImage];
}

+(UIImage*) scaleIfNeeded:(CGImageRef)cgimg {
    bool isRetina = [[[UIDevice currentDevice] systemVersion] intValue] >= 4 && [[UIScreen mainScreen] scale] == 2.0;
    if (isRetina) {
        return [UIImage imageWithCGImage:cgimg scale:2.0 orientation:UIImageOrientationUp];
    } else {
        return [UIImage imageWithCGImage:cgimg];
    }
}

- (UIImage*) reOrientIfNeeded:(UIImage*)theImage{

    if (theImage.imageOrientation != UIImageOrientationUp) {

        CGAffineTransform reOrient = CGAffineTransformIdentity;
        switch (theImage.imageOrientation) {
            case UIImageOrientationDown:
            case UIImageOrientationDownMirrored:
                reOrient = CGAffineTransformTranslate(reOrient, theImage.size.width, theImage.size.height);
                reOrient = CGAffineTransformRotate(reOrient, M_PI);
                break;
            case UIImageOrientationLeft:
            case UIImageOrientationLeftMirrored:
                reOrient = CGAffineTransformTranslate(reOrient, theImage.size.width, 0);
                reOrient = CGAffineTransformRotate(reOrient, M_PI_2);
                break;
            case UIImageOrientationRight:
            case UIImageOrientationRightMirrored:
                reOrient = CGAffineTransformTranslate(reOrient, 0, theImage.size.height);
                reOrient = CGAffineTransformRotate(reOrient, -M_PI_2);
                break;
            case UIImageOrientationUp:
            case UIImageOrientationUpMirrored:
                break;
        }

        switch (theImage.imageOrientation) {
            case UIImageOrientationUpMirrored:
            case UIImageOrientationDownMirrored:
                reOrient = CGAffineTransformTranslate(reOrient, theImage.size.width, 0);
                reOrient = CGAffineTransformScale(reOrient, -1, 1);
                break;
            case UIImageOrientationLeftMirrored:
            case UIImageOrientationRightMirrored:
                reOrient = CGAffineTransformTranslate(reOrient, theImage.size.height, 0);
                reOrient = CGAffineTransformScale(reOrient, -1, 1);
                break;
            case UIImageOrientationUp:
            case UIImageOrientationDown:
            case UIImageOrientationLeft:
            case UIImageOrientationRight:
                break;
        }

        CGContextRef myContext = CGBitmapContextCreate(NULL, theImage.size.width, theImage.size.height, CGImageGetBitsPerComponent(theImage.CGImage), 0, CGImageGetColorSpace(theImage.CGImage), CGImageGetBitmapInfo(theImage.CGImage));

        CGContextConcatCTM(myContext, reOrient);

        switch (theImage.imageOrientation) {
            case UIImageOrientationLeft:
            case UIImageOrientationLeftMirrored:
            case UIImageOrientationRight:
            case UIImageOrientationRightMirrored:
                CGContextDrawImage(myContext, CGRectMake(0,0,theImage.size.height,theImage.size.width), theImage.CGImage);
                break;

            default:
                CGContextDrawImage(myContext, CGRectMake(0,0,theImage.size.width,theImage.size.height), theImage.CGImage);
                break;
        }

        CGImageRef CGImg = CGBitmapContextCreateImage(myContext);
        theImage = [UIImage imageWithCGImage:CGImg];

        CGImageRelease(CGImg);
        CGContextRelease(myContext);
    }

    return theImage;
}

Desfoque de pilha (Box + Gaussian)

  • StackBlur Isso implementa uma mistura de Box e Gaussian Blur. 7x mais rápido que o gaussiano não acelerado, mas não tão feio quanto o desfoque da caixa. Veja uma demonstração aqui (versão do plugin Java) ou aqui (versão JavaScript). Este algoritmo é usado no KDE e no Camera + e outros. Ele não usa o Accelerate Framework, mas é rápido.

Acelere o Framework

  • Na sessão “Implementando a interface do usuário envolvente no iOS” da WWDC 2013, a Apple explica como criar um fundo desfocado (às 14:30) e menciona um método applyLightEffectimplementado no código de exemplo usando Accelerate.framework.

  • GPUImage usa sombreadores OpenGL para criar borrões dinâmicos. Ele tem vários tipos de desfoque: GPUImageBoxBlurFilter, GPUImageFastBlurFilter, GaussianSelectiveBlur, GPUImageGaussianBlurFilter. Existe até um GPUImageiOSBlurFilter que "deve replicar completamente o efeito de desfoque fornecido pelo painel de controle do iOS 7" ( tweet , artigo ). O artigo é detalhado e informativo.

    - (UIImage *) blurryGPUImage: (UIImage *) imagem comBlurLevel: (NSInteger) blur {
        GPUImageFastBlurFilter * blurFilter = [GPUImageFastBlurFilter novo];
        blurFilter.blurSize = desfoque;
        UIImage * result = [blurFilter imageByFilteringImage: imagem];
        resultado de retorno;
    }

Outras coisas

Andy Matuschak disse no Twitter: "você sabe, muitos dos lugares em que parece que estamos fazendo isso em tempo real são estáticos com truques inteligentes".

No doubleencore.com, eles dizem que “descobrimos que um raio de desfoque de 10 pontos mais um aumento de 10 pontos na saturação imitam melhor o efeito de desfoque do iOS 7 na maioria das circunstâncias”.

Uma espiada nos cabeçalhos privados do SBFProceduralWallpaperView da Apple .

Finalmente, esse não é um borrão real, mas lembre-se de que você pode definir o rasterizationScale para obter uma imagem pixelizada: http://www.dimzzy.com/blog/2010/11/blur-effect-for-uiview/

Jano
fonte
Obrigado pela resposta! Um problema está resolvido. Mas temos mais um problema. Como obter uma imagem de capa no iOS 7. Se possível?
kondratyevdev
Se você quer saber como obter a imagem do papel de parede em segundo plano do seu telefone, não faz ideia neste momento. Não vi essa funcionalidade nas diferenças de API . Talvez ele use uma API privada.
Jano
Uma coisa que notei (e posso estar totalmente errado) é que o desfoque da Apple parece adicionar um pouco de saturação de cor também. Então, não acho que seja um simples borrão gaussiano.
Xtravar
Lembre-se o fator de escala ao retornar o UIImagecaso contrário ele vai maneira olhar muito grande em um dispositivo Retina ...
Stephen Darlington
Você sabe se esse efeito pode ser aplicado a um UITableViewCell sem prejudicar o desempenho?
Leonardo13
15

Decidi postar uma versão Objective-C escrita a partir da resposta aceita, apenas para fornecer mais opções nesta pergunta.

- (UIView *)applyBlurToView:(UIView *)view withEffectStyle:(UIBlurEffectStyle)style andConstraints:(BOOL)addConstraints
{
  //only apply the blur if the user hasn't disabled transparency effects
  if(!UIAccessibilityIsReduceTransparencyEnabled())
  {
    UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:style];
    UIVisualEffectView *blurEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
    blurEffectView.frame = view.bounds;

    [view addSubview:blurEffectView];

    if(addConstraints)
    {
      //add auto layout constraints so that the blur fills the screen upon rotating device
      [blurEffectView setTranslatesAutoresizingMaskIntoConstraints:NO];

      [view addConstraint:[NSLayoutConstraint constraintWithItem:blurEffectView
                                                       attribute:NSLayoutAttributeTop
                                                       relatedBy:NSLayoutRelationEqual
                                                          toItem:view
                                                       attribute:NSLayoutAttributeTop
                                                      multiplier:1
                                                        constant:0]];

      [view addConstraint:[NSLayoutConstraint constraintWithItem:blurEffectView
                                                       attribute:NSLayoutAttributeBottom
                                                       relatedBy:NSLayoutRelationEqual
                                                          toItem:view
                                                       attribute:NSLayoutAttributeBottom
                                                      multiplier:1
                                                        constant:0]];

      [view addConstraint:[NSLayoutConstraint constraintWithItem:blurEffectView
                                                       attribute:NSLayoutAttributeLeading
                                                       relatedBy:NSLayoutRelationEqual
                                                          toItem:view
                                                       attribute:NSLayoutAttributeLeading
                                                      multiplier:1
                                                        constant:0]];

      [view addConstraint:[NSLayoutConstraint constraintWithItem:blurEffectView
                                                       attribute:NSLayoutAttributeTrailing
                                                       relatedBy:NSLayoutRelationEqual
                                                          toItem:view
                                                       attribute:NSLayoutAttributeTrailing
                                                      multiplier:1
                                                        constant:0]];
    }
  }
  else
  {
    view.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.7];
  }

  return view;
}

As restrições podem ser removidas se você quiser, caso suporte apenas o modo retrato ou apenas adicionei um sinalizador a essa função para usá-las ou não.

valbu17
fonte
11
para pessoas novas (eu), uma maneira de chamar o método acima é: [self applyBlurToView: self.view withEffectStyle: UIBlurEffectStyleDark andConstraints: YES]; (obrigado NorthBlast)
tmr
14

Acho que não tenho permissão para postar o código, mas a postagem acima mencionando o código de exemplo da WWDC está correta. Aqui está o link: https://developer.apple.com/downloads/index.action?name=WWDC%202013

O arquivo que você está procurando é a categoria em UIImage e o método é applyLightEffect.

Como observei acima em um comentário, o Apple Blur tem saturação e outras coisas acontecendo além do desfoque. Um simples borrão não funciona ... se você deseja imitar o estilo deles.

xtravar
fonte
8
Esse link está quebrado. Aqui está o link correto: developer.apple.com/downloads/index.action?name=WWDC%202013
olivaresF
Note-se que este código exemplo requer Xcode 5.0 e iOS SDK 7.0 (que não foram divulgados publicamente até o momento)
Mike Gledhill
Obrigado pelo link fixo, no entanto, há alguns exemplos de código, qual deles contém a categoria UIImage relevante?
Leonardo
11
@Leonardo iOS_RunningWithASnap.zip
John Starr Dewar
11
... ou iOS_UIImageEffects.zip é mais especificamente exatamente isso.
precisa saber é o seguinte
9

Eu acho que a solução mais fácil para isso é substituir o UIToolbar, que desfoca tudo por trás dele no iOS 7. É bastante sorrateiro, mas é muito simples de implementar e rápido!

Você pode fazer isso com qualquer visualização, apenas faça uma subclasse em UIToolbarvez de UIView. Você pode até mesmo fazê-lo com um UIViewController's viewpropriedade, por exemplo ...

1) crie uma nova classe que seja uma "Subclasse de" UIViewControllere marque a caixa "Com XIB para interface do usuário".

2) Selecione View e vá para o inspetor de identidade no painel direito (alt-command-3). Mude a "Classe" para UIToolbar. Agora vá ao inspetor de atributos (alt-command-4) e altere a cor "Background" para "Clear Color".

3) Adicione uma subvisão à visualização principal e conecte-a a um IBOutlet na sua interface. Ligue backgroundColorView. Será algo parecido com isto, como uma categoria privada no .marquivo de implementação ( ).

@interface BlurExampleViewController ()
@property (weak, nonatomic) IBOutlet UIView *backgroundColorView;
@end

4) Vá para o .marquivo de implementação do controlador de exibição ( ) e altere o -viewDidLoadmétodo, da seguinte maneira:

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.view.barStyle = UIBarStyleBlack; // this will give a black blur as in the original post
    self.backgroundColorView.opaque = NO;
    self.backgroundColorView.alpha = 0.5;
    self.backgroundColorView.backgroundColor = [UIColor colorWithWhite:0.3 alpha:1];
}

Isso lhe dará uma visão cinza escura, que desfoca tudo por trás dela. Não é engraçado, não há desfocagem lenta da imagem principal, usando tudo o que está ao seu alcance fornecido pelo OS / SDK.

Você pode adicionar a visão deste controlador de visão a outra visão, da seguinte maneira:

[self addChildViewController:self.blurViewController];
[self.view addSubview:self.blurViewController.view];
[self.blurViewController didMoveToParentViewController:self];

// animate the self.blurViewController into view

Deixe-me saber se algo não estiver claro, terei prazer em ajudar!


Editar

O UIToolbar foi alterado na 7.0.3 para fornecer um efeito indesejável ao usar um desfoque colorido.

Nós costumávamos definir a cor usando barTintColor, mas se você estava fazendo isso antes, precisará configurar o componente alfa para menos de 1. Caso contrário, a sua barra de ferramentas do UITool será completamente opaca - sem desfoque.

Isso pode ser alcançado da seguinte forma: (tendo em mente selfuma subclasse de UIToolbar)

UIColor *color = [UIColor blueColor]; // for example
self.barTintColor = [color colorWithAlphaComponent:0.5];

Isso dará um tom azulado à visão borrada.

Sam
fonte
11
Não é mau homem. Eu usei essas três linhas em minha opinião: self.backgroundColorView.opaque = NO; self.backgroundColorView.alpha = 0.5; self.backgroundColorView.backgroundColor = [UIColor colorWithWhite:0.3 alpha:1];Mas o fundo não está desfocado, apenas produza um bom efeito. obrigado mesmo assim!
IgniteCoders
11
Não estou vendo nenhum borrão usando essa técnica. Ele apenas cria uma sobreposição colorida.
MusiGenesis
verifique se o alfa colorido da sobreposição é menor que 1. Você pode usar uma barra UITool sem o controlador de exibição, o que pode ser mais simples, dependendo do que você precisa.
Sam
truque arrumado. Eu converti minha visualização para a classe UIToolbar no storyboard, depois alterei o plano de fundo da visualização para limpar a cor. Deu um fundo branco borrado. Se você tornar alfa menor que 1, o efeito embaçado desaparecerá.
Badr
9

Aqui está uma implementação rápida no Swift usando o CIGaussianBlur:

func blur(image image: UIImage) -> UIImage {
    let radius: CGFloat = 20;
    let context = CIContext(options: nil);
    let inputImage = CIImage(CGImage: image.CGImage!);
    let filter = CIFilter(name: "CIGaussianBlur");
    filter?.setValue(inputImage, forKey: kCIInputImageKey);
    filter?.setValue("\(radius)", forKey:kCIInputRadiusKey);
    let result = filter?.valueForKey(kCIOutputImageKey) as! CIImage;
    let rect = CGRectMake(radius * 2, radius * 2, image.size.width - radius * 4, image.size.height - radius * 4)
    let cgImage = context.createCGImage(result, fromRect: rect);
    let returnImage = UIImage(CGImage: cgImage);

    return returnImage;
}
kev
fonte
7

Escala de desfoque personalizada

Você pode tentar UIVisualEffectView com a configuração personalizada como -

class BlurViewController: UIViewController {
    private let blurEffect = (NSClassFromString("_UICustomBlurEffect") as! UIBlurEffect.Type).init()

    override func viewDidLoad() {
        super.viewDidLoad()
        let blurView = UIVisualEffectView(frame: UIScreen.main.bounds)
        blurEffect.setValue(1, forKeyPath: "blurRadius")
        blurView.effect = blurEffect
        view.addSubview(blurView)
    }   
}

Saída: - para blurEffect.setValue(1...& blurEffect.setValue(2.. insira a descrição da imagem aqui insira a descrição da imagem aqui

Jack
fonte
3
Ele irá parar de funcionar se na próxima versão do iOS o nome desse parâmetro for alterado.
Ariel Bogdziewicz
@ArielBogdziewicz atualmente está trabalhando. atualizarei se houver alguma variação da API no wwdc.
Jack
Ummm ... não, você nunca deseja acessar APIs privadas. Eles são privados por um motivo. Eles mudarão, quebrarão e / ou a Apple rejeitará seu aplicativo. Use outro método, há bastante. Parabéns por encontrar o hack, mas não é recomendado.
N13 04/04/19
@ Jack Muito obrigado por esta resposta! É a única solução que encontrei para o meu problema: desfocar uma visão de acordo com a posição de outra visão. No entanto, ainda tenho outra pergunta. Existe uma maneira de adicionar vibração ao meu UIBlurEffect? Se sim, como? Preciso criar outra visualização para isso em cima do meu blurView? Eu tentei, mas sempre travava quando eu usava (NSClassFromString("_UICustomVibrancyEffect") as! UIVibrancyEffect.Type).init(). Realmente apreciaria alguma ajuda!
Moritz
@Moritz não tentou. Mas deve funcionar. Você pode tentar e verificar.
Jack
7

Aqui está uma maneira fácil de adicionar desfoque personalizado sem pechinchar com APIs privadas usando UIViewPropertyAnimator :

Primeiro, declare a propriedade da classe:

var blurAnimator: UIViewPropertyAnimator!

Em seguida, defina sua exibição de desfoque em viewDidLoad():

let blurEffectView = UIVisualEffectView()
blurEffectView.backgroundColor = .clear
blurEffectView.frame = view.bounds
blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
view.addSubview(blurEffectView)

blurAnimator = UIViewPropertyAnimator(duration: 1, curve: .linear) { [blurEffectView] in
    blurEffectView.effect = UIBlurEffect(style: .light)
}

blurAnimator.fractionComplete = 0.15 // set the blur intensity.    

Nota: Esta solução não é adequada para UICollectionView/ UITableViewcélulas

Adam Bardon
fonte
11
Esta é a única solução, que eu encontrei, se você deseja controlar a transparência do UIVisualEffectView.
Denis Kutlubaev
6

insira a descrição da imagem aqui

No Xcode, você pode fazer isso facilmente. Siga as etapas do xcode. Drage a visualização do efeito visual na sua visualização ou visualização de imagem.

Happy Coding :)

Mehedi Hasan
fonte
5

A resposta aceita está correta, mas falta uma etapa importante aqui, caso essa visualização - para a qual você deseja um fundo desfocado - seja apresentada usando

[self presentViewController:vc animated:YES completion:nil]

Por padrão, isso negará o desfoque, pois o UIKit remove a exibição do apresentador, que você está desfocando. Para evitar essa remoção, adicione esta linha antes da anterior

vc.modalPresentationStyle = UIModalPresentationOverFullScreen;

Ou use outros Overestilos.

Aleksandar Vacić
fonte
3

OBJETIVO-C

UIVisualEffect *blurEffect;
blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
UIVisualEffectView *visualEffectView;
visualEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
visualEffectView.frame = self.accessImageView.bounds;
[self.accessImageView addSubview:visualEffectView];

SWIFT 3.0

let blurEffect = UIBlurEffect(style: UIBlurEffectStyle.dark)
let blurEffectView = UIVisualEffectView(effect: blurEffect)
blurEffectView.frame = view.bounds
blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
view.addSubview(blurEffectView)

from: https://stackoverflow.com/a/24083728/4020910

BennyTheNerd
fonte
2

Usando UIImageEffects

Para quem quer mais controle, você pode usar o UIImageEffectscódigo de exemplo da Apple .

Você pode copiar o código UIImageEffectsda Biblioteca de desenvolvedores da Apple: Desfocar e colorir uma imagem

E aqui está como aplicá-lo:

#import "UIImageEffects.h"
...

self.originalImageView.image = [UIImageEffects imageByApplyingLightEffectToImage:[UIImage imageNamed:@"yourImage.png"]];
Zakaria Braksa
fonte
Como faço para usar isso em rápida
devjme
2
func blurBackgroundUsingImage(image: UIImage)
{
    var frame                   = CGRectMake(0, 0, self.view.frame.width, self.view.frame.height)
    var imageView               = UIImageView(frame: frame)
    imageView.image             = image
    imageView.contentMode       = .ScaleAspectFill
    var blurEffect              = UIBlurEffect(style: .Light)
    var blurEffectView          = UIVisualEffectView(effect: blurEffect)
    blurEffectView.frame        = frame
    var transparentWhiteView    = UIView(frame: frame)
    transparentWhiteView.backgroundColor = UIColor(white: 1.0, alpha: 0.30)
    var viewsArray              = [imageView, blurEffectView, transparentWhiteView]

    for index in 0..<viewsArray.count {
        if let oldView = self.view.viewWithTag(index + 1) {
            var oldView         = self.view.viewWithTag(index + 1)
            // Must explicitly unwrap oldView to access its removeFromSuperview() method as of Xcode 6 Beta 5
            oldView!.removeFromSuperview()
        }
        var viewToInsert        = viewsArray[index]
        self.view.insertSubview(viewToInsert, atIndex: index + 1)
        viewToInsert.tag        = index + 1
    }
}
Durul Dalkanat
fonte
1

Descobri isso por acidente, me dá ótimos resultados (quase duplicados com os da Apple) e usa a estrutura Acceleration. - http://pastebin.com/6cs6hsyQ * Não escrito por mim

Jake
fonte
8
Na verdade, é um código da Apple da WWDC 2013 com direitos autorais incorretos.
Shmidt
os códigos da WWDC não são protegidos por direitos autorais e o acesso é permitido apenas a membros com assinaturas pagas?
SAFAD 26/04
11
Possivelmente, mas o código acima encontrei usando o Google. Não alterei os direitos autorais e presumi (e ainda assumo) que ele possui a reivindicação de direitos autorais correta. Se a Apple discordar, eles devem se esforçar para derrubá-lo. Eu não vejo a relevância.
Jake
1

Esta resposta é baseada na excelente resposta anterior de Mitja Semolic . Eu o convertei para o swift 3, adicionei uma explicação para o que está acontecendo nos comentários, o tornei uma extensão de um UIViewController para que qualquer VC pudesse chamá-lo à vontade, adicionei uma visão sem desfocagem para mostrar a aplicação seletiva e adicionei um bloco de conclusão para que o controlador de visualização de chamada pode fazer o que quiser ao concluir o desfoque.

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

Confirmei que funciona com iOS 10.3.1 e iOS 11

James Jordan Taylor
fonte
1

Um complemento importante à resposta de @ Joey

Isto aplica-se a uma situação em que pretende apresentar a-fundo desfocado UIViewControllercom UINavigationController.

// suppose you've done blur effect with your presented view controller
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController];

// this is very important, if you don't do this, the blur effect will darken after view did appeared
// the reason is that you actually present navigation controller, not presented controller
// please note it's "OverFullScreen", not "OverCurrentContext"
nav.modalPresentationStyle = UIModalPresentationOverFullScreen;

UIViewController *presentedViewController = [[UIViewController alloc] init]; 
// the presented view controller's modalPresentationStyle is "OverCurrentContext"
presentedViewController.modalPresentationStyle = UIModalPresentationOverCurrentContext;

[presentingViewController presentViewController:nav animated:YES completion:nil];

Aproveitar!

steveluoxin
fonte
1

Versão Swift 3 da resposta de Kev para retornar a imagem borrada -

func blurBgImage(image: UIImage) -> UIImage? {
        let radius: CGFloat = 20;
        let context = CIContext(options: nil);
        let inputImage = CIImage(cgImage: image.cgImage!);
        let filter = CIFilter(name: "CIGaussianBlur");
        filter?.setValue(inputImage, forKey: kCIInputImageKey);
        filter?.setValue("\(radius)", forKey:kCIInputRadiusKey);

        if let result = filter?.value(forKey: kCIOutputImageKey) as? CIImage{

            let rect = CGRect(origin: CGPoint(x: radius * 2,y :radius * 2), size: CGSize(width: image.size.width - radius * 4, height: image.size.height - radius * 4))

            if let cgImage = context.createCGImage(result, from: rect){
                return UIImage(cgImage: cgImage);
                }
        }
        return nil;
    }
Pramod
fonte
1

Código 2019

Aqui está um exemplo mais completo usando a incrível técnica @AdamBardon.

@IBDesignable class ButtonOrSomethingWithBlur: UIButton {

    var ba: UIViewPropertyAnimator?
    private lazy var blurry: BlurryBall = { return BlurryBall() }()

    override func didMoveToSuperview() {
        super.didMoveToSuperview()

        // Setup the blurry ball.  BE SURE TO TEARDOWN.
        // Use superb trick to access the internal guassian level of Apple's
        // standard gpu blurrer per stackoverflow.com/a/55378168/294884

        superview?.insertSubview(blurry, belowSubview: self)
        ba = UIViewPropertyAnimator(duration:1, curve:.linear) {[weak self] in
            // note, those duration/curve values are simply unusued
            self?.blurry.effect = UIBlurEffect(style: .extraLight)
        }
        ba?.fractionComplete = live.largeplaybutton_blurfactor
    }

    override func willMove(toSuperview newSuperview: UIView?) {

        // Teardown for the blurry ball - critical

        if newSuperview == nil { print("safe teardown")
            ba?.stopAnimation(true)
            ba?.finishAnimation(at: .current)
        }
    }

    override func layoutSubviews() { super.layoutSubviews()
        blurry.frame = bounds, your drawing frame or whatever
    }

{Além disso: como uma questão geral de engenharia do iOS, didMoveToWindowpode ser mais adequado para você do quedidMoveToSuperview . Em segundo lugar, você pode usar outra maneira de desmontar, mas a desmontagem são as duas linhas de código mostradas lá.}

BlurryBallé apenas um UIVisualEffectView. Observe as entradas para uma visualização de efeitos visuais. Se você precisar de cantos arredondados ou qualquer outra coisa, faça-o nesta classe.

class BlurryBall: UIVisualEffectView {

    override init(effect: UIVisualEffect?) { super.init(effect: effect)
        commonInit() }

    required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder)
        commonInit() }

    private func commonInit() {
        clipsToBounds = true
        backgroundColor = .clear
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        layer.cornerRadius = bounds.width / 2
    }
}
Fattie
fonte
0

A Apple forneceu uma extensão para a classe UIImage chamada UIImage + ImageEffects.h. Nesta classe, você tem os métodos desejados para desfocar sua visualização

Preet
fonte
11
Você pode compartilhar mais informações sobre esses métodos?
Mike Laren
0

Aqui está o código Swift 2.0 para a solução fornecida na resposta aceita :

    //only apply the blur if the user hasn't disabled transparency effects
    if !UIAccessibilityIsReduceTransparencyEnabled() {
        self.view.backgroundColor = UIColor.clearColor()

        let blurEffect = UIBlurEffect(style: UIBlurEffectStyle.Dark)
        let blurEffectView = UIVisualEffectView(effect: blurEffect)
        //always fill the view
        blurEffectView.frame = self.view.bounds
        blurEffectView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]

        self.view.addSubview(blurEffectView) //if you have more UIViews, use an insertSubview API to place it where needed
    } else {
        self.view.backgroundColor = UIColor.blackColor()
    }
RaptoX
fonte
0

Se adicionar uma visão de desfoque escuro para o tableView, isso fará com que seja lindamente:

tableView.backgroundColor = .clear
let blurEffect = UIBlurEffect(style: .dark)
let blurEffectView = UIVisualEffectView(effect: blurEffect)
blurEffectView.frame = tableView.bounds
blurEffectView.autoresizingMask = [.flexibleHeight, .flexibleWidth]


// Assigning blurEffectView to backgroundView instead of addSubview to tableView makes tableView cell not blocked by blurEffectView 
tableView.backgroundView = blurEffectView
tchau
fonte
0

Você pode fazer seu Background Blur diretamente usando "Visual Effect Effect with Blur" e "Visual Effect View with Blur and Vibrancy".

Tudo o que você precisa fazer para tornar o Blur Background no aplicativo iOS é ...

  1. Vá e procure "Visualização de efeito visual com desfoque" na biblioteca de objetos

Etapa 1 Imagem

  1. Arraste o "Visual Effect View with Blur" no Storyboard e configure-o ...

Etapa 2 Imagem

  1. Finalmente ... Você faz o seu App Background Blur!

Layout da aplicação antes de clicar em qualquer botão!

Visualização do aplicativo após clicar no botão, o que torna todo o fundo do aplicativo desfocado!

Conheça Patel
fonte
0

Caso isso ajude alguém, aqui está uma extensão rápida que criei com base na resposta de Jordan H. Está escrita no Swift 5 e pode ser usada no Objetivo C.

extension UIView {

    @objc func blurBackground(style: UIBlurEffect.Style, fallbackColor: UIColor) {
        if !UIAccessibility.isReduceTransparencyEnabled {
            self.backgroundColor = .clear

            let blurEffect = UIBlurEffect(style: style)
            let blurEffectView = UIVisualEffectView(effect: blurEffect)
            //always fill the view
            blurEffectView.frame = self.self.bounds
            blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]

            self.insertSubview(blurEffectView, at: 0)
        } else {
            self.backgroundColor = fallbackColor
        }
    }

}

NOTA: Se você deseja desfocar o fundo de um UILabel sem afetar o texto, crie um UIView de contêiner, adicione o UILabel ao UIView de contêiner como uma subvisão, defina backgroundColor do UILabel como UIColor.clear e chame blurBackground (style : UIBlurEffect.Style, fallbackColor: UIColor) no contêiner UIView. Aqui está um exemplo rápido disso escrito em Swift 5:

let frame = CGRect(x: 50, y: 200, width: 200, height: 50)
let containerView = UIView(frame: frame)
let label = UILabel(frame: frame)
label.text = "Some Text"
label.backgroundColor = UIColor.clear
containerView.addSubview(label)
containerView.blurBackground(style: .dark, fallbackColor: UIColor.black)
Tyler Wood
fonte
-1

Swift 4:

Para adicionar uma sobreposição ou a janela pop-up Você também pode usar a Container View com a qual você obtém um View Controller gratuito (você obtém a Container View da paleta / biblioteca de objetos usuais)

Passos:

Tenha uma View (ViewForContainer na foto) que contenha essa Container View, para escurecê-la quando o conteúdo da Container View for exibido. Conecte a tomada dentro do primeiro View Controller

Ocultar esta visualização quando o 1º VC for carregado

Exibir quando o botão é clicado, insira a descrição da imagem aqui

Para escurecer essa exibição quando o conteúdo da exibição de contêiner for exibido, defina o plano de fundo das visualizações como preto e a opacidade para 30%

Adicionei uma resposta à criação da exibição popview em outra pergunta do Stackoverflow https://stackoverflow.com/a/49729431/5438240

Naishta
fonte
-3

Resposta simples é Adicione uma subvisão e mude de alfa.

UIView *mainView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
UIView *subView = [[UIView alloc] initWithFrame:popupView.frame];
UIColor * backImgColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"blue_Img.png"]];
subView.backgroundColor = backImgColor;
subView.alpha = 0.5;
[mainView addSubview:subView];
Sohail
fonte