218 votes

Comment puis-je produire un effet similaire à celui d'iOS 7 flou de vue?

Je suis en train d'essayer de reproduire ce flous d'arrière-plan à partir d'Apple publié iOS 7 exemple de l'écran:

iOS 7 Control Center screenshot

Cette question suggère d'appliquer un IC filtre le contenu ci-dessous, mais c'est une toute autre approche. Il est évident que l'iOS 7 n'a pas de capturer le contenu de la vue ci-dessous, pour de nombreuses raisons:

  1. Faire un peu rugueuse de test, de capturer une capture d'écran de la vue ci-dessous et l'application d'un CIGaussianBlur filtre avec un assez grand rayon d'imiter iOS 7 est flou style dure 1 à 2 secondes, même sur un simulateur.
  2. L'iOS 7 flou de vue est en mesure de flou sur les vues dynamiques, tels que la vidéo ou des animations, avec pas remarqué de lag.

Quelqu'un peut émettre l'hypothèse que les cadres qu'ils pourraient utiliser pour créer cet effet, et si il est possible de créer un effet similaire avec le public actuel de l'Api?

Edit: (de commentaire) On ne sait pas vraiment comment Apple est en train de faire, mais existe-il des hypothèses de base que nous pouvons faire? On peut supposer qu'ils sont à l'aide de matériel, droit?

Est l'effet d'auto-contenue dans chaque vue, tels que l'effet n'est pas réellement savoir ce qu'il y a derrière? Ou doit, basé sur la façon dont les flous de travail, le contenu derrière le flou être pris en considération?

Si le contenu derrière la effet sont pertinentes, peut-on supposer que Apple est à la réception d'un "flux" de le contenu ci-dessous et en continu de rendu avec un flou de bougé?

133voto

user2342340 Points 1151

Pourquoi se soucier de la réplication de l'effet? Il suffit de dessiner une UIToolbar derrière votre point de vue.

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

64voto

FreaknBigPanda Points 809

Apple a publié code lors de la WWDC de la catégorie sur UIImage qui comprend cette fonctionnalité, si vous avez un compte de développeur, vous pouvez saisir le UIImage catégorie (et le reste de l'exemple de code) en allant sur ce lien: https://developer.apple.com/wwdc/schedule/ et de navigation pour l'article 226 et en cliquant sur détails. Je n'ai pas joué avec ça encore, mais je pense que l'effet sera beaucoup plus lente sur iOS 6, il y a quelques améliorations à iOS 7 qui font de l'accaparement la première capture d'écran qui est utilisé comme entrée pour l'effet de flou est beaucoup plus rapide.

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

37voto

Jeremy Fox Points 1483

En fait, je parie que ce serait assez simple à réaliser. Il ne serait probablement pas fonctionner ou de ressembler exactement à ce que Apple a à faire, mais peuvent être très proches.

Tout d'abord, vous devez déterminer la CGRect de la UIView que vous allez présenter. Une fois que vous avez déterminé que vous n'avez qu'à saisir une image de la partie de l'INTERFACE utilisateur de sorte qu'il peut être floue. Quelque chose comme ceci...

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

Flou Gaussien - Recommandé

À l'aide de l' UIImage+ImageEffects Catégorie d'Apple fourni ici, vous obtiendrez un flou gaussien qui ressemble beaucoup comme le flou dans iOS 7.

Zone De Flou

Vous pouvez également utiliser une zone de flou à l'aide de la suite de boxBlurImageWithBlur: UIImage catégorie. Il est basé sur un algorythem que vous pouvez trouver ici.

@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

Maintenant que vous êtes le calcul de la zone de l'écran pour le flou, le passage dans la catégorie flou et la réception d'une UIImage de retour qui a été brouillée, maintenant tout ce qui reste est de mettre le flou de l'image comme arrière-plan de la vue que vous allez présenter. Comme je l'ai dit, ce ne sera pas un match parfait pour ce que fait Apple, mais il faudrait tout de même l'air assez cool.

Espérons que cela aide.

24voto

Adam Waite Points 2242

iOS8 répondu à ces questions.

UIVisualEffect

- (instancetype)initWithEffect:(UIVisualEffect *)effect

ou Swift:

init(effect effect: UIVisualEffect)

19voto

Ivo Leko Points 374

Je viens d'écrire mon petit sous-classe de UIView qui a la capacité de produire natif iOS 7 flou sur n'importe quel affichage personnalisé. Il utilise UIToolbar mais dans un chemin sûr pour changer de cadre, de limites, de couleur et alpha avec animation en temps réel.

S'il vous plaît laissez-moi savoir si vous remarquez des problèmes.

https://github.com/ivoleko/ILTranslucentView

ILTranslucentView examples

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X