创build一个模糊重叠视图

在新的iOS的音乐应用程序中,我们可以看到一个模糊的视图背后的专辑封面。

怎么能这样做呢? 我已阅读文档,但没有find任何东西。

对于iOS 8+,您可以使用UIVisualEffectView来达到这个效果。 这是一个原生的API,它已经经过了性能和电池寿命的优化调整,而且很容易实现。

Swift 3:

 //only apply the blur if the user hasn't disabled transparency effects if !UIAccessibilityIsReduceTransparencyEnabled() { self.view.backgroundColor = UIColor.clear 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.black } 

Objective-C的:

 if (!UIAccessibilityIsReduceTransparencyEnabled()) { self.view.backgroundColor = [UIColor clearColor]; UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark]; UIVisualEffectView *blurEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect]; blurEffectView.frame = self.view.bounds; blurEffectView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; [self.view addSubview:blurEffectView]; } else { self.view.backgroundColor = [UIColor blackColor]; } 

核心形象

由于截图中的图像是静态的,因此可以使用Core Image中的CIGaussianBlur (需要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 (eg 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版本)。 这个algorithm被用在KDE和Camera +等等。 它不使用Accelerate Framework,但速度很快。

加速框架

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

  • GPUImage使用OpenGL着色器来创builddynamic模糊。 它有几种types的模糊:GPUImageBoxBlurFilter,GPUImageFastBlurFilter,GaussianSelectiveBlur,GPUImageGaussianBlurFilter。 甚至有一个GPUImageiOSBlurFilter“应该完全复制iOS 7控制面板提供的模糊效果”( tweet , 文章 )。 文章详细和信息。

     - (UIImage *)blurryGPUImage:(UIImage *)图像与BlurLevel:(NSInteger)blur {
         GPUImageFastBlurFilter * blurFilter = [GPUImageFastBlurFilter new];
         blurFilter.blurSize = blur;
         UIImage * result = [blurFilter imageByFilteringImage:image];
        返回结果;
     }
  • 来自indieambitions.com: 使用vImage进行模糊处理 。 该algorithm也用于iOS-RealTimeBlur 。

  • 来自Nick Lockwood: https : //github.com/nicklockwood/FXBlurView该示例显示滚动视图上的模糊。 它使用dispatch_async模糊,然后同步以使用UITrackingRunLoopMode调用更新,以便在UIKit给予UIScrollView的滚动优先级时模糊不会被延迟。 这是在尼克的书籍iOS核心animation ,这是很好的解释。

  • iOS的模糊这将UIToolbar的模糊层,并把它放在其他地方。 如果您使用此方法,苹果将拒绝您的应用程序。 请参阅https://github.com/mochidev/MDBlurView/issues/4

  • 从Evadne博客: LiveFrost:快速,同步的UIView快照包含 。 伟大的代码和一个伟大的阅读。 这篇文章的一些想法:

    • 使用串行队列来限制来自CADisplayLink的更新。
    • 重新使用位图上下文,除非边界改变。
    • 使用 – [CALayer renderInContext:]以0.5f比例因子绘制较小的图像。

其他的东西

Andy Matuschak在Twitter上说 :“你知道,很多地方看起来像是我们正在做的事情,而且它们是聪明的技巧。

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

查看Apple的SBFProceduralWallpaperView的私人标题。

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

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

您正在寻找的文件是UIImage上的类别,方法是applyLightEffect。

正如我在评论中提到的那样,苹果模糊已经饱和,除了模糊外,还有其他一些事情正在发生。 一个简单的模糊不会做…如果你正在寻找模仿他们的风格。

我决定从接受的答案发布一个书面的Objective-C版本,只是为了在这个问题上提供更多的select。

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

如果你只想支持肖像模式,或者只是给这个函数添加一个标志来使用它们,那么约束可以被删除。

我认为最简单的解决scheme是重写UIToolbar,这会在iOS 7中模糊背后的一切。它很偷偷摸摸,但实现起来非常简单,而且速度很快!

你可以用任何视图来做到,只要把它做成UIToolbar的子类而不是UIView 。 你甚至可以用UIViewControllerview属性来完成它,例如…

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

2)select视图并转到右侧面板的身份检查器(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将是完全不透明的颜色 – 没有模糊。

这可以实现如下:(铭记selfUIToolbar的子类)

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

这将给模糊的视图带来蓝色的色调。

这里是使用CIGaussianBlur的Swift中的快速实现:

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

被接受的答案是正确的,但是在这里丢失了一个重要的步骤,如果这个视图 – 你想要模糊的背景 – 被使用

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

默认情况下,这将消除模糊UIKit删除演示者的视图,你实际上模糊。 要避免这种删除,请在上一行之前添加此行

vc.modalPresentationStyle = UIModalPresentationOverFullScreen;

或者使用其他Over样式。

发现这个意外,给我真的很棒(与苹果公司近乎重复)的结果,并使用加速框架。 – http://pastebin.com/6cs6hsyQ *不是我写的

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

Objective-C的

 UIVisualEffect *blurEffect; blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark]; UIVisualEffectView *visualEffectView; visualEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect]; visualEffectView.frame = self.accessImageView.bounds; [self.accessImageView addSubview:visualEffectView]; 

SWIFT 3.0

 let blurEffect = UIBlurEffect(style: UIBlurEffectStyle.dark) let blurEffectView = UIVisualEffectView(effect: blurEffect) blurEffectView.frame = view.bounds blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight] view.addSubview(blurEffectView) 

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

Apple为UIImage类提供了一个名为UIImage + ImageEffects.h的扩展。 在这个课堂上,你有所需的模糊你的观点的方法

使用UIImageEffects

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

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

以下是如何应用它:

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

以下是接受答案中提供的解决scheme的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() } 

这个答案是基于Mitja Semolic早期的优秀答案 。 我已经将它转换为swift 3,添加了关于在coments中发生了什么的解释,使其成为UIViewController的扩展,以便任何VC可以随意调用它,添加一个未经视图的视图来显示select性应用程序,并添加一个完成块调用视图控制器可以完成模糊任务。

  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

简单的答案是添加一个子视图,并更改它的阿尔法。

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