您的位置:首页 > 移动开发 > IOS开发

iOS通知栏磨砂透明背景的代码实现(高斯模糊)

2014-03-11 11:05 1146 查看
方法一.使用UIToolBar可以支持iOS7之后的高斯模糊效果

利用UIToolbar来实现是最简单的毛玻璃效果。需要什么控件自行添加到toolbar上就OK。

初始化UIToolbar,设置toolbar样式为UIBarStyleBlackTranslucent或者UIBarStyleBlackOpaque 即可。修改bartintcolor的RGB值 可修改毛玻璃色调效果。

通过本人亲身尝试,其实UIToolBar,UINavigationBar,UITabbar在IOS7上都会有高斯效果,当然,有些机型不支持(后面会总结),然后他们的表现都是一模一样的,细微的差别就是各个控件上的边框多了一些圆角,横线,但是实现高斯效果的类都是用同一个。具体是什么类,可以去研究一下,这里不深入介绍那个类,只讲怎么使用

高斯效果有系统提供的有两种效果,白色底和黑色底。具体通过设置UIBarStyle属性去设置,有UIBarStyleDefault和UIBarStyleBlack,这两种效果对比起来,Black的效果最佳,所以现在在系统本身,都是用Black样式。

但是有人想,如果只有这两种样式,能不能通过修改一些属性去改变样式呢。下面尝试了几种方法

1.alpha值

通过修改alpha值,发现,如果alpha值不为1,那么就没有高斯效果,假如你对UIToolbar进行alpha值渐变,你会发现只有等到为1的时候才会有效果,所以alpha值不能修改,会导致高斯模糊失效

2.mask

由于UIToolbar只有是矩形的样式,我们可以通过mask属性对图像进行处理,通过根据我们自定的图形,mask对应的图形,但是,如果你使用了mask,那么很不好意思,高斯模糊没有了。

3.tintColor

设置了没效果

4.barTintColor

这个是设置bar 背景颜色,设置之后,发现有效果,但是效果不明显,有兴趣可以设置一下

至于其他属性,有兴趣可以去设置一下,我是没找到其他属性了

根据好几天的接触,发现了IOS7的高斯模糊的一个特点,由于系统是支持实时更新,这部分运算明显是有效率问题的,但是我们发现,系统的好像感觉不到效率问题。通过观察,发现,如果背景图片颜色比较单一,简单,高斯模糊效果很一般,有时候就只是简单的alpha透明过去,如果背景颜色块比较明显,那么高斯效果就很清晰,可见苹果对这个的处理还是做了优化,而不是每时每刻都在刷新界面,不然效率肯定提不上来。

机型限制,目前只支持IOS7系统,4s和以上的机型,touch5,ipad上屏幕较大,支持ipad4以上

示例代码:

@property (weak, nonatomic) IBOutlet UIToolbar *bottomTabsBarBlurBgView;
@property (weak, nonatomic) IBOutlet SingleSelectTabsView *bottomTabsBar;

- (void)awakeFromNib
{
[super awakeFromNib];

self.bottomTabsBarBlurBgView.barStyle = UIBarStyleBlack;
self.bottomTabsBarBlurBgView.hidden = IS_AT_LEAST_IOS7 ? NO : YES;
self.bottomTabsBar.alpha = IS_AT_LEAST_IOS7 ? 1 : 0.95;
self.bottomTabsBar.backgroundColor = IS_AT_LEAST_IOS7 ? UIColorFromRGB(255, 255, 255, 0) : UIColorFromRGB(25, 25, 25, 1);

}







方法二.通过图片处理+实时刷新的方法实现(但是有性能问题)

(1).工程中添加Accelerate.framework。

(2).添加Category文件UIImage+ImageEffects.h/UIImage+ImageEffects.m.

#import <UIKit/UIKit.h>

@interface UIImage (ImageEffects)

- (UIImage *)applyLightEffect;
- (UIImage *)applyExtraLightEffect;
- (UIImage *)applyDarkEffect;
- (UIImage *)applyTintEffectWithColor:(UIColor *)tintColor;

- (UIImage *)applyBlurWithRadius:(CGFloat)blurRadius tintColor:(UIColor *)tintColor saturationDeltaFactor:(CGFloat)saturationDeltaFactor maskImage:(UIImage *)maskImage;

@end


#import "UIImage+ImageEffects.h"

#import <Accelerate/Accelerate.h>
#import <float.h>

@implementation UIImage (ImageEffects)

- (UIImage *)applyLightEffect
{
UIColor *tintColor = [UIColor colorWithWhite:1.0 alpha:0.3];
return [self applyBlurWithRadius:30 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil];
}

- (UIImage *)applyExtraLightEffect
{
UIColor *tintColor = [UIColor colorWithWhite:0.97 alpha:0.82];
return [self applyBlurWithRadius:20 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil];
}

- (UIImage *)applyDarkEffect
{
UIColor *tintColor = [UIColor colorWithWhite:0.11 alpha:0.73];
return [self applyBlurWithRadius:20 tintColor:tintColor saturationDeltaFactor:1.8 maskImage:nil];
}

- (UIImage *)applyTintEffectWithColor:(UIColor *)tintColor
{
const CGFloat EffectColorAlpha = 0.6;
UIColor *effectColor = tintColor;
int componentCount = CGColorGetNumberOfComponents(tintColor.CGColor);
if (componentCount == 2) {
CGFloat b;
if ([tintColor getWhite:&b alpha:NULL]) {
effectColor = [UIColor colorWithWhite:b alpha:EffectColorAlpha];
}
}
else {
CGFloat r, g, b;
if ([tintColor getRed:&r green:&g blue:&b alpha:NULL]) {
effectColor = [UIColor colorWithRed:r green:g blue:b alpha:EffectColorAlpha];
}
}
return [self applyBlurWithRadius:10 tintColor:effectColor saturationDeltaFactor:-1.0 maskImage:nil];
}

- (UIImage *)applyBlurWithRadius:(CGFloat)blurRadius tintColor:(UIColor *)tintColor saturationDeltaFactor:(CGFloat)saturationDeltaFactor maskImage:(UIImage *)maskImage
{
// Check pre-conditions.
if (self.size.width < 1 || self.size.height < 1) {
NSLog (@"*** error: invalid size: (%.2f x %.2f). Both dimensions must be >= 1: %@", self.size.width, self.size.height, self);
return nil;
}
if (!self.CGImage) {
NSLog (@"*** error: image must be backed by a CGImage: %@", self);
return nil;
}
if (maskImage && !maskImage.CGImage) {
NSLog (@"*** error: maskImage must be backed by a CGImage: %@", maskImage);
return nil;
}

CGRect imageRect = { CGPointZero, self.size };
UIImage *effectImage = self;

BOOL hasBlur = blurRadius > __FLT_EPSILON__;
BOOL hasSaturationChange = fabs(saturationDeltaFactor - 1.) > __FLT_EPSILON__;
if (hasBlur || hasSaturationChange) {
UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]);
CGContextRef effectInContext = UIGraphicsGetCurrentContext();
CGContextScaleCTM(effectInContext, 1.0, -1.0);
CGContextTranslateCTM(effectInContext, 0, -self.size.height);
CGContextDrawImage(effectInContext, imageRect, self.CGImage);

vImage_Buffer effectInBuffer;
effectInBuffer.data     = CGBitmapContextGetData(effectInContext);
effectInBuffer.width    = CGBitmapContextGetWidth(effectInContext);
effectInBuffer.height   = CGBitmapContextGetHeight(effectInContext);
effectInBuffer.rowBytes = CGBitmapContextGetBytesPerRow(effectInContext);

UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]);
CGContextRef effectOutContext = UIGraphicsGetCurrentContext();
vImage_Buffer effectOutBuffer;
effectOutBuffer.data     = CGBitmapContextGetData(effectOutContext);
effectOutBuffer.width    = CGBitmapContextGetWidth(effectOutContext);
effectOutBuffer.height   = CGBitmapContextGetHeight(effectOutContext);
effectOutBuffer.rowBytes = CGBitmapContextGetBytesPerRow(effectOutContext);

if (hasBlur) {
// A description of how to compute the box kernel width from the Gaussian
// radius (aka standard deviation) appears in the SVG spec:
// http://www.w3.org/TR/SVG/filters.html#feGaussianBlurElement //
// For larger values of 's' (s >= 2.0), an approximation can be used: Three
// successive box-blurs build a piece-wise quadratic convolution kernel, which
// approximates the Gaussian kernel to within roughly 3%.
//
// let d = floor(s * 3*sqrt(2*pi)/4 + 0.5)
//
// ... if d is odd, use three box-blurs of size 'd', centered on the output pixel.
//
CGFloat inputRadius = blurRadius * [[UIScreen mainScreen] scale];
NSUInteger radius = floor(inputRadius * 3. * sqrt(2 * M_PI) / 4 + 0.5);
if (radius % 2 != 1) {
radius += 1; // force radius to be odd so that the three box-blur methodology works.
}
vImageBoxConvolve_ARGB8888(&effectInBuffer, &effectOutBuffer, NULL, 0, 0, radius, radius, 0, kvImageEdgeExtend);
vImageBoxConvolve_ARGB8888(&effectOutBuffer, &effectInBuffer, NULL, 0, 0, radius, radius, 0, kvImageEdgeExtend);
vImageBoxConvolve_ARGB8888(&effectInBuffer, &effectOutBuffer, NULL, 0, 0, radius, radius, 0, kvImageEdgeExtend);
}
BOOL effectImageBuffersAreSwapped = NO;
if (hasSaturationChange) {
CGFloat s = saturationDeltaFactor;
CGFloat floatingPointSaturationMatrix[] = {
0.0722 + 0.9278 * s,  0.0722 - 0.0722 * s,  0.0722 - 0.0722 * s,  0,
0.7152 - 0.7152 * s,  0.7152 + 0.2848 * s,  0.7152 - 0.7152 * s,  0,
0.2126 - 0.2126 * s,  0.2126 - 0.2126 * s,  0.2126 + 0.7873 * s,  0,
0,                    0,                    0,  1,
};
const int32_t divisor = 256;
NSUInteger matrixSize = sizeof(floatingPointSaturationMatrix)/sizeof(floatingPointSaturationMatrix[0]);
int16_t saturationMatrix[matrixSize];
for (NSUInteger i = 0; i < matrixSize; ++i) {
saturationMatrix[i] = (int16_t)roundf(floatingPointSaturationMatrix[i] * divisor);
}
if (hasBlur) {
vImageMatrixMultiply_ARGB8888(&effectOutBuffer, &effectInBuffer, saturationMatrix, divisor, NULL, NULL, kvImageNoFlags);
effectImageBuffersAreSwapped = YES;
}
else {
vImageMatrixMultiply_ARGB8888(&effectInBuffer, &effectOutBuffer, saturationMatrix, divisor, NULL, NULL, kvImageNoFlags);
}
}
if (!effectImageBuffersAreSwapped)
effectImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

if (effectImageBuffersAreSwapped)
effectImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}

// Set up output context.
UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]);
CGContextRef outputContext = UIGraphicsGetCurrentContext();
CGContextScaleCTM(outputContext, 1.0, -1.0);
CGContextTranslateCTM(outputContext, 0, -self.size.height);

// Draw base image.
CGContextDrawImage(outputContext, imageRect, self.CGImage);

// Draw effect image.
if (hasBlur) {
CGContextSaveGState(outputContext);
if (maskImage) {
CGContextClipToMask(outputContext, imageRect, maskImage.CGImage);
}
CGContextDrawImage(outputContext, imageRect, effectImage.CGImage);
CGContextRestoreGState(outputContext);
}

// Add in color tint.
if (tintColor) {
CGContextSaveGState(outputContext);
CGContextSetFillColorWithColor(outputContext, tintColor.CGColor);
CGContextFillRect(outputContext, imageRect);
CGContextRestoreGState(outputContext);
}

// Output image is ready.
UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

return outputImage;
}

@end


(3).使用Sample代码(图片可以通过截屏背景得到,从而有磨砂透明的盖层效果)。————>苹果官方Demo<————

- (void)viewDidLoad
{
[super viewDidLoad];

const CGFloat fontSize = 25.f;
const NSString *text = @"Over layer string.";
CGSize size = [text sizeWithAttributes:@{NSFontAttributeName: [UIFont fontWithName:@"Avenir Next" size:fontSize]}];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(30, 200, size.width, size.height)];
label.font = [UIFont fontWithName:@"Avenir Next" size:fontSize];
label.textAlignment = NSTextAlignmentNatural;
label.backgroundColor = [UIColor clearColor];
label.text = (NSString *)text;

UIImage *image = [UIImage imageNamed:@"wat.png"];
UIImage *blurredImage = [image applyBlurWithRadius:10 tintColor:[UIColor colorWithWhite:0 alpha:0.25] saturationDeltaFactor:1.f maskImage:nil];

UIImageView *imageView = [[UIImageView alloc] initWithImage:blurredImage];
imageView.frame = CGRectMake(0, 0, 500, 375);

CGFloat imgScale = image.scale;
CGRect labelFrame = label.frame;
CGRect realRect = CGRectMake(labelFrame.origin.x * imgScale, labelFrame.origin.y * imgScale, labelFrame.size.width * imgScale, labelFrame.size.height * imgScale);
CGImageRef labelPatternImage = CGImageCreateWithImageInRect(image.CGImage, realRect);
label.textColor = [UIColor colorWithPatternImage:[UIImage imageWithCGImage:labelPatternImage scale:image.scale orientation:UIImageOrientationUp]];
CGImageRelease(labelPatternImage);

[self.view addSubview:imageView];
[self.view addSubview:label];
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: