Creazione di una vista sovrapposta sfocata


Risposte:


552

Puoi usare UIVisualEffectView per ottenere questo effetto. Questa è un'API nativa che è stata ottimizzata per prestazioni e durata della batteria, inoltre è facile da implementare.

Swift:

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

Objective-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 stai presentando questo controller di visualizzazione in modo modale per offuscare il contenuto sottostante, dovrai impostare lo stile di presentazione modale su Over Current Context e impostare il colore di sfondo su clear per garantire che il controller di visualizzazione sottostante rimanga visibile una volta che questo viene presentato in overtop.


7
Come chiarimento al insertSubView:belowSubView:commento in questo codice, ho usato quanto segue per impostare la sfocatura come sfondo della vista:view.insertSubview(blurEffectView, atIndex: 0)
Michael Voccola,

2
Con riferimento alla risposta di cui sopra, è necessario verificare "if (! UIAccessibilityIsReduceTransparencyEnabled ())" o Possiamo ignorarlo?
GKK,

3
Se stai presentando il tuo controller di visualizzazione, assicurati di modificare modalPresentationStyle = .overCurrentContext insieme a impostare il colore di sfondo come chiaro
Shardul,

3
Funziona a meraviglia !!! È necessaria una modifica singola: [self.view insertSubview: blurEffectView atIndex: 1];
Abhishek Thapliyal,

2
In iOS 11, sto scoprendo che non è necessario controllare manualmente UIAccessibilityIsReduceTransparencyEnabled().
Nate Whittaker,

284

Immagine principale

Poiché l'immagine nello screenshot è statica, è possibile utilizzare CIGaussianBlurda Core Image (richiede iOS 6). Ecco un esempio: https://github.com/evanwdavis/Fun-with-Masks/blob/master/Fun%20with%20Masks/EWDBlurExampleVC.m

Intendiamoci, questo è più lento rispetto alle altre opzioni in questa pagina.

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

Stack blur (Box + Gaussian)

  • StackBlur Questo implementa un mix di Box e sfocatura gaussiana. 7 volte più veloce del gaussiano non accelerato, ma non così brutto come il mosso. Guarda una demo qui (versione del plugin Java) o qui (versione JavaScript). Questo algoritmo è usato in KDE e Camera + e altri. Non utilizza Accelerate Framework ma è veloce.

Accelerare il framework

  • Nella sessione "Implementazione dell'interfaccia utente su iOS" del WWDC 2013, Apple spiega come creare uno sfondo sfocato (alle 14:30) e menziona un metodo applyLightEffectimplementato nel codice di esempio utilizzando Accelerate.framework.

  • GPUImage utilizza shader OpenGL per creare sfocature dinamiche. Ha diversi tipi di sfocatura: GPUImageBoxBlurFilter, GPUImageFastBlurFilter, GaussianSelectiveBlur, GPUImageGaussianBlurFilter. Esiste anche un GPUImageiOSBlurFilter che "dovrebbe replicare completamente l'effetto sfocatura fornito dal pannello di controllo di iOS 7" ( tweet , articolo ). L'articolo è dettagliato e informativo.

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

Altre cose

Andy Matuschak ha dichiarato su Twitter: "Sai, molti dei posti in cui sembra che lo stiamo facendo in tempo reale, è statico con trucchi intelligenti".

Su doubleencore.com affermano che "abbiamo scoperto che un raggio di sfocatura di 10 pt più un aumento di 10 pt della saturazione imita meglio l'effetto di sfocatura di iOS 7 nella maggior parte dei casi".

Uno sguardo alle intestazioni private di SBFProceduralWallpaperView di Apple .

Infine, questa non è una vera sfocatura, ma ricorda che puoi impostare rasterizationScale per ottenere un'immagine pixelata: http://www.dimzzy.com/blog/2010/11/blur-effect-for-uiview/


Grazie per la risposta! Un problema è stato risolto. Ma abbiamo un altro problema. Come ottenere l'immagine di copertina in iOS 7. Se possibile?
kondratyevdev,

Se intendi come ottenere l'immagine di sfondo del tuo telefono, non hai idea a questo punto. Non ho visto quella funzionalità nelle differenze API . Forse utilizza un'API privata.
Jano,

Una cosa che ho notato (e potrei sbagliarmi totalmente) è che la sfocatura di Apple sembra aggiungere anche un po 'di saturazione del colore. Quindi, non penso sia una semplice sfocatura gaussiana.
xtravar il

Ricorda il fattore di scala quando ritorna, UIImagealtrimenti sembrerà troppo grande su un dispositivo Retina ...
Stephen Darlington,

Sai se un tale effetto potrebbe essere applicato a un UITableViewCell senza peggiorare le prestazioni?
Leonardo

15

Ho deciso di pubblicare una versione scritta di Objective-C dalla risposta accettata solo per fornire più opzioni in questa domanda.

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

I vincoli potrebbero essere rimossi se si desidera in caso di supporto se si supporta solo la modalità verticale o aggiungo semplicemente un flag a questa funzione per usarli o meno.


1
per le nuove persone (me), un modo per chiamare il metodo sopra è: [self applyBlurToView: self.view withEffectStyle: UIBlurEffectStyleDark andConstraints: YES]; (grazie NorthBlast)
tmr

14

Non credo di poter pubblicare il codice, ma il post sopra che menziona il codice di esempio WWDC è corretto. Ecco il link: https://developer.apple.com/downloads/index.action?name=WWDC%202013

Il file che stai cercando è la categoria su UIImage e il metodo è applyLightEffect.

Come ho notato sopra in un commento, l'Apple Blur ha saturazione e altre cose oltre a sfocatura. Una semplice sfocatura non farà ... se stai cercando di emulare il loro stile.


8
Quel collegamento è rotto. Ecco il link corretto: developer.apple.com/downloads/index.action?name=WWDC%202013
olivaresF

Si noti che questo codice di esempio richiede XCode 5.0 e iOS SDK 7.0 (che non sono ancora stati rilasciati pubblicamente)
Mike Gledhill

Grazie per il collegamento fisso, tuttavia contiene alcuni codici di esempio, quale contiene la categoria UIImage pertinente?
Leonardo

1
@Leonardo iOS_RunningWithASnap.zip
John Starr Dewar,

1
... o iOS_UIImageEffects.zip è più precisamente solo questo.
John Starr Dewar,

9

Penso che la soluzione più semplice sia quella di sovrascrivere UIToolbar, che sfuma tutto ciò che sta dietro in iOS 7. È abbastanza subdolo, ma è molto semplice da implementare e veloce!

Puoi farlo con qualsiasi vista, basta renderlo una sottoclasse UIToolbarinvece di UIView. Si può anche farlo con una UIViewController's viewproprietà, per esempio ...

1) creare una nuova classe che è una "sottoclasse di" UIViewControllere selezionare la casella "Con XIB per l'interfaccia utente".

2) Seleziona la vista e vai alla finestra di ispezione identità nel pannello di destra (alt-command-3). Cambia la "Classe" in UIToolbar. Ora vai alla finestra di ispezione degli attributi (alt-command-4) e cambia il colore "Sfondo" in "Cancella colore".

3) Aggiungi una sottoview alla vista principale e collegala a una IBOutlet nella tua interfaccia. Chiamatela backgroundColorView. Assomiglierà a qualcosa del genere, come una categoria privata nel .mfile deployment ( ).

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

4) Vai al .mfile di implementazione del controller di visualizzazione ( ) e modifica il -viewDidLoadmetodo, per visualizzare come segue:

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

Questo ti darà una vista grigio scuro, che offusca tutto ciò che c'è dietro. Nessun business divertente, nessuna sfocatura delle immagini core lenta, utilizzando tutto ciò che è a portata di mano fornito dal sistema operativo / SDK.

È possibile aggiungere la vista del controller di questa vista a un'altra vista, come segue:

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

// animate the self.blurViewController into view

Fammi sapere se qualcosa non è chiaro, sarò felice di aiutarti!


modificare

UIToolbar è stato modificato in 7.0.3 per dare un effetto potenzialmente indesiderato quando si usa una sfocatura colorata.

barTintColorPrima eravamo in grado di impostare il colore usando , ma se lo facevi prima, dovrai impostare il componente alfa su un valore inferiore a 1. Altrimenti la tua barra UITool sarà completamente opaca, senza sfocature.

Ciò può essere ottenuto come segue: (tenere presente che selfè una sottoclasse di UIToolbar)

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

Questo darà una sfumatura blu alla vista sfocata.


1
Non cattivo. Ho usato queste tre linee a mio avviso: self.backgroundColorView.opaque = NO; self.backgroundColorView.alpha = 0.5; self.backgroundColorView.backgroundColor = [UIColor colorWithWhite:0.3 alpha:1];ma lo sfondo non è stato sfocato, ma solo un bell'effetto. grazie comunque!
IgniteCoders,

1
Non vedo alcun offuscamento affatto usando questa tecnica. Crea solo una sovrapposizione colorata.
MusiGenesis,

assicurati che la sovrapposizione colorata alfa sia inferiore a 1. Puoi usare una UIToolbar senza il controller di visualizzazione, che potrebbe essere più semplice a seconda di ciò di cui hai bisogno.
Sam,

bravo uomo. Ho convertito la mia vista in classe UIToolbar nello storyboard, quindi ho cambiato lo sfondo della vista per cancellare il colore. Ha dato uno sfondo sfocato bianco. Se rendi alpha inferiore a 1, l'effetto sfocato scompare.
Badr,

9

Ecco un'implementazione veloce in Swift usando 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;
}

7

Scala di sfocatura personalizzata

Puoi provare UIVisualEffectView con un'impostazione personalizzata come -

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

Uscita: - per blurEffect.setValue(1...& blurEffect.setValue(2.. inserisci qui la descrizione dell'immagine inserisci qui la descrizione dell'immagine


3
Smetterà di funzionare se nella prossima versione del nome iOS di questo parametro viene modificato.
Ariel Bogdziewicz,

@ArielBogdziewicz attualmente sta funzionando. aggiornerò se ci sono variazioni API in wwdc.
Jack

Ummm ... no, non vuoi mai accedere alle API private. Sono privati ​​per un motivo. Cambieranno, si romperanno e / o Apple rifiuterà la tua app. Usa un altro metodo, ce n'è in abbondanza. Complimenti per aver trovato l'hack, ma non è raccomandato.
n13

@Jack Grazie mille per questa risposta! È l'unica soluzione che ho trovato al mio problema: sfocare una vista in base alla posizione di un'altra vista. Tuttavia, ho ancora un'altra domanda. C'è un modo in cui posso aggiungere vivacità al mio UIBlurEffect? Se é cosi, come? Devo creare un'altra vista per questo sopra il mio blurView? L'ho provato ma si è sempre schiantato quando l'ho usato (NSClassFromString("_UICustomVibrancyEffect") as! UIVibrancyEffect.Type).init()Avrei davvero apprezzato l'aiuto!
Moritz,

@Moritz non ci ha provato. Ma dovrebbe funzionare. Puoi provare e controllare.
Jack,

7

Ecco un modo semplice per aggiungere la sfocatura personalizzata senza contrattare con le API private utilizzando UIViewPropertyAnimator :

Per prima cosa, dichiara la proprietà della classe:

var blurAnimator: UIViewPropertyAnimator!

Quindi imposta la sfocatura in 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: questa soluzione non è adatta per UICollectionView/ UITableViewcellule


1
Questa è l'unica soluzione che ho trovato se desideri controllare la trasparenza di UIVisualEffectView.
Denis Kutlubaev,

6

inserisci qui la descrizione dell'immagine

Da Xcode puoi farlo facilmente. Seguire i passaggi da xcode. Drage vista effetti visivi sul tuo uiview o imageview.

Happy Coding :)


5

La risposta accettata è corretta ma manca un passaggio importante qui, nel caso in cui questa vista, per la quale si desidera uno sfondo sfocato, sia presentata usando

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

Per impostazione predefinita, questo annullerà la sfocatura poiché UIKit rimuove la vista del presentatore, che in realtà stai sfocando. Per evitare tale rimozione, aggiungi questa riga prima di quella precedente

vc.modalPresentationStyle = UIModalPresentationOverFullScreen;

O usa altri Overstili.


3

Objective-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)

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


2

Utilizzo di UIImageEffects

Per le persone che desiderano maggiore controllo, è possibile utilizzare il UIImageEffectscodice di esempio di Apple .

Puoi copiare il codice UIImageEffectsdalla Libreria per sviluppatori di Apple: sfocatura e tinta di un'immagine

Ed ecco come applicarlo:

#import "UIImageEffects.h"
...

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

Come
posso

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

1

Ho trovato questo per caso, mi dà risultati davvero fantastici (quasi duplicati con quelli di Apple) e usa il framework Acceleration. - http://pastebin.com/6cs6hsyQ * Non scritto da me


8
In realtà è il codice Apple del WWDC 2013 con copyright errato.
Shmidt,

i codici del WWDC non sono protetti da copyright e l'accesso è consentito solo ai membri con abbonamenti a pagamento?
SAFAD,

1
Forse, ma il codice sopra ho trovato usando Google. Non ho modificato il Copyright e ho assunto (e presumo ancora) che abbia il diritto corretto sul copyright. Se Apple non è d'accordo, dovrebbero impegnarsi a smontarlo. Non vedo la rilevanza.
Jake,

1

Questa risposta si basa sull'eccellente risposta precedente di Mitja Semolic . L'ho convertito in Swift 3, ho aggiunto una spiegazione a ciò che sta accadendo nei commenti, l'ho trasformato in un'estensione di UIViewController in modo che qualsiasi VC possa chiamarlo a piacimento, ho aggiunto una vista non sfocata per mostrare un'applicazione selettiva e ho aggiunto un blocco di completamento in modo che il controller della vista chiamante può fare quello che vuole al completamento della sfocatura.

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

Ho confermato che funziona con iOS 10.3.1 e iOS 11


1

Un importante supplemento alla risposta di @ Joey

Questo vale per una situazione in cui si desidera presentare un offuscata-sfondo UIViewControllercon 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];

Godere!


1

Swift 3 Versione della risposta di Kev per restituire un'immagine sfocata -

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

1

Codice 2019

Ecco un esempio più completo usando la straordinaria tecnica di @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
    }

{A parte: come una questione generale di ingegneria iOS, didMoveToWindowpotrebbe essere più adatto a te di didMoveToSuperview. In secondo luogo, è possibile utilizzare un altro modo per eseguire lo smontaggio, ma lo smontaggio sono le due righe di codice mostrate lì.}

BlurryBallè solo un UIVisualEffectView. Nota gli init per una vista degli effetti visivi. Se hai bisogno di angoli arrotondati o altro, fallo in questa 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
    }
}


0

Ecco il codice Swift 2.0 per la soluzione fornita nella risposta accettata :

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

0

Se aggiunge una vista sfocatura scura per tableView, questo lo renderà magnificamente:

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

0

Puoi creare direttamente la sfocatura dello sfondo usando "Vista effetto visivo con sfocatura" e "Vista effetto visivo con sfocatura e vividezza".

Tutto quello che devi fare per creare sfocatura dello sfondo nell'applicazione iOS è ...

  1. Vai e cerca "Vista effetto visivo con sfocatura" nella Libreria oggetti

Passaggio 1 Immagine

  1. Trascina la "Visualizzazione effetto visivo con sfocatura" nello Storyboard e impostala ...

Passaggio 2 Immagine

  1. Finalmente ... Fai la sfocatura dello sfondo della tua app!

Layout dell'applicazione prima di fare clic su qualsiasi pulsante!

Visualizzazione applicazione dopo aver fatto clic sul pulsante che rende sfocata l'intera applicazione!


0

Se questo aiuta qualcuno, ecco una rapida estensione che ho creato sulla base della risposta di Jordan H. È scritto in Swift 5 e può essere utilizzato dall'Obiettivo 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 si desidera sfocare lo sfondo di un UILabel senza influire sul testo, è necessario creare un UIView contenitore, aggiungere UILabel al contenitore UIView come sottoview, impostare il backgroundColor di UILabel su UIColor.clear, quindi chiamare blurBackground (stile : UIBlurEffect.Style, fallbackColor: UIColor) sul contenitore UIView. Ecco un breve esempio di questo scritto in 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)

-1

Swift 4:

Per aggiungere una sovrapposizione o la vista popup È inoltre possibile utilizzare la vista contenitore con la quale si ottiene un controller vista gratuito (si ottiene la vista contenitore dalla normale tavolozza / libreria di oggetti)

passi:

Avere una vista (ViewForContainer nella foto) che contiene questa vista contenitore, per oscurarla quando vengono visualizzati i contenuti della vista contenitore. Collegare la presa all'interno del primo View Controller

Nascondi questa vista quando viene caricato il 1 ° VC

Scopri quando si fa clic sul pulsante, immettere qui la descrizione dell'immagine

Per oscurare questa vista quando viene visualizzato il contenuto della vista contenitore, impostare lo Sfondo delle viste su Nero e l'opacità sul 30%

Ho aggiunto una risposta alla creazione della vista popview in un'altra domanda StackOver https://stackoverflow.com/a/49729431/5438240


-3

La risposta semplice è Aggiungi una sottoview e cambiarla è 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];
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.