创建模糊的叠加视图


Answers:


552

您可以使用UIVisualEffectView来达到此效果。这是一个本机API,已针对性能和更长的电池寿命进行了微调,并且易于实现。

迅速:

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

目标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];
}

如果要以模态方式呈现此视图控制器以模糊基础内容,则需要将模式呈现样式设置为“当前上下文”,并将背景色设置为“清除”,以确保基础视图控制器一旦呈现在顶部即可保持可见。


7
为了澄清insertSubView:belowSubView:此代码中的注释,我使用以下内容将模糊设置为视图的背景:view.insertSubview(blurEffectView, atIndex: 0)
Michael Voccola 2015年

2
参考上面的答案,是否需要检查“是否(!UIAccessibilityIsReduceTransparencyEnabled())”,还是可以跳过?
GKK

3
如果要显示视图控制器,请确保更改modalPresentationStyle = .overCurrentContext以及将背景颜色设置为透明
Shardul 2016年

3
很棒!需要单个更改:[se​​lf.view insertSubview:blurEffectView atIndex:1];
Abhishek Thapliyal

2
在iOS 11中,我发现无需手动检查UIAccessibilityIsReduceTransparencyEnabled()
Nate Whittaker '18

284

核心形象

由于屏幕快照中的图像是静态的,因此您可以CIGaussianBlur从Core Image(需要iOS 6)中使用。这是示例:https : //github.com/evanwdavis/Fun-with-Masks/blob/master/Fun%20with%20Masks/EWDBlurExampleVC.m

请注意,这比此页面上的其他选项要慢。

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

堆栈模糊(盒+高斯)

  • StackBlur这实现了Box和Gaussian模糊的混合。比非加速高斯快7倍,但不像盒子模糊那么丑陋。在此处(Java插件版本)或此处(JavaScript版本)中查看演示。该算法用于KDE和Camera +等。它不使用Accelerate Framework,但速度很快。

加速框架

  • WWDC 2013的 “在iOS上实现Eningging UI的实现”会话中,Apple解释了如何创建模糊的背景(在14:30),并提到了applyLightEffect使用Accelerate.framework在示例代码中实现的方法。

  • GPUImage使用OpenGL着色器创建动态模糊。它具有几种模糊类型:GPUImageBoxBlurFilter,GPUImageFastBlurFilter,GaussianSelectiveBlur,GPUImageGaussianBlurFilter。甚至还有一个GPUImageiOSBlurFilter,它“应该完全复制iOS 7的控制面板提供的模糊效果”(tweet文章)。这篇文章是详尽而翔实的。

    -(UIImage *)模糊GPUImage:(UIImage *)具有BlurLevel:(NSInteger)blur的图像{
        GPUImageFastBlurFilter * blurFilter = [GPUImageFastBlurFilter新];
        blurFilter.blurSize =模糊;
        UIImage * result = [blurFilter imageByFilteringImage:image];
        返回结果;
    }

其他的东西

安迪·马图沙克(Andy Matuschak)在Twitter上:“您知道,在许多地方,我们似乎都是实时进行的,而且它的技巧很巧妙。”

doubleencore.com上,他们说:“我们发现,在大多数情况下,模糊半径增加10磅加上饱和度增加10磅最能模仿iOS 7的模糊效果。”

窥视苹果公司SBFProceduralWallpaperView的私有标题。

最后,这不是真正的模糊,但请记住,您可以设置rasterizationScale以获得像素化图像:http : //www.dimzzy.com/blog/2010/11/blur-effect-for-uiview/


感谢您的回答!解决了一个问题。但是,我们还有另一个问题。如何在iOS 7中获取封面图像。
kondratyevdev

如果您要说的是如何从手机中获取背景墙纸图像,则目前还不知道。我没有在API diff中看到该功能。也许它使用私有API。
Jano 2013年

我注意到的一件事(我可能完全错了)是苹果的模糊效果似乎也增加了一点色彩饱和度。因此,我认为这不是简单的高斯模糊。
xtravar 2013年

请记住返回时的比例因子,UIImage否则它将在Retina设备上看起来太大...
Stephen Darlington

您知道这种效果是否可以应用于UITableViewCell而不降低性能吗?
莱昂纳多·

15

我决定从已接受的答案中发布书面的Objective-C版本,只是为了在此问题中提供更多选择。

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

如果您想只支持纵向模式,或者我只是在此函数中添加一个标志以使用或不使用它们,则可以删除这些约束。


1
对于新手(我),调用上述方法的一种方法是:[self applyBlurToView:self.view withEffectStyle:UIBlurEffectStyleDark andConstraints:YES]; (感谢NorthBlast)
tmr

14

我认为我不允许发布代码,但是上面提到WWDC示例代码的帖子是正确的。这是链接:https : //developer.apple.com/downloads/index.action?name=WWDC%202013

您要查找的文件是UIImage上的类别,方法是applyLightEffect。

正如我在上面的评论中指出的那样,Apple Blur除饱和度外还有饱和度和其他情况。如果您想模仿他们的风格,那么简单的模糊是不会的。


8
该链接已断开。这是正确的链接:developer.apple.com/downloads/index.action?
name=WWDC%202013

请注意,此示例代码需要XCode 5.0和iOS SDK 7.0(尚未公开发布)
Mike Gledhill

感谢固定链接,但是其中有一些示例代码,其中包含相关的UIImage类别?
莱昂纳多·

1
@Leonardo iOS_RunningWithASnap.zip
John Starr Dewar

1
...或iOS_UIImageEffects.zip更具体地说就是这个。
John Starr Dewar

9

我认为,最简单的解决方案是重写UIToolbar,它模糊了iOS 7中的所有功能。虽然很偷偷摸摸,但实现起来非常简单,而且速度很快!

你可以用任何观点做到这一点,只是让它的子类UIToolbar来代替UIView。您甚至可以使用UIViewControllerview属性来执行此操作,例如...

1)创建一个新的类,它是“的子类”,UIViewController并选中“使用XIB作为用户界面”复选框。

2)选择视图,然后转到右侧面板中的身份检查器(alt-command-3)。将“类”更改为UIToolbar。现在转到属性检查器(alt-command-4),并将“背景”颜色更改为“清除颜色”。

3)在主视图中添加一个子视图,并将其连接到界面中的IBOutlet。叫它backgroundColorView。在实现(.m)文件中,它是一个私有类别,看起来像这样。

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

4)转到视图控制器实现(.m)文件并更改-viewDidLoad方法,如下所示:

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

这将为您提供深灰色视图,从而模糊其后的所有内容。使用OS / SDK提供的唾手可得的功能,无需做任何有趣的事情,也不会使核心图像变慢。

您可以将此视图控制器的视图添加到另一个视图,如下所示:

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

// animate the self.blurViewController into view

让我知道是否有任何不清楚的地方,我们将竭诚为您服务!


编辑

UIToolbar在7.0.3中进行了更改,以在使用彩色模糊时产生可能不希望的效果。

我们曾经能够使用设置颜色barTintColor,但是如果您之前进行过设置,则需要将alpha分量设置为小于1。否则,您的UIToolbar将是完全不透明的颜色-没有模糊。

这可以通过以下方式实现:(注意self是的子类UIToolbar

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

这会使模糊的视图呈现蓝色调。


1
不坏人。我在视图中使用了以下三行内容: self.backgroundColorView.opaque = NO; self.backgroundColorView.alpha = 0.5; self.backgroundColorView.backgroundColor = [UIColor colorWithWhite:0.3 alpha:1];但是背景并没有模糊,只是使效果更好。还是谢谢你!
IgniteCoders

1
使用此技术完全看不到任何模糊。它只是创建一个彩色的叠加层。
MusiGenesis

确保彩色叠加层的Alpha值小于1。您可以使用不带视图控制器的UIToolbar,根据您的需要,它可能会更简单。
2014年

整洁的把戏人。我将视图转换为情节提要中的UIToolbar类,然后将视图背景更改为纯色。它给了白色模糊的背景。如果您使Alpha小于1,模糊效果将消失。
Badr

9

这是Swift中使用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

自定义模糊比例

您可以尝试 UIVisualEffectView将自定义设置设置为-

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

输出:-用于 blurEffect.setValue(1...blurEffect.setValue(2.. 在此处输入图片说明 在此处输入图片说明


3
如果在下一版本的iOS中更改此参数的名称,它将停止工作。
阿里尔·博格齐耶维奇

@ArielBogdziewicz当前正在工作。如果wwdc中有任何API变体,我将进行更新。
杰克,

嗯...不,您永远不想访问私有API。由于某种原因,它们是私人的。它们会改变,破裂,和/或Apple会拒绝您的应用程序。使用另一种方法,有很多。寻找黑客的荣誉,但不推荐。
n13

@Jack非常感谢您的回答!这是我发现问题的唯一解决方案:根据另一个视图的位置模糊视图。但是,我还有另一个问题。有什么方法可以在UIBlurEffect之上增加活力吗?如果是这样,怎么办?我是否需要在我的blurView之上为此创建另一个视图?我曾尝试过,但使用时它总是崩溃。(NSClassFromString("_UICustomVibrancyEffect") as! UIVibrancyEffect.Type).init()非常感谢您的帮助!
莫里茨

@Moritz尚未尝试。但这应该可以。您可以尝试并检查。
杰克

7

这是使用UIViewPropertyAnimator添加自定义模糊而不用私有API的简单方法:

首先,声明类属性:

var blurAnimator: UIViewPropertyAnimator!

然后在中设置模糊视图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.    

注意:此解决方案不适用于UICollectionView/ UITableView电池


1
如果要控制UIVisualEffectView的透明度,这是我找到的唯一解决方案。
Denis Kutlubaev


5

可以接受的答案是正确的,但如果使用以下方式显示此视图(您想要背景模糊的视图),则此处缺少重要的步骤

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

默认情况下,这将消除模糊,因为UIKit会删除您实际上是模糊的演示者的视图。为了避免删除,请在上一行之前添加此行

vc.modalPresentationStyle = UIModalPresentationOverFullScreen;

或使用其他Over样式。


3

目标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)

来自:https : //stackoverflow.com/a/24083728/4020910


2

使用UIImageEffects

对于需要更多控制权的人,您可以使用Apple的UIImageEffects示例代码。

您可以UIImageEffects从Apple开发人员库中复制以下代码:模糊和着色图像

这是应用方法:

#import "UIImageEffects.h"
...

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

我如何迅速使用它
devjme,2018年

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

偶然发现这一点,给了我非常棒的结果(几乎与Apple的结果相同),并使用了Acceleration框架。- http://pastebin.com/6cs6hsyQ *并非由我写的


8
实际上,这是WWDC 2013的Apple代码,版权有误。
Shmidt 2013年

WWDC的代码是否受版权保护,并且仅允许付费订阅的会员访问?
SAFAD

1
可能是这样,但是上面的代码是我使用Google找到的。我没有更改版权,并且我假设(并且仍然假设)它具有正确的版权声明。如果苹果不同意,他们应该努力将其删除。我看不到相关性。
2014年

1

该答案基于Mitja Semolic出色的早期答案。我将其转换为swift 3,对注释中的情况进行了说明,使其成为UIViewController的扩展,以便任何VC都可以随意调用它,添加了未模糊的视图以显示选择性应用程序,并添加了完成块,以便调用视图控制器可以在模糊结束时做任何想做的事情。

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

我已经确认它可以在iOS 10.3.1和iOS 11上使用


1

@Joey答案的重要补充

这适用于您要使用呈现模糊背景的UIViewController情况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];

请享用!


1

Swift 3版本的Kev回答可返回模糊图像-

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

2019年代码

这是使用惊人的@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
    }

{此外:作为一般的iOS工程,您didMoveToWindow可能比更加适合您didMoveToSuperview。其次,您可以使用其他方法进行拆解,但拆解是此处显示的两行代码。}

BlurryBall只是一个UIVisualEffectView。注意视觉效果视图的初始化。如果您碰巧需要圆角或其他任何东西,请在本课程中进行。

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

这是已接受的答案中提供的解决方案的Swift 2.0代码:

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

如果为tableView添加一个黑暗的模糊视图,它将很漂亮:

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

您可以使用“带有模糊效果的视觉效果视图”和“带有模糊和鲜艳度的视觉效果视图”直接制作背景模糊。

在iOS应用程序中制作模糊背景所需要做的就是...

  1. 转到对象库中搜索“带有模糊效果的视觉效果视图”

第1步图片

  1. 将“带有模糊效果的视觉效果视图”拖到情节提要中并进行设置。

步骤2图片

  1. 最后,您可以使应用程序背景模糊!

单击任何按钮之前的应用程序布局!

单击按钮后的应用程序视图,这会使整个应用程序背景模糊!


0

如果这对任何人都有用,这是我根据Jordan H的答案创建的快速扩展。它是用Swift 5编写的,可以在Objective 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
        }
    }

}

注意:如果要模糊UILabel的背景而不影响文本,则应创建一个容器UIView,将UILabel作为子视图添加到容器UIView中,将UILabel的backgroundColor设置为UIColor.clear,然后调用blurBackground(style :UIBlurEffect.Style,fallbackColor:UIColor)。这是用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

斯威夫特4:

添加叠加或弹出视图您还可以使用Container View,使用该容器可获取免费的View Controller(您可以从通常的对象选项板/库中获得Container View)

脚步:

有一个包含此容器视图的视图(照片中为ViewForContainer),以在显示容器视图的内容时将其变暗。连接第一个View Controller内部的插座

在第一个VC加载时隐藏此视图

单击“按钮”时取消隐藏

要在显示“容器视图”内容时将此视图变暗,请将“视图背景”设置为“黑色”,将不透明度设置为30%

我在其他Stackoverflow问题https://stackoverflow.com/a/49729431/5438240中为popview视图创建添加了答案


-3

简单的答案是添加一个子视图并更改其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];
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.