Come posso produrre un effetto simile alla vista sfocatura di iOS 7?


219

Sto cercando di replicare questo sfondo sfocato dalla schermata di esempio iOS 7 rilasciata pubblicamente da Apple:

Schermata del Centro di controllo iOS 7

Questa domanda suggerisce di applicare un filtro CI ai contenuti di seguito, ma questo è un approccio completamente diverso. È ovvio che iOS 7 non acquisisce i contenuti delle visualizzazioni seguenti, per molte ragioni:

  1. Effettuare alcuni test approssimativi, catturare uno screenshot delle viste seguenti e applicare un filtro CIGaussianBlur con un raggio sufficientemente ampio da imitare lo stile di sfocatura di iOS 7 richiede 1-2 secondi, anche su un simulatore.
  2. La vista sfocatura di iOS 7 è in grado di sfocare su viste dinamiche, come un video o animazioni, senza alcun ritardo evidente.

Qualcuno può ipotizzare quali framework potrebbero utilizzare per creare questo effetto e se è possibile creare un effetto simile con le attuali API pubbliche?

Modifica: (dal commento) Non sappiamo esattamente come lo stia facendo Apple, ma ci sono ipotesi di base che possiamo fare? Possiamo presumere che stiano usando l'hardware, giusto?

L'effetto è indipendente in ogni vista, in modo tale che l'effetto non sappia realmente cosa c'è dietro? Oppure, in base a come funzionano le sfocature, i contenuti dietro la sfocatura devono essere presi in considerazione?

Se i contenuti alla base dell'effetto sono rilevanti, possiamo supporre che Apple stia ricevendo un "feed" dei contenuti sottostanti e li stia continuamente visualizzando con una sfocatura?


(Penso che possiamo supporre che apple stia usando pure GL per rendere comunque le schermate home. Dubito che lo stiano astraggendo con UIVview e altre cose che potrebbero degradare le prestazioni, dal momento che è una parte così importante del sistema operativo)
Dave,

Come ho indicato nei commenti alla mia risposta qui: stackoverflow.com/a/17048668/19679 hanno scritto il sistema operativo, quindi ovviamente avranno un accesso accelerato al contenuto dei livelli composti sotto la vista corrente. Possiamo vedere qualcosa di quello che potrebbero utilizzare nell'API IOSurface privato: stackoverflow.com/questions/14135215/... . Le sfocature gaussiane possono essere eseguite molto più rapidamente rispetto ai casi di sfocatura gaussiana generalizzata se hanno un raggio fisso o addirittura utilizzano ottimizzazioni interessanti come le immagini integrali.
Brad Larson

@BradLarson - Per parafrasare Jessica Simpson ... Non ho idea di cosa significhi tutto ciò, ma sembra fantastico! Ma seriamente, stai dicendo che puoi usare una vista parzialmente trasparente con un filtro di sfocatura e posizionarla su un'altra vista per ottenere questo effetto?
sangony

stackoverflow.com/a/25706250/2308190 ha funzionato perfettamente per me la prima volta che l'ho provato ed è stato conciso
Ben Wheeler,

Risposte:


134

Perché preoccuparsi di replicare l'effetto? Basta disegnare una UIToolbar dietro la vista.

myView.backgroundColor = [UIColor clearColor];
UIToolbar* bgToolbar = [[UIToolbar alloc] initWithFrame:myView.frame];
bgToolbar.barStyle = UIBarStyleDefault;
[myView.superview insertSubview:bgToolbar belowSubview:myView];

8
Non sono d'accordo con Crizzwald. Non credo sia una buona interpretazione delle regole di aspettativa di ciò che APple farà.
Andrew Johnson,

117
Ho seguito questo approccio da un ingegnere Apple UIKit questa settimana nel loro laboratorio Tech Talks. Sebbene certamente non approverebbe questo approccio, ha riconosciuto la necessità dell'effetto e la mancanza di un'API pubblica reale per questo, e ha detto che questo approccio era l'opzione "meno malvagia" per ora ed è abbastanza sicuro come scritto. In particolare, ha detto di non provare a fare alcuna animazione della frameo transformdi questa barra degli strumenti / vista o qualcosa del genere, o accadranno cose brutte. Ha anche fortemente suggerito di archiviare segnalazioni di bug del radar su questo, per costruire un caso internamente in modo da poter ottenere una vera API pubblica per questo effetto!
smileyborg,

44
Interessante ... sembra che l'account @ user2342340 sia stato creato solo per rispondere anonimamente a questa domanda. Ti chiedi se questo non è un post non ufficiale di qualcuno che conosce più di tutti noi di queste cose :)
smileyborg

4
Questo non funziona su iPhone 4 con iOS 7. Probabilmente perché su iPhone 4, poiché la GPU è troppo bassa, il sistema non aggiunge il solito effetto sfocato a se UITabBarstesso.
Ayush Goel,

2
Come faccio a renderlo non bianco? Se cambio il colore di sfondo per la barra degli strumenti, non mostra la sfocatura.
Nikita P,

64

Apple ha rilasciato il codice al WWDC come categoria su UIImage che include questa funzionalità, se hai un account sviluppatore puoi prendere la categoria UIImage (e il resto del codice di esempio) andando a questo link: https://developer.apple. com / wwdc / schedule / e sfogliando la sezione 226 e facendo clic sui dettagli. Non ci ho ancora giocato, ma penso che l'effetto sarà molto più lento su iOS 6, ci sono alcuni miglioramenti a iOS 7 che rendono molto più veloce la cattura della schermata iniziale che viene utilizzata come input per la sfocatura.

Link diretto: https://developer.apple.com/downloads/download.action?path=wwdc_2013/wwdc_2013_sample_code/ios_uiimageeffects.zip


1
Vedo il video, posso guardarlo, ma non riesco a capire dove scaricare il codice di esempio!
Nathan H,

Non ho visto molta differenza rispetto a un semplice cambio alfa in background; forse è perché sto visualizzando video e hanno solo bisogno di più sfocatura ...
Ja͢ck

37

In realtà scommetto che questo sarebbe piuttosto semplice da raggiungere. Probabilmente non funzionerebbe o non assomiglierebbe esattamente a ciò che sta accadendo Apple, ma potrebbe essere molto vicino.

Prima di tutto, dovresti determinare il CGRect di UIView che presenterai. Una volta stabilito che avresti solo bisogno di catturare un'immagine della parte dell'interfaccia utente in modo che possa essere sfocata. Qualcosa come questo...

- (UIImage*)getBlurredImage {
    // You will want to calculate this in code based on the view you will be presenting.
    CGSize size = CGSizeMake(200,200);

    UIGraphicsBeginImageContext(size);
    [view drawViewHierarchyInRect:(CGRect){CGPointZero, w, h} afterScreenUpdates:YES]; // view is the view you are grabbing the screen shot of. The view that is to be blurred.
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    // Gaussian Blur
    image = [image applyLightEffect];

    // Box Blur
    // image = [image boxblurImageWithBlur:0.2f];

    return image;
}

Sfocatura gaussiana: consigliata

Usando la UIImage+ImageEffectscategoria Apple fornita qui , otterrai una sfocatura gaussiana che assomiglia molto alla sfocatura in iOS 7.

Sfocatura casella

Puoi anche usare una sfocatura casella usando la seguente boxBlurImageWithBlur:categoria UIImage. Questo si basa su un algoritmo che puoi trovare qui .

@implementation UIImage (Blur)

-(UIImage *)boxblurImageWithBlur:(CGFloat)blur {
    if (blur < 0.f || blur > 1.f) {
        blur = 0.5f;
    }
    int boxSize = (int)(blur * 50);
    boxSize = boxSize - (boxSize % 2) + 1;

    CGImageRef img = self.CGImage;

    vImage_Buffer inBuffer, outBuffer;

    vImage_Error error;

    void *pixelBuffer;

    CGDataProviderRef inProvider = CGImageGetDataProvider(img);
    CFDataRef inBitmapData = CGDataProviderCopyData(inProvider);

    inBuffer.width = CGImageGetWidth(img);
    inBuffer.height = CGImageGetHeight(img);
    inBuffer.rowBytes = CGImageGetBytesPerRow(img);

    inBuffer.data = (void*)CFDataGetBytePtr(inBitmapData);

    pixelBuffer = malloc(CGImageGetBytesPerRow(img) * CGImageGetHeight(img));

    if(pixelBuffer == NULL)
        NSLog(@"No pixelbuffer");

    outBuffer.data = pixelBuffer;
    outBuffer.width = CGImageGetWidth(img);
    outBuffer.height = CGImageGetHeight(img);
    outBuffer.rowBytes = CGImageGetBytesPerRow(img);

    error = vImageBoxConvolve_ARGB8888(&inBuffer, &outBuffer, NULL, 0, 0, boxSize, boxSize, NULL, kvImageEdgeExtend);

    if (error) {
        NSLog(@"JFDepthView: error from convolution %ld", error);
    }

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef ctx = CGBitmapContextCreate(outBuffer.data,
                                         outBuffer.width,
                                         outBuffer.height,
                                         8,
                                         outBuffer.rowBytes,
                                         colorSpace,
                                         kCGImageAlphaNoneSkipLast);
    CGImageRef imageRef = CGBitmapContextCreateImage (ctx);
    UIImage *returnImage = [UIImage imageWithCGImage:imageRef];

    //clean up
    CGContextRelease(ctx);
    CGColorSpaceRelease(colorSpace);

    free(pixelBuffer);
    CFRelease(inBitmapData);

    CGImageRelease(imageRef);

    return returnImage;
}

@end

Ora che stai calcolando l'area dello schermo da sfocare, passandola nella categoria sfocatura e ricevendo un UIImage indietro che è stato sfocato, ora tutto ciò che resta è impostare quell'immagine sfocata come sfondo della vista che presenterai. Come ho detto, questo non sarà un abbinamento perfetto per ciò che Apple sta facendo, ma dovrebbe comunque sembrare piuttosto interessante.

Spero che sia d'aiuto.


Sembra che il colore blu dell'immagine sfocata e il colore rosso siano sbiaditi.
Henry,

Sembra che qualcuno abbia usato il tuo codice per creare questo progetto: github.com/alexdrone/ios-realtimeblur/blob/master/RealTimeBlur/… ma sfortunatamente non ci sono attribuzioni e hanno aggiunto una dichiarazione sul copyright "Tutti i diritti riservati" in cima.
Mark Erdmann,

@Mark, grazie per il testa a testa. Tuttavia, questo algoritmo di sfocatura non è il mio. Ho già menzionato da dove l'ho preso nel mio post sopra. Come dice il mio post "Questo si basa su un algoritmo che puoi trovare qui." con un link a indieambitions.com/idevblogaday/… invierò sicuramente a questa persona un messaggio e farò sapere che mancano di attribuzione. Grazie
Jeremy Fox,

@MarkErdmann dai un'occhiata ai tuoi file in xcode. Ha "Tutti i diritti riservati". È una cosa generica che aggiunge xcode. Anche l'autore ha aggiunto una licenza.md che dice che è stata lisenziata sotto la licenza
Babbo Natale

Non utilizzare renderInContext, utilizzare il nuovo drawViewHierarchyInRect:o snapshotView:. Il discorso del WWDC 216 "Implementing Engaging UI su iOS7" afferma un miglioramento delle prestazioni di 5-15x.
bcattle

25

iOS8 ha risposto a queste domande.

UIVisualEffect

- (instancetype)initWithEffect:(UIVisualEffect *)effect

o Swift:

init(effect effect: UIVisualEffect)


Immagino che questa soluzione sia per lo più inutile fino a quando iOS 9 non verrà rilasciato. La maggior parte delle applicazioni supporta ancora iOS 7 e questa soluzione non è supportata lì.
Dmitry Sobolev,

vero vero, puoi usare questo genere di cose per ora: github.com/nicklockwood/FXBlurView
Adam Waite

L'ho implementato con la toolchain Xcode 6 con iOS8 e funziona benissimo. Ho provato a implementare usando la CPU, ma funziona notevolmente più lentamente di questo metodo.
Jon

Perché programmare quando Xcode fornisce nello storyboard stesso !!!!! Grazie @AdamWaite
Mihir Oza l'

20

Ho appena scritto la mia piccola sottoclasse di UIView che ha la capacità di produrre sfocatura nativa di iOS 7 su qualsiasi vista personalizzata. Utilizza UIToolbar ma in modo sicuro per cambiare cornice, limiti, colore e alfa con l'animazione in tempo reale.

Per favore fatemi sapere se notate qualche problema.

https://github.com/ivoleko/ILTranslucentView

Esempi di ILTranslucentView


Ho provato altri approcci (come l'aggiunta di una UIToolbar o la categoria UIImage + ImageEffects.h di Apple); la tua era la soluzione migliore e più semplice. Grazie!
Yunus Nedim Mehel,

4
Quanto reagisce bene al nuovo download di iOS 7.0.3? Altre classi che hanno usato questa tecnica non vengono più visualizzate correttamente: [
achi

@achi, non ho notato alcun problema con iOS 7.0.3.
Ivo Leko,

Sai se qualche app che si anima con il tuo approccio e è stata accettata da Apple?
Brad Goss,

Ciao ragazzi. Sì, l'app che utilizza questa classe sarà approvata da Apple!
Ivo Leko,

10

Si dice che gli ingegneri Apple abbiano affermato che, per rendere questo performer, stanno leggendo direttamente dal buffer gpu, il che solleva problemi di sicurezza, motivo per cui non esiste ancora un'API pubblica per farlo.


6
Se questo è vero, questa è - di gran lunga - la peggiore soluzione di sempre.
elslooo,

2
aaaaa e la sfocatura viene rimossa da iOS 7.
Code Guru

3
È stato rimosso solo su dispositivi con problemi di prestazioni.
Cody C

24
Questo post è la fonte della voce? :)
Jano,

11
Quella voce è probabilmente a castello. OpenGL ES 2.0 su iOS ti consente di leggere e scrivere su framebuffer senza alcun rischio per la sicurezza. La sfocatura viene eseguita utilizzando gli shader GLSL, motivo per cui corre veloce.
Bentford,

7

Questa è una soluzione che puoi vedere nei vidios del WWDC. Devi fare una sfocatura gaussiana, quindi la prima cosa che devi fare è aggiungere un nuovo file .m e .h con il codice che sto scrivendo qui, quindi devi fare e fare lo screen screen, usare l'effetto desiderato e aggiungilo alla tua vista, quindi alla tua UIVable UIView o qualsiasi cosa debba essere sempre trasparente, puoi giocare con applyBlurWithRadius, per archiviare l'effetto desiderato, questa chiamata funziona con qualsiasi UIImage.

Alla fine l'immagine sfocata sarà lo sfondo e il resto dei controlli sopra dovrà essere trasparente.

Perché questo funzioni devi aggiungere le seguenti librerie:

Acelerate.framework, UIKit.framework, CoreGraphics.framework

Spero vi piaccia.

Buona codifica.

    //Screen capture.
    UIGraphicsBeginImageContext(self.view.bounds.size);

    CGContextRef c = UIGraphicsGetCurrentContext();
    CGContextTranslateCTM(c, 0, 0);
    [self.view.layer renderInContext:c];

    UIImage* viewImage = UIGraphicsGetImageFromCurrentImageContext();
    viewImage = [viewImage applyLightEffect];

    UIGraphicsEndImageContext();

    //.h FILE
    #import <UIKit/UIKit.h>

    @interface UIImage (ImageEffects)

   - (UIImage *)applyLightEffect;
   - (UIImage *)applyExtraLightEffect;
   - (UIImage *)applyDarkEffect;
   - (UIImage *)applyTintEffectWithColor:(UIColor *)tintColor;

   - (UIImage *)applyBlurWithRadius:(CGFloat)blurRadius tintColor:(UIColor *)tintColor saturationDeltaFactor:(CGFloat)saturationDeltaFactor maskImage:(UIImage *)maskImage;

   @end

    //.m FILE
    #import "cGaussianEffect.h"
    #import <Accelerate/Accelerate.h>
    #import <float.h>


     @implementation UIImage (ImageEffects)


    - (UIImage *)applyLightEffect
    {
        UIColor *tintColor = [UIColor colorWithWhite:1.0 alpha:0.3];
        return [self applyBlurWithRadius:1 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil];
    }


    - (UIImage *)applyExtraLightEffect
    {
        UIColor *tintColor = [UIColor colorWithWhite:0.97 alpha:0.82];
        return [self applyBlurWithRadius:1 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil];
    }


    - (UIImage *)applyDarkEffect
    {
        UIColor *tintColor = [UIColor colorWithWhite:0.11 alpha:0.73];
        return [self applyBlurWithRadius:1 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil];
    }


    - (UIImage *)applyTintEffectWithColor:(UIColor *)tintColor
    {
        const CGFloat EffectColorAlpha = 0.6;
        UIColor *effectColor = tintColor;
        int componentCount = CGColorGetNumberOfComponents(tintColor.CGColor);
        if (componentCount == 2) {
            CGFloat b;
            if ([tintColor getWhite:&b alpha:NULL]) {
                effectColor = [UIColor colorWithWhite:b alpha:EffectColorAlpha];
            }
        }
        else {
            CGFloat r, g, b;
            if ([tintColor getRed:&r green:&g blue:&b alpha:NULL]) {
                effectColor = [UIColor colorWithRed:r green:g blue:b alpha:EffectColorAlpha];
            }
        }
        return [self applyBlurWithRadius:10 tintColor:effectColor saturationDeltaFactor:-1.0 maskImage:nil];
    }


    - (UIImage *)applyBlurWithRadius:(CGFloat)blurRadius tintColor:(UIColor *)tintColor saturationDeltaFactor:(CGFloat)saturationDeltaFactor maskImage:(UIImage *)maskImage
    {
        if (self.size.width < 1 || self.size.height < 1) {
            NSLog (@"*** error: invalid size: (%.2f x %.2f). Both dimensions must be >= 1: %@", self.size.width, self.size.height, self);
            return nil;
        }
        if (!self.CGImage) {
            NSLog (@"*** error: image must be backed by a CGImage: %@", self);
            return nil;
        }
        if (maskImage && !maskImage.CGImage) {
            NSLog (@"*** error: maskImage must be backed by a CGImage: %@", maskImage);
            return nil;
        }

        CGRect imageRect = { CGPointZero, self.size };
        UIImage *effectImage = self;

        BOOL hasBlur = blurRadius > __FLT_EPSILON__;
        BOOL hasSaturationChange = fabs(saturationDeltaFactor - 1.) > __FLT_EPSILON__;
        if (hasBlur || hasSaturationChange) {
            UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]);
            CGContextRef effectInContext = UIGraphicsGetCurrentContext();
            CGContextScaleCTM(effectInContext, 1.0, -1.0);
            CGContextTranslateCTM(effectInContext, 0, -self.size.height);
            CGContextDrawImage(effectInContext, imageRect, self.CGImage);

            vImage_Buffer effectInBuffer;
            effectInBuffer.data     = CGBitmapContextGetData(effectInContext);
            effectInBuffer.width    = CGBitmapContextGetWidth(effectInContext);
            effectInBuffer.height   = CGBitmapContextGetHeight(effectInContext);
            effectInBuffer.rowBytes = CGBitmapContextGetBytesPerRow(effectInContext);

            UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]);
            CGContextRef effectOutContext = UIGraphicsGetCurrentContext();
            vImage_Buffer effectOutBuffer;
            effectOutBuffer.data     = CGBitmapContextGetData(effectOutContext);
            effectOutBuffer.width    = CGBitmapContextGetWidth(effectOutContext);
            effectOutBuffer.height   = CGBitmapContextGetHeight(effectOutContext);
            effectOutBuffer.rowBytes = CGBitmapContextGetBytesPerRow(effectOutContext);

            if (hasBlur) {
                CGFloat inputRadius = blurRadius * [[UIScreen mainScreen] scale];
                NSUInteger radius = floor(inputRadius * 3. * sqrt(2 * M_PI) / 4 + 0.5);
                if (radius % 2 != 1) {
                    radius += 1;
                }
                vImageBoxConvolve_ARGB8888(&effectInBuffer, &effectOutBuffer, NULL, 0, 0, radius, radius, 0, kvImageEdgeExtend);
                vImageBoxConvolve_ARGB8888(&effectOutBuffer, &effectInBuffer, NULL, 0, 0, radius, radius, 0, kvImageEdgeExtend);
                vImageBoxConvolve_ARGB8888(&effectInBuffer, &effectOutBuffer, NULL, 0, 0, radius, radius, 0, kvImageEdgeExtend);
            }
            BOOL effectImageBuffersAreSwapped = NO;
            if (hasSaturationChange) {
                CGFloat s = saturationDeltaFactor;
                CGFloat floatingPointSaturationMatrix[] = {
                    0.0722 + 0.9278 * s,  0.0722 - 0.0722 * s,  0.0722 - 0.0722 * s,  0,
                    0.7152 - 0.7152 * s,  0.7152 + 0.2848 * s,  0.7152 - 0.7152 * s,  0,
                    0.2126 - 0.2126 * s,  0.2126 - 0.2126 * s,  0.2126 + 0.7873 * s,  0,
                                  0,                    0,                    0,  1,
                };
                const int32_t divisor = 256;
                NSUInteger matrixSize = sizeof(floatingPointSaturationMatrix)/sizeof(floatingPointSaturationMatrix[0]);
                int16_t saturationMatrix[matrixSize];
                for (NSUInteger i = 0; i < matrixSize; ++i) {
                    saturationMatrix[i] = (int16_t)roundf(floatingPointSaturationMatrix[i] * divisor);
                }
                if (hasBlur) {
                    vImageMatrixMultiply_ARGB8888(&effectOutBuffer, &effectInBuffer, saturationMatrix, divisor, NULL, NULL, kvImageNoFlags);
                    effectImageBuffersAreSwapped = YES;
                }
                else {
                    vImageMatrixMultiply_ARGB8888(&effectInBuffer, &effectOutBuffer, saturationMatrix, divisor, NULL, NULL, kvImageNoFlags);
                }
            }
            if (!effectImageBuffersAreSwapped)
                effectImage = UIGraphicsGetImageFromCurrentImageContext();
            UIGraphicsEndImageContext();

            if (effectImageBuffersAreSwapped)
                effectImage = UIGraphicsGetImageFromCurrentImageContext();
            UIGraphicsEndImageContext();
        }

        UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]);
        CGContextRef outputContext = UIGraphicsGetCurrentContext();
        CGContextScaleCTM(outputContext, 1.0, -1.0);
        CGContextTranslateCTM(outputContext, 0, -self.size.height);

        CGContextDrawImage(outputContext, imageRect, self.CGImage);

        if (hasBlur) {
            CGContextSaveGState(outputContext);
            if (maskImage) {
                CGContextClipToMask(outputContext, imageRect, maskImage.CGImage);
            }
            CGContextDrawImage(outputContext, imageRect, effectImage.CGImage);
            CGContextRestoreGState(outputContext);
        }

        if (tintColor) {
            CGContextSaveGState(outputContext);
            CGContextSetFillColorWithColor(outputContext, tintColor.CGColor);
            CGContextFillRect(outputContext, imageRect);
            CGContextRestoreGState(outputContext);
        }

        UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();

        return outputImage;
    }

7

Puoi trovare la tua soluzione dalla DEMO di apple in questa pagina: WWDC 2013 , scoprire e scaricare il codice di esempio UIImageEffects.

Quindi con il codice di @Jeremy Fox. L'ho cambiato in

- (UIImage*)getDarkBlurredImageWithTargetView:(UIView *)targetView
{
    CGSize size = targetView.frame.size;

    UIGraphicsBeginImageContext(size);
    CGContextRef c = UIGraphicsGetCurrentContext();
    CGContextTranslateCTM(c, 0, 0);
    [targetView.layer renderInContext:c]; // view is the view you are grabbing the screen shot of. The view that is to be blurred.
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return [image applyDarkEffect];
}

Spero che questo ti possa aiutare.


7

Ecco un modo davvero semplice per farlo: https://github.com/JagCesar/iOS-blur

Basta copiare il livello di UIToolbar e il gioco è fatto, AMBlurView lo fa per te. Va bene, non è sfocato come il centro di controllo, ma è abbastanza sfocato.

Ricorda che iOS7 è sotto NDA.


6

Ogni risposta qui sta usando vImageBoxConvolve_ARGB8888 questa funzione è molto, molto lenta, va bene, se le prestazioni non sono un requisito prioritario, ma se lo stai usando per la transizione tra due controller di visualizzazione (ad esempio) questo approccio significa tempi superiori a 1 secondo o forse di più, ciò è molto negativo per l'esperienza dell'utente dell'applicazione.

Se preferisci lasciare tutta questa elaborazione delle immagini sulla GPU (e dovresti) puoi ottenere un effetto molto migliore e anche tempi fantastici arrotondando i 50ms (supponendo che tu abbia un tempo di 1 secondo nel primo approccio), quindi, facciamolo .

Prima scaricare il quadro GPUImage (licenza BSD) qui .

Successivamente, aggiungi le seguenti classi (.m e .h) da GPUImage (non sono sicuro che queste siano le minime necessarie solo per l'effetto di sfocatura)

  • GPUImage.h
  • GPUImageAlphaBlendFilter
  • GPUImageFilter
  • GPUImageFilterGroup
  • GPUImageGaussianBlurPositionFilter
  • GPUImageGaussianSelectiveBlurFilter
  • GPUImageLuminanceRangeFilter
  • GPUImageOutput
  • GPUImageTwoInputFilter
  • GLProgram
  • GPUImageBoxBlurFilter
  • GPUImageGaussianBlurFilter
  • GPUImageiOSBlurFilter
  • GPUImageSaturationFilter
  • GPUImageSolidColorGenerator
  • GPUImageTwoPassFilter
  • GPUImageTwoPassTextureSamplingFilter

  • iOS / GPUImage-Prefix.pch

  • iOS / GPUImageContext
  • iOS / GPUImageMovieWriter
  • iOS / GPUImagePicture
  • iOS / GPUImageView

Successivamente, crea una categoria su UIImage, che aggiungerà un effetto di sfocatura a un UIImage esistente:

#import "UIImage+Utils.h"

#import "GPUImagePicture.h"
#import "GPUImageSolidColorGenerator.h"
#import "GPUImageAlphaBlendFilter.h"
#import "GPUImageBoxBlurFilter.h"

@implementation UIImage (Utils)

- (UIImage*) GPUBlurredImage
{
    GPUImagePicture *source =[[GPUImagePicture alloc] initWithImage:self];

    CGSize size = CGSizeMake(self.size.width * self.scale, self.size.height * self.scale);

    GPUImageBoxBlurFilter *blur = [[GPUImageBoxBlurFilter alloc] init];
    [blur setBlurRadiusInPixels:4.0f];
    [blur setBlurPasses:2.0f];
    [blur forceProcessingAtSize:size];
    [source addTarget:blur];

    GPUImageSolidColorGenerator * white = [[GPUImageSolidColorGenerator alloc] init];

    [white setColorRed:1.0f green:1.0f blue:1.0f alpha:0.1f];
    [white forceProcessingAtSize:size];

    GPUImageAlphaBlendFilter * blend = [[GPUImageAlphaBlendFilter alloc] init];
    blend.mix = 0.9f;

    [blur addTarget:blend];
    [white addTarget:blend];

    [blend forceProcessingAtSize:size];
    [source processImage];

    return [blend imageFromCurrentlyProcessedOutput];
}

@end

Infine, aggiungi i seguenti framework al tuo progetto:

AVFoundation CoreMedia CoreVideo OpenGLES

Sì, divertiti con questo approccio molto più veloce;)


4

Puoi provare a utilizzare la mia vista personalizzata, che ha la capacità di sfocare lo sfondo. Lo fa falsificando la creazione di un'istantanea dello sfondo e la sfocatura, proprio come quella nel codice WWDC di Apple. È molto semplice da utilizzare.

Ho anche apportato alcuni miglioramenti per simulare la sfocatura dinamica senza perdere le prestazioni. Lo sfondo della mia vista è un scrollView che scorre con la vista, fornendo così l'effetto di sfocatura per il resto della superview.

Vedi l'esempio e il codice sul mio GitHub


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.