ios qual Criando uma visualização de sobreposição de desfoque



modo retrato iphone 8 (18)

No aplicativo Música do novo iOS, podemos ver uma capa de álbum por trás de uma visualização que a embaça.

Como algo assim pode ser realizado? Eu li a documentação, mas não encontrei nada lá.


Answer #1

Eu acho que a solução mais fácil para isso é substituir o UIToolbar, que embaçava tudo no iOS 7. É bem sorrateiro, mas é muito simples de implementar e rápido!

Você pode fazer isso com qualquer visão, apenas torná-la uma subclasse de UIToolbar invés de UIView . Você pode até fazer isso com a propriedade view UIViewController , por exemplo ...

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

2) Selecione a Visualização e vá para o inspetor de identidade no painel da direita (alt-command-3). Mude a "Classe" para UIToolbar . Agora vá para o inspetor de atributos (alt-command-4) e mude a cor "Background" para "Clear Color".

3) Adicione uma subvisualização à visão principal e conecte-a a um IBOutlet na sua interface. Chame isso de backgroundColorView . Será algo parecido com isto, como uma categoria privada no arquivo de implementação ( .m ).

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

4) Vá para o arquivo de implementação do view controller ( .m ) e altere o método -viewDidLoad , da seguinte forma:

- (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 embaçará tudo atrás dela. Nenhum negócio engraçado, sem desfocar a imagem do núcleo lento, usando tudo o que está ao seu alcance, fornecido pelo OS / SDK.

Você pode adicionar a exibição deste controlador de exibição a outra exibiçã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 está claro, eu ficarei feliz em ajudar!

Editar

UIToolbar foi alterado em 7.0.3 para dar um efeito possivelmente indesejável ao usar um borrão colorido.

Nós costumávamos conseguir definir a cor usando barTintColor , mas se você estava fazendo isso antes, você precisa configurar o componente alpha para menos de 1. Caso contrário, seu UIToolbar será completamente opaco - sem desfoque.

Isto pode ser conseguido da seguinte forma: (tendo em conta que self é uma subclasse de UIToolbar )

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

Isso dará uma tonalidade azul para a vista desfocada.


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

Answer #3

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


Answer #4

Um complemento importante para a resposta do @ Joey

Isso se aplica a uma situação em que você deseja apresentar um UIViewController fundo desfocado com o 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];

Apreciar!


Answer #5

Usando UIImageEffects

Para as pessoas que querem mais controle, você pode usar o código de exemplo UIImageEffects da Apple.

Você pode copiar o código para UIImageEffects da Biblioteca de Desenvolvedores da Apple: Desfocando e Tingindo uma Imagem

E aqui está como aplicá-lo:

#import "UIImageEffects.h"
...

self.originalImageView.image = [UIImageEffects imageByApplyingLightEffectToImage:[UIImage imageNamed:@"yourImage.png"]];

Answer #6

Você pode usar o UIVisualEffectView para obter esse efeito. Essa é 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 !UIAccessibilityIsReduceTransparencyEnabled() {
    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 este view controller modally para desfocar o conteúdo subjacente, será necessário definir o estilo de apresentação modal como Over Current Context e definir a cor do plano de fundo para limpar, a fim de garantir que o controlador de visualização subjacente permaneça visível quando isso for exibido no topo.


Answer #7

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

Answer #8

Eu decidi postar uma versão escrita do Objective-C a partir da resposta aceita apenas para fornecer mais opções nesta questão.

- (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 se encaixar apenas no modo retrato ou apenas adicionar um sinalizador a essa função para usá-las ou não.


Answer #9

Swift 3 Versão da resposta de Kev para retornar 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;
    }

Answer #10

A resposta aceita está correta, mas há um passo importante que está faltando aqui, caso essa visão - para a qual você quer um fundo desfocado - seja apresentada usando

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

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

vc.modalPresentationStyle = UIModalPresentationOverFullScreen;

Ou use outros estilos Over .


Answer #11

Achei isso por acidente, me dá resultados muito bons (quase duplicados com a Apple) e usa o framework Acceleration. - http://pastebin.com/6cs6hsyQ * Não escrito por mim


Answer #12

Se adicionar uma visão obscura do tableView, isso fará com que ela:

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

Answer #13

Não acho que posso 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 no UIImage, e o método é o applyLightEffect.

Como eu disse acima em um comentário, o Apple Blur tem saturação e outras coisas acontecendo além de desfoque. Um simples borrão não fará ... se você estiver tentando imitar seu estilo.


Answer #14

A resposta simples é Adicionar uma subvisualização e alterar seu 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];

Answer #15

Escala de desfocagem personalizada

Você pode tentar o UIVisualEffectView com 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..


Answer #16

Swift 4:

Para adicionar uma sobreposição ou a exibição pop-up Você também pode usar a Visualização de Contêiner com a qual obtém um Controlador de Visualização livre (você obtém a Visualização de Contêiner da paleta / biblioteca de objetos usual)

Passos:

Tenha uma Visualização (ViewForContainer na foto) que contenha essa Exibição de Contêiner para diminuí-la quando o conteúdo da Exibição de Contêiner for exibido. Conecte a tomada dentro do primeiro View Controller

Ocultar esta vista quando carregar o 1º VC

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

Para escurecer esta Visualização quando o conteúdo da Exibição de Contêiner for exibido, defina o Fundo de Visualizações como Preto e a opacidade como 30%

Eu adicionei uma resposta para a criação de visão popview em outra questão https://.com/a/49729431/5438240


Answer #17

Core Image

Como a imagem na captura de tela é estática, você pode usar o CIGaussianBlur do Core Image (requer o 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 do 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;
}

Borrão de pilha (caixa + Gaussian)

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

Acelerar Framework

  • Na sessão “Implementando o Engaging UI on iOS” do WWDC 2013, a Apple explica como criar um fundo desfocado (às 14:30) e menciona um método applyLightEffect implementado no código de amostra usando Accelerate.framework.

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

    -(UIImage *)blurryGPUImage:(UIImage *)image withBlurLevel:(NSInteger)blur {
        GPUImageFastBlurFilter *blurFilter = [GPUImageFastBlurFilter new];
        blurFilter.blurSize = blur;
        UIImage *result = [blurFilter imageByFilteringImage:image];
        return result;
    }

Outras coisas

Andy Matuschak said no Twitter: "você sabe, muitos dos lugares onde parece que estamos fazendo em tempo real, é estático com truques inteligentes."

No site doubleencore.com eles dizem “descobrimos que um raio de 10 pt de borrão e um aumento de 10 pt na saturação melhor reproduzem o efeito de desfoque do iOS 7 na maioria das circunstâncias”.

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

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


Answer #18

Aqui está o código do Swift 2.0 para a solução que foi 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()
    }




core-image