![](https://istack.dev59.com/QXEg4m.webp)
UIVisualEffectView
来实现这个效果。这是一个本地API,已经过优化以提高性能和电池寿命,而且易于实现。
Swift:
//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”,并将背景颜色设置为透明,以确保在此视图控制器呈现在顶部时底层视图控制器仍然可见。
由于截图中的图像是静态的,因此您可以使用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 (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;
}
在WWDC 2013的“实现iOS上引人入胜的UI”会议中,苹果解释了如何创建模糊的背景(在14:30处),并提到使用Accelerate.framework实现的一个applyLightEffect
方法。
GPUImage使用OpenGL着色器创建动态模糊。它有几种类型的模糊:GPUImageBoxBlurFilter、GPUImageFastBlurFilter、GaussianSelectiveBlur、GPUImageGaussianBlurFilter。甚至还有一个GPUImageiOSBlurFilter,它“应该完全复制iOS 7控制面板提供的模糊效果”(tweet,article)。这篇文章详细而且信息量大。
-(UIImage *)blurryGPUImage:(UIImage *)image withBlurLevel:(NSInteger)blur { GPUImageFastBlurFilter *blurFilter = [GPUImageFastBlurFilter new]; blurFilter.blurSize = blur; UIImage *result = [blurFilter imageByFilteringImage:image]; return result; }这段代码是用于使用GPUImage对图片进行模糊处理的。其中,blur参数表示模糊程度,值越大则图片越模糊。函数返回处理后的图片。
来自indieambitions.com: 使用vImage执行模糊算法在iOS-RealTimeBlur中也有使用。
来自Nick Lockwood: https://github.com/nicklockwood/FXBlurView示例显示了滚动视图上的模糊效果。它使用dispatch_async进行模糊,然后同步调用UITrackingRunLoopMode更新以使模糊不会被UIScrollView的滚动影响而产生延迟。这在Nick的书iOS核心动画中有解释,顺带一提,这是一本很棒的书。
iOS-blur这将UIToolbar的模糊层放置在其他位置。如果您使用此方法,苹果将拒绝您的应用程序。请查看https://github.com/mochidev/MDBlurView/issues/4
来自Evadne博客: LiveFrost:快速、同步的UIView快照滤镜。伟大的代码和阅读材料。这篇文章中的一些想法:
Andy Matuschak 在 Twitter 上说:“你知道,很多看起来像我们实时处理的地方,其实都是静态的,但有一些巧妙的技巧。”
在 doubleencore.com 上他们说:“我们发现,在大多数情况下,模糊半径为 10pt,饱和度增加 10pt 最能模仿 iOS 7 的模糊效果。”
查看 Apple 的 SBFProceduralWallpaperView 的私有头文件。
最后,这并不是真正的模糊效果,但请记住,您可以设置 rasterizationScale 来获得像素化的图像:http://www.dimzzy.com/blog/2010/11/blur-effect-for-uiview/
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
单元格。
我决定发布一份书面的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;
}
如果您只支持竖屏模式,或者我在此函数中添加一个标志来使用它们或不使用它们,则可以删除限制。
我不认为我被允许发布代码,但上面提到WWDC示例代码的帖子是正确的。以下是链接:https://developer.apple.com/downloads/index.action?name=WWDC%202013
你需要找到的文件是UIImage中的分类,并且方法是applyLightEffect。
正如我在评论中提到的,苹果模糊效果除了模糊之外还有饱和度和其他一些因素。如果你想要模仿他们的风格,仅仅进行简单的模糊处理是不够的。
这里是使用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;
}
@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];
}
[self addChildViewController:self.blurViewController];
[self.view addSubview:self.blurViewController.view];
[self.blurViewController didMoveToParentViewController:self];
// animate the self.blurViewController into view
如果有不清楚的地方,请告诉我,我很乐意帮助!
在7.0.3中,UIToolbar已经更改,使用彩色模糊可能会产生不良影响。
我们以前可以使用barTintColor
设置颜色,但如果您之前正在这样做,则需要将alpha组件设置为小于1。否则,您的UIToolbar将成为完全不透明的颜色-没有模糊效果。
可以通过以下方法实现:(请记住self
是UIToolbar
的子类)
UIColor *color = [UIColor blueColor]; // for example
self.barTintColor = [color colorWithAlphaComponent:0.5];
self.backgroundColorView.opaque = NO;
self.backgroundColorView.alpha = 0.5;
self.backgroundColorView.backgroundColor = [UIColor colorWithWhite:0.3 alpha:1];
但是背景并没有被模糊处理,只是产生了一个很好的覆盖效果。无论如何还是谢谢你! - IgniteCoders您可以尝试使用自定义设置的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...
这里是两张图片,你可以通过第一张图片和第二张图片中的模糊效果看到结果。请注意,这些效果是通过在 iOS 中应用 Core Image 框架中的高斯滤镜(CIGaussianBlur)来实现的。如果有人需要,这是我基于Jordan H的答案创建的一个Swift扩展。它使用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添加为其子视图,将UILabel的backgroundColor设置为UIColor.clear,然后在容器UIView上调用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)
insertSubView:belowSubView:
注释,我使用以下代码将模糊效果设置为视图的背景:view.insertSubview(blurEffectView, atIndex: 0)
。 - Michael VoccolaUIAccessibilityIsReduceTransparencyEnabled()
。 - Nate Whittaker