创建模糊叠加视图

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

这样的事情是如何完成的呢?我看了文件,但什么都没发现。

.

299468 次浏览

核心形象

由于截图中的图像是静态的,你可以使用Core image中的CIGaussianBlur(需要iOS 6)

注意,这比本页上的其他选项要慢。

#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这个函数实现了盒状模糊和高斯模糊的混合。比非加速高斯快7倍,但不像盒子模糊那么难看。请参见在这里 (Java插件版本)或在这里 (JavaScript版本)中的演示。该算法用于KDE和Camera+等。它不使用加速框架,但速度很快。

加速框架

  • 在会议“在iOS上实现吸引人的UI”从WWDC 2013苹果解释了如何创建一个模糊的背景(在14:30),并提到了一个方法applyLightEffect实现在示例代码使用加速.框架。

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

-(UIImage *)blurryGPUImage:(UIImage *)image withBlurLevel:(NSInteger)blur {
GPUImageFastBlurFilter *blurFilter = [GPUImageFastBlurFilter new];
blurFilter.blurSize = blur;
UIImage *result = [blurFilter imageByFilteringImage:image];
return result;
}
  • 来自indieambitions.com: 使用vImage执行模糊。该算法还用于iOS-RealTimeBlur

  • 来自Nick Lockwood: https://github.com/nicklockwood/FXBlurView这个例子显示了一个滚动视图的模糊。它用dispatch_async模糊,然后用UITrackingRunLoopMode同步调用更新,所以当UIKit给UIScrollView滚动更多优先级时,模糊不会滞后。这在Nick的书iOS Core Animation中有解释,顺便说一句,这很棒。

  • iOS-blur这采取模糊层的UIToolbar,并把它放在其他地方。如果你使用这种方法,苹果将拒绝你的应用。参见https://github.com/mochidev/MDBlurView/issues/4

  • 来自Evadne博客:LiveFrost:快速,同步UIView快照卷积。很棒的代码和阅读。以下是这篇文章的一些想法:

    • 使用串行队列限制来自CADisplayLink的更新。
    • 除非边界改变,否则重用位图上下文。
    • 使用-[CALayer renderInContext:]绘制较小的图像,缩放因子为0.5f。
    • 李< / ul > < / >

    其他东西

    Andy Matuschak 在推特上:“你知道,很多地方看起来我们是在实时做的,它是静态的,有聪明的技巧。”

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

    苹果SBFProceduralWallpaperView的私有头文件。

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

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

你要找的文件是UIImage上的category,方法是applyLightEffect。

正如我在上面的评论中提到的,除了模糊,苹果模糊还有饱和度和其他东西。简单的模糊是不行的……如果你想模仿他们的风格。

这是偶然发现的,给了我真正伟大的(几乎复制与苹果)的结果,并使用加速框架。——http://pastebin.com/6cs6hsyQ 不是我写的

我认为最简单的解决方案是覆盖UIToolbar,它在iOS 7中模糊了它后面的所有东西。这很狡猾,但实现起来非常简单,而且速度很快!

你可以对任何视图这样做,只要使它成为UIToolbar的子类而不是UIView。你甚至可以用UIViewControllerview属性来实现,例如…

1)创建一个名为“UIViewController的子类”的新类,并选中“With XIB for user interface”。

2)选择View,进入右边面板中的标识检查器(alt-command-3)。将“Class”更改为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];
}

这将给你一个深灰色的视图,它模糊了它后面的一切。没有有趣的业务,没有缓慢的核心图像模糊,使用操作系统/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];

这将给模糊的视图一个蓝色的色调。

你可以使用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
}

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

如果你以模态方式呈现这个视图控制器来模糊底层内容,你需要将模态呈现风格设置为Over Current Context,并将背景颜色设置为clear,以确保底层视图控制器在顶部呈现时仍然可见。

苹果为UIImage类提供了一个名为UIImage+ImageEffects.h的扩展。在这个类中,您可以使用所需的方法来模糊视图

我决定发布一个书面的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;
}

如果你想要,如果你只支持纵向模式,或者我只是在这个函数中添加了一个标志来使用它们,可以删除这些限制。

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

公认的答案是正确的,但这里缺少一个重要的步骤,如果这个视图-您想要模糊的背景-是使用

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

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

vc.modalPresentationStyle = UIModalPresentationOverFullScreen;

或者使用其他Over样式。

使用UIImageEffects

对于那些想要更多控制权的人,你可以使用Apple的UIImageEffects样例代码。

你可以从苹果的开发者库中复制UIImageEffects 的代码:模糊和着色图像

下面是如何应用它:

#import "UIImageEffects.h"
...


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

下面是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;
}

简单的答案是添加一个子视图并改变它的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];

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

objective - c

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

斯威夫特3.0

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

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

这个答案基于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

这是乔伊回答的重要补充

这适用于你想用UINavigationController呈现一个模糊背景UIViewController的情况。

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

享受吧!

斯威夫特4:

你也可以使用容器视图,它可以让你获得一个免费的视图控制器(你可以从通常的对象面板/库中获得容器视图)。

步骤:

有一个视图(图片中的ViewForContainer)持有这个容器视图,当容器视图的内容显示时,使其暗淡。连接第一个视图控制器内部的出口

当第一个VC加载时隐藏这个视图

当按钮点击此处输入图像描述时取消隐藏

当容器视图内容显示时,要使该视图变暗,将视图背景设置为黑色,不透明度设置为30%

我已经在其他Stackoverflow问题中添加了popview视图创建的答案 https://stackoverflow.com/a/49729431/5438240 < / p >

enter image description here

在Xcode中你可以很容易地做到。遵循xcode中的步骤。在你的uiview或imageview上拖动视觉效果视图。

快乐编码:)

如果为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

自定义模糊比例

你可以试试 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)
}
}

Output:- for blurEffect.setValue(1... &blurEffect.setValue(2.. enter image description here enter image description here < / p >

Swift 3版本的凯文的答案返回模糊的图像-

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

你可以直接使用“带模糊的视觉效果视图”和“带模糊和活力的视觉效果视图”来创建背景模糊。

所有你需要做的是在iOS应用程序模糊背景…

  1. 在对象库中搜索“视觉效果模糊视图”

步骤1图像

  1. 在你的故事板中拖动“带模糊的视觉效果视图”并设置它…

步骤2图像

  1. 最后……你使你的应用程序背景模糊!

应用程序布局之前点击任何按钮!< / >

应用程序视图点击按钮后使整个应用程序背景模糊!< / >

下面是一个简单的方法来添加自定义模糊,而不用使用UIViewPropertyAnimator与私有api讨价还价:

首先,声明class属性:

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单元格

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

为了帮助大家,下面是我根据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。样式,fallbackColor: UIColor)的容器UIView。下面是用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)