Création d'une vue de superposition floue

Réponses:

552

Vous pouvez utiliser UIVisualEffectViewpour obtenir cet effet. Il s'agit d'une API native qui a été optimisée pour les performances et la durée de vie de la batterie, en plus d'être facile à mettre en œuvre.

Rapide:

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

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

Si vous présentez ce contrôleur de vue de manière modale pour brouiller le contenu sous-jacent, vous devrez définir le style de présentation modale sur Over Current Context et définir la couleur d'arrière-plan pour effacer pour vous assurer que le contrôleur de vue sous-jacent restera visible une fois qu'il sera présenté au-dessus.

Jordan H
la source
7
Pour clarifier le insertSubView:belowSubView:commentaire de ce code, j'ai utilisé ce qui suit pour définir le flou comme arrière-plan de la vue:view.insertSubview(blurEffectView, atIndex: 0)
Michael Voccola
2
En référence à la réponse ci-dessus, est-il nécessaire de vérifier "si (! UIAccessibilityIsReduceTransparencyEnabled ())" ou pouvons-nous ignorer cela?
GKK
3
Si vous présentez votre contrôleur de vue, assurez-vous de modifier modalPresentationStyle = .overCurrentContext en définissant la couleur d'arrière-plan comme claire
Shardul
3
Fonctionne génial !!! Besoin d'une seule modification: [self.view insertSubview: blurEffectView atIndex: 1];
Abhishek Thapliyal
2
Dans iOS 11, je constate qu'il n'est pas nécessaire de vérifier manuellement UIAccessibilityIsReduceTransparencyEnabled().
Nate Whittaker
284

Image de base

Étant donné que cette image dans la capture d'écran est statique, vous pouvez utiliser à CIGaussianBlurpartir de Core Image (nécessite iOS 6). Voici un exemple: https://github.com/evanwdavis/Fun-with-Masks/blob/master/Fun%20with%20Masks/EWDBlurExampleVC.m

Attention, c'est plus lent que les autres options de cette page.

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

Flou de la pile (boîte + gaussien)

  • StackBlur Ceci implémente un mélange de Box et de flou gaussien. 7x plus rapide que le gaussien non accéléré, mais pas aussi laid que le flou de la boîte. Voir une démo ici (version du plugin Java) ou ici (version JavaScript). Cet algorithme est utilisé dans KDE et Camera + et autres. Il n'utilise pas Accelerate Framework mais il est rapide.

Accélérer le cadre

  • Dans la session «Implémentation de l'interface utilisateur engageante sur iOS» de la WWDC 2013, Apple explique comment créer un arrière-plan flou (à 14h30) et mentionne une méthode applyLightEffectimplémentée dans l'exemple de code à l'aide d'Accelerate.framework.

  • GPUImage utilise des shaders OpenGL pour créer des flous dynamiques. Il a plusieurs types de flou: GPUImageBoxBlurFilter, GPUImageFastBlurFilter, GaussianSelectiveBlur, GPUImageGaussianBlurFilter. Il existe même un GPUImageiOSBlurFilter qui «devrait reproduire pleinement l'effet de flou fourni par le panneau de configuration d'iOS 7» ( tweet , article ). L'article est détaillé et informatif.

    - (UIImage *) flouGPUImage: (UIImage *) image avecBlurLevel: (NSInteger) blur {
        GPUImageFastBlurFilter * blurFilter = [GPUImageFastBlurFilter nouveau];
        blurFilter.blurSize = flou;
        UIImage * result = [blurFilter imageByFilteringImage: image];
        résultat de retour;
    }
  • Depuis indieambitions.com: effectuez un flou à l'aide de vImage . L'algorithme est également utilisé dans iOS-RealTimeBlur .

  • De Nick Lockwood: https://github.com/nicklockwood/FXBlurView L'exemple montre le flou sur une vue de défilement. Il se brouille avec dispatch_async, puis se synchronise pour appeler les mises à jour avec UITrackingRunLoopMode afin que le flou ne soit pas retardé lorsque UIKit donne plus de priorité au défilement de l'UIScrollView. Cela est expliqué dans le livre de Nick, iOS Core Animation , qui est génial.

  • iOS-blur Cela prend la couche de flou de la barre d'outils UIT et la place ailleurs. Apple rejettera votre application si vous utilisez cette méthode. Voir https://github.com/mochidev/MDBlurView/issues/4

  • Du blog Evadne: LiveFrost : Convolution rapide et synchrone d'instantanés UIView . Excellent code et bonne lecture. Quelques idées de ce post:

    • Utilisez une file d'attente série pour limiter les mises à jour de CADisplayLink.
    • Réutilisez les contextes bitmap à moins que les limites ne changent.
    • Dessinez des images plus petites en utilisant - [CALayer renderInContext:] avec un facteur d'échelle de 0,5f.

D'autres choses

Andy Matuschak a déclaré sur Twitter: "vous savez, beaucoup d'endroits où il semble que nous le faisons en temps réel, c'est statique avec des astuces intelligentes."

Sur doubleencore.com, ils disent «nous avons constaté qu'un rayon de flou de 10 pt plus une augmentation de 10 pt de la saturation imite mieux l'effet de flou d'iOS 7 dans la plupart des circonstances».

Un aperçu des en-têtes privés du SBFProceduralWallpaperView d'Apple .

Enfin, ce n'est pas un vrai flou, mais n'oubliez pas que vous pouvez définir rasterizationScale pour obtenir une image pixellisée: http://www.dimzzy.com/blog/2010/11/blur-effect-for-uiview/

Jano
la source
Merci de répondre! Un problème est résolu. Mais nous avons encore un problème. Comment obtenir une image de couverture dans iOS 7. Si c'est possible?
kondratyevdev
Si vous voulez savoir comment obtenir l'image de fond d'écran de votre téléphone, aucune idée à ce stade. Je n'ai pas vu cette fonctionnalité dans les différences d' API . Peut-être qu'il utilise une API privée.
Jano
Une chose que j'ai remarquée (et je peux me tromper) est que le flou d'Apple semble également ajouter une petite saturation des couleurs. Donc, je ne pense pas que ce soit un simple flou gaussien.
xtravar
Rappelez-vous le facteur d'échelle lorsque vous retournez le UIImagesinon il va paraître beaucoup trop gros sur un appareil Retina ...
Stephen Darlington
Savez-vous si un tel effet pourrait être appliqué à une UITableViewCell sans dégrader les performances?
Leonardo
15

J'ai décidé de publier une version écrite d'Objective-C à partir de la réponse acceptée juste pour fournir plus d'options dans cette question.

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

Les contraintes pourraient être supprimées si vous voulez incase si vous ne supportez que le mode portrait ou si j'ajoute juste un drapeau à cette fonction pour les utiliser ou non.

valbu17
la source
1
pour les nouveaux (moi), une façon d'appeler la méthode ci-dessus est: [self applyBlurToView: self.view withEffectStyle: UIBlurEffectStyleDark andConstraints: YES]; (merci NorthBlast)
tmr
14

Je ne pense pas que je suis autorisé à publier le code, mais l'article ci-dessus mentionnant l'exemple de code WWDC est correct. Voici le lien: https://developer.apple.com/downloads/index.action?name=WWDC%202013

Le fichier que vous recherchez est la catégorie sur UIImage, et la méthode est applyLightEffect.

Comme je l'ai noté ci-dessus dans un commentaire, l'Apple Blur a une saturation et d'autres choses en plus du flou. Un simple flou ne fera pas l'affaire ... si vous cherchez à imiter leur style.

xtravar
la source
8
Ce lien est rompu. Voici le lien correct: developer.apple.com/downloads/index.action?name=WWDC%202013
olivaresF
Notez que cet exemple de code nécessite XCode 5.0 et iOS SDK 7.0 (qui n'ont pas encore été rendus publics)
Mike Gledhill
Merci pour le lien fixe, mais il contient quelques exemples de code, lequel contient la catégorie UIImage pertinente?
Leonardo
1
@Leonardo iOS_RunningWithASnap.zip
John Starr Dewar
1
... ou iOS_UIImageEffects.zip est plus précisément cela.
John Starr Dewar
10

Voici une implémentation rapide dans Swift en utilisant CIGaussianBlur:

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

    return returnImage;
}
kev
la source
9

Je pense que la solution la plus simple est de remplacer UIToolbar, qui brouille tout derrière iOS 7. C'est assez sournois, mais c'est très simple à mettre en œuvre et rapide!

Vous pouvez le faire avec n'importe quelle vue, faites-en simplement une sous-classe de UIToolbarau lieu de UIView. Vous pouvez même le faire avec unUIViewController la viewpropriété a, par exemple ...

1) créer une nouvelle classe qui est une "sous-classe de" UIViewController et cochez la case "Avec XIB pour l'interface utilisateur".

2) Sélectionnez la vue et accédez à l'inspecteur d'identité dans le panneau de droite (alt-commande-3). Changez la "Classe" enUIToolbar . Allez maintenant dans l'inspecteur d'attributs (alt-commande-4) et changez la couleur "Arrière-plan" en "Couleur claire".

3) Ajoutez une sous-vue à la vue principale et connectez-la à un IBOutlet dans votre interface. Appelez ça backgroundColorView. Il ressemblera à quelque chose comme ceci, comme une catégorie privée dans le .mfichier implementation ( ).

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

4) Accédez au .mfichier d' implémentation du contrôleur de vue ( ) et modifiez la -viewDidLoadméthode, comme suit:

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

Cela vous donnera une vue gris foncé, qui brouille tout derrière. Aucune entreprise amusante, aucun flou lent de l'image de base, en utilisant tout ce qui est à portée de main fourni par l'OS / SDK.

Vous pouvez ajouter la vue de ce contrôleur de vue à une autre vue, comme suit:

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

// animate the self.blurViewController into view

Faites-moi savoir si quelque chose n'est pas clair, je serai heureux de vous aider!


Éditer

UIToolbar a été modifié dans 7.0.3 pour donner un effet éventuellement indésirable lors de l'utilisation d'un flou coloré.

barTintColorAuparavant, nous pouvions définir la couleur à l'aide , mais si vous le faisiez auparavant, vous devrez définir le composant alpha sur moins de 1. Sinon, votre UIToolbar sera de couleur complètement opaque - sans flou.

Ceci peut être réalisé comme suit: (en gardant à l'esprit selfune sous-classe de UIToolbar)

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

Cela donnera une teinte bleue à la vue floue.

Sam
la source
1
Pas mauvais homme. J'ai utilisé ces trois lignes à mon avis: self.backgroundColorView.opaque = NO; self.backgroundColorView.alpha = 0.5; self.backgroundColorView.backgroundColor = [UIColor colorWithWhite:0.3 alpha:1];mais l'arrière-plan n'est pas flou, faites juste un bel effet de sur. merci quand même!
IgniteCoders
1
Je ne vois aucun flou en utilisant cette technique. Il crée simplement une superposition colorée.
MusiGenesis
assurez-vous que la superposition alpha de couleur est inférieure à 1. Vous pouvez utiliser une barre d'outils UIT sans le contrôleur de vue, ce qui peut être plus simple selon vos besoins.
Sam
homme de truc soigné. J'ai converti ma vue en classe UIToolbar dans le storyboard, puis j'ai changé l'arrière-plan de la vue en couleur claire. Il a donné un arrière-plan flou blanc. Si vous faites un alpha inférieur à 1, l'effet flou disparaîtra.
Badr
7

Échelle de flou personnalisée

Vous pouvez essayer UIVisualEffectView avec un paramètre personnalisé comme -

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

Sortie: - pour blurEffect.setValue(1...& blurEffect.setValue(2.. entrez la description de l'image ici entrez la description de l'image ici

Jack
la source
3
Il cessera de fonctionner si dans la prochaine version d'iOS le nom de ce paramètre est modifié.
Ariel Bogdziewicz
@ArielBogdziewicz fonctionne actuellement. je mettrai à jour s'il y a une variation API dans wwdc.
Jack
Ummm ... non, vous ne voulez jamais accéder aux API privées. Ils sont privés pour une raison. Ils changeront, ils se briseront et / ou Apple rejettera votre application. Utilisez une autre méthode, il y en a beaucoup. Bravo pour avoir trouvé le hack, mais pas recommandé.
n13
@Jack Merci beaucoup pour cette réponse! C'est la seule solution que j'ai trouvée à mon problème: brouiller une vue en fonction de la position d'une autre vue. Cependant, j'ai encore une autre question. Existe-t-il un moyen d'ajouter du dynamisme à mon UIBlurEffect? Si c'est le cas, comment? Dois-je créer une autre vue pour cela au-dessus de mon blurView? J'ai essayé mais ça plantait toujours quand j'utilisais (NSClassFromString("_UICustomVibrancyEffect") as! UIVibrancyEffect.Type).init()J'apprécierais vraiment de l'aide!
Moritz
@Moritz n'a pas essayé. Mais cela devrait fonctionner. Vous pouvez essayer de vérifier.
Jack
7

Voici un moyen simple d'ajouter un flou personnalisé sans marchander avec des API privées à l'aide d' UIViewPropertyAnimator :

Tout d'abord, déclarez la propriété de classe:

var blurAnimator: UIViewPropertyAnimator!

Ensuite, définissez votre vue floue dans 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.    

Remarque: Cette solution ne convient pas pour UICollectionView/ UITableViewcells

Adam Bardon
la source
1
C'est la seule solution que j'ai trouvée si vous voulez contrôler la transparence de UIVisualEffectView.
Denis Kutlubaev
6

entrez la description de l'image ici

Depuis Xcode, vous pouvez le faire facilement. Suivez les étapes de xcode. Affichez l'effet visuel sur votre uiview ou imageview.

Happy Coding :)

Mehedi Hasan
la source
5

La réponse acceptée est correcte mais il manque une étape importante ici, au cas où cette vue - pour laquelle vous voulez un arrière-plan flou - est présentée à l'aide de

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

Par défaut, cela annulera le flou car UIKit supprime la vue du présentateur, que vous brouillez réellement. Pour éviter cette suppression, ajoutez cette ligne avant la précédente

vc.modalPresentationStyle = UIModalPresentationOverFullScreen;

Ou utilisez d'autres Overstyles.

Aleksandar Vacić
la source
3

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

à partir de: https://stackoverflow.com/a/24083728/4020910

BennyTheNerd
la source
2

Utilisation d'UIImageEffects

Pour les personnes qui souhaitent plus de contrôle, vous pouvez utiliser l' UIImageEffectsexemple de code d'Apple .

Vous pouvez copier le code UIImageEffectsde la bibliothèque des développeurs d'Apple: flou et teinte d'une image

Et voici comment l'appliquer:

#import "UIImageEffects.h"
...

self.originalImageView.image = [UIImageEffects imageByApplyingLightEffectToImage:[UIImage imageNamed:@"yourImage.png"]];
Zakaria Braksa
la source
Comment puis-je l'utiliser dans Swift
devjme
2
func blurBackgroundUsingImage(image: UIImage)
{
    var frame                   = CGRectMake(0, 0, self.view.frame.width, self.view.frame.height)
    var imageView               = UIImageView(frame: frame)
    imageView.image             = image
    imageView.contentMode       = .ScaleAspectFill
    var blurEffect              = UIBlurEffect(style: .Light)
    var blurEffectView          = UIVisualEffectView(effect: blurEffect)
    blurEffectView.frame        = frame
    var transparentWhiteView    = UIView(frame: frame)
    transparentWhiteView.backgroundColor = UIColor(white: 1.0, alpha: 0.30)
    var viewsArray              = [imageView, blurEffectView, transparentWhiteView]

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

J'ai trouvé cela par accident, me donne de très bons résultats (presque en double avec ceux d'Apple) et utilise le cadre d'accélération. - http://pastebin.com/6cs6hsyQ * Non écrit par moi

Jake
la source
8
Il s'agit en fait du code Apple de la WWDC 2013 avec un droit d'auteur incorrect.
Shmidt
les codes de la WWDC ne sont-ils pas protégés par des droits d'auteur, et l'accès n'est autorisé qu'aux membres abonnés payants?
SAFAD
1
Peut-être, mais le code ci-dessus que j'ai trouvé en utilisant Google. Je n'ai pas changé le Copyright et j'ai supposé (et je suppose toujours) qu'il a la revendication de copyright correcte. Si Apple n'est pas d'accord, ils devraient mettre tout en œuvre pour le supprimer. Je ne vois pas la pertinence.
Jake
1

Cette réponse est basée sur l'excellente réponse antérieure de Mitja Semolic . Je l'ai converti en swift 3, ajouté une explication à ce qui se passe dans coments, en ai fait une extension d'un UIViewController pour que n'importe quel VC puisse l'appeler à volonté, ajouté une vue non floue pour montrer une application sélective et ajouté un bloc de complétion afin que le contrôleur de vue appelant peut faire ce qu'il veut à la fin du flou.

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

J'ai confirmé que cela fonctionne avec iOS 10.3.1 et iOS 11

James Jordan Taylor
la source
1

Un complément important à la réponse de @ Joey

Cela s'applique à une situation où vous voulez présenter un arrière - plan flou UIViewControlleravec 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];

Prendre plaisir!

stévéluoxine
la source
1

Version Swift 3 de la réponse de Kev pour renvoyer une image floue -

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

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

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

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

Code 2019

Voici un exemple plus complet utilisant l'incroyable technique @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
    }

{À part: en général, l'ingénierie iOS didMoveToWindowpeut vous convenir mieux quedidMoveToSuperview . Deuxièmement, vous pouvez utiliser une autre méthode pour effectuer le démontage, mais le démontage correspond aux deux lignes de code qui y sont affichées.}

BlurryBallest juste un UIVisualEffectView. Notez les inits pour une vue d'effets visuels. Si vous avez besoin de coins arrondis ou autre, faites-le dans cette classe.

class BlurryBall: UIVisualEffectView {

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

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

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

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

Voici le code Swift 2.0 pour la solution qui a été fournie dans la réponse acceptée :

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

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

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

Si ajoute une vue floue sombre pour tableView, cela le fera magnifiquement:

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
Ciao
la source
0

Vous pouvez directement rendre votre arrière-plan flou en utilisant "Visual Effect View with Blur" et "Visual Effect View with Blur and Vibrancy".

Tout ce que vous avez à faire pour créer un arrière-plan flou dans une application iOS est ...

  1. Allez chercher "Visual Effect View with Blur" dans la bibliothèque d'objets

Étape 1 Image

  1. Faites glisser le "Visual Effect View with Blur" dans votre Storyboard et configurez-le ...

Étape 2 Image

  1. Enfin ... vous rendez votre arrière-plan flou!

Présentation de l'application avant de cliquer sur un bouton!

Vue de l'application après avoir cliqué sur le bouton, ce qui rend l'arrière-plan de l'application flou!

Rencontrez Patel
la source
0

Dans le cas où cela aiderait quelqu'un, voici une extension rapide que j'ai créée sur la base de la réponse de Jordan H. Elle est écrite dans Swift 5 et peut être utilisée à partir de l'objectif 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
        }
    }

}

Remarque: si vous souhaitez flouter l'arrière-plan d'un UILabel sans affecter le texte, vous devez créer un conteneur UIView, ajoutez l'UILabel au conteneur UIView en tant que sous-vue, définissez backgroundColor du UILabel sur UIColor.clear, puis appelez blurBackground (style : UIBlurEffect.Style, fallbackColor: UIColor) sur le conteneur UIView. Voici un exemple rapide de cela écrit dans Swift 5:

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

Swift 4:

Pour ajouter une superposition ou la vue contextuelle Vous pouvez également utiliser la vue conteneur avec laquelle vous obtenez un contrôleur de vue gratuit (vous obtenez la vue conteneur à partir de la palette / bibliothèque d'objets habituelle)

Pas:

Avoir une vue (ViewForContainer sur la photo) qui contient cette vue de conteneur, pour la réduire lorsque le contenu de la vue de conteneur est affiché. Connectez la prise à l'intérieur du premier View Controller

Masquer cette vue lors du premier chargement de VC

Afficher lorsque le bouton est cliqué entrez la description de l'image ici

Pour atténuer cette vue lorsque le contenu de la vue conteneur est affiché, définissez l'arrière-plan des vues sur Noir et l'opacité sur 30%

J'ai ajouté une réponse à la création de la vue popview dans une autre question Stackoverflow https://stackoverflow.com/a/49729431/5438240

Naishta
la source
-3

La réponse simple est Ajouter une sous-vue et changer son alpha.

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