iOS(OC)毛玻璃效果(已更新更完美方案)

参考

网上毛玻璃有好几个方式, 先说官方的UIBlurEffect, 可以在平面任意View上添加效果, 但是现在看来, 效果差强人意, 不推荐, 如有需要, 跳到 demo演练

更新版本, 还是用图片的高斯模糊来做, 但是可以实现任意view上模糊

/// 实现一个分类方法
@implementation UIView (PPEX)

/// 设置高斯模糊(在原有基础上盖一个imageView)需要在有size之后设置
/// - Parameter inputRadius: 模糊程度, 数字越大越模糊, 设置0 , 就是移除
- (void)tryToAddBlurEffectWithInputRadius:(CGFloat)inputRadius {
    
    for (UIView *subview in self.subviews) {
        if (subview.tag == 19930713) {
            [subview removeFromSuperview];
        }
    }
    
    if (inputRadius < 0.01) {
        return;
    }
    
    // 1. 先把当前view截个图
    CGSize imageSize = self.bounds.size;
    CGFloat scale = [UIScreen mainScreen].scale;
    UIGraphicsBeginImageContextWithOptions(imageSize, NO, scale);
    [self.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    UIImageView *imageView = [[UIImageView alloc] initWithFrame:self.bounds];
    imageView.backgroundColor = UIColor.whiteColor;
    imageView.image = [self cgreateGaussianBlurImage:image inputRadius:inputRadius];
    imageView.tag = 19930713;
    [self addSubview:imageView];
}

- (UIImage *)cgreateGaussianBlurImage:(UIImage *)image inputRadius:(CGFloat)inputRadius {
    CIContext *context = [CIContext contextWithOptions:nil];
    CIImage *ciImage = [CIImage imageWithCGImage:image.CGImage];
    CIFilter *filter = [CIFilter filterWithName:@"CIGaussianBlur"];
    [filter setValue:ciImage forKey:kCIInputImageKey];
    //设置模糊程度 (值越大,越模糊)
    [filter setValue:@(inputRadius) forKey: @"inputRadius"];
    CIImage *result = [filter valueForKey:kCIOutputImageKey];
    //        CGRect frame = [ciImage extent];
    CGImageRef outImage = [context createCGImage:result fromRect:ciImage.extent];
    UIImage * blurImage = [UIImage imageWithCGImage:outImage];
    // 内存释放 (补充)
    CGImageRelease(outImage);
    return blurImage;
}

@end

demo演练

主要代码就四行

UIBlurEffect * blur = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
UIVisualEffectView * effe = [[UIVisualEffectView alloc]initWithEffect:blur];
effe.frame = CGRectMake(50, 90, self.view.frame.size.width - 100, 600);
[self.view addSubview:effe];

创建一个蒙板, 设置style, 设置frame, 放到界面上即可.

注意这里的UIBlurEffectStyleLight, 它是枚举UIBlurEffectStyle的其中一个,

typedef NS_ENUM(NSInteger, UIBlurEffectStyle) {
    /* Traditional blur styles.
     */
    UIBlurEffectStyleExtraLight,
    UIBlurEffectStyleLight,
    UIBlurEffectStyleDark,
    UIBlurEffectStyleExtraDark API_AVAILABLE(tvos(10.0)) API_UNAVAILABLE(ios) API_UNAVAILABLE(watchos),

    /* Styles which automatically show one of the traditional blur styles,
     * depending on the user interface style.
     *
     * Regular displays either Light or Dark.
     */
    UIBlurEffectStyleRegular API_AVAILABLE(ios(10.0)),
    /* Prominent displays either ExtraLight, Dark (on iOS), or ExtraDark (on tvOS).
     */
    UIBlurEffectStyleProminent API_AVAILABLE(ios(10.0)),

    /*
     * Blur styles available in iOS 13.
     *
     * Styles which automatically adapt to the user interface style:
     */
    UIBlurEffectStyleSystemUltraThinMaterial        API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos),
    UIBlurEffectStyleSystemThinMaterial             API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos),
    UIBlurEffectStyleSystemMaterial                 API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos),
    UIBlurEffectStyleSystemThickMaterial            API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos),
    UIBlurEffectStyleSystemChromeMaterial           API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos),

    /* And always-light and always-dark versions:
     */
    UIBlurEffectStyleSystemUltraThinMaterialLight   API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos),
    UIBlurEffectStyleSystemThinMaterialLight        API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos),
    UIBlurEffectStyleSystemMaterialLight            API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos),
    UIBlurEffectStyleSystemThickMaterialLight       API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos),
    UIBlurEffectStyleSystemChromeMaterialLight      API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos),

    UIBlurEffectStyleSystemUltraThinMaterialDark    API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos),
    UIBlurEffectStyleSystemThinMaterialDark         API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos),
    UIBlurEffectStyleSystemMaterialDark             API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos),
    UIBlurEffectStyleSystemThickMaterialDark        API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos),
    UIBlurEffectStyleSystemChromeMaterialDark       API_AVAILABLE(ios(13.0)) API_UNAVAILABLE(tvos, watchos),

} API_AVAILABLE(ios(8.0));

这里我们来尝试用不同style. 按照显示效果, 选择适合自己项目的一个style即可

/// 界面创建一个按钮, 或者直接重写touchBegan方法, 执行如下
// index从0开始
for (UIView *view in self.view.subviews) {
    if ([view isKindOfClass:[UIVisualEffectView class]]) {
        [view removeFromSuperview];
    }
}

UIBlurEffect * blur = [UIBlurEffect effectWithStyle:self.index];
UIVisualEffectView * effe = [[UIVisualEffectView alloc]initWithEffect:blur];
effe.frame = CGRectMake(50, 90, self.view.frame.size.width - 100, 600);
[self.view addSubview:effe];

self.index += 1;

每次点击, 界面将重设一个模糊效果, 自己选择一个适合的.

效果图

posted @ 2021-01-18 15:16  CleverPeng  阅读(1916)  评论(0)    收藏  举报