iOS-毛玻璃效果详解

作者: 鲲鹏DP | 来源:发表于2016-07-17 18:09 被阅读4612次

    在ios开发过程中,为了界面的美观,我们往往需要对一个图片进行模糊化处理,有一种朦胧美得感觉,就是所谓的毛玻璃效果。在GitHub上不乏实现毛玻璃效果的三方框架,这里就不做过多介绍。现在主要谈谈苹果自己提供的两种实现毛玻璃效果的类,UIToolBar和UIVisuaEffectView。


    UIToolBar

    UIToolBar在IOS 2.0就已经出现,可以快速实现毛玻璃效果。简单易懂,但是效果单一,系统只提供了两种bayStyle. UIBarStyleDefault和UIBarStyleBlack 。

    Snip20160717_9.png Snip20160717_8.png
    //背景图片
      UIImageView *backImageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"Snip20160714_17"]];
        backImageView.frame = self.view.bounds;
        [self.view addSubview:backImageView];
    //UIToolBar:加了三层遮盖
            UIToolbar *bar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 100,375, 300)];
            bar.barStyle = UIBarStyleDefault;
            bar.alpha = 0.8;
            [self.view addSubview:bar];
    

    UIVisuaEffectView

    UIVisuaEffectView是苹果从IOS8.0开始提供的可实现毛玻璃效果(blur)的控件。相比以前的UIToolBar,UIVisuaEffectView的功能更加强大,能实现更加复杂的效果。 利用UIVisuaEffectView实现毛玻璃效果,首先需要对UIVisualEffect,UIBlurEffect、UIVibrancyEffect 和UIVisuaEffectView有一个正确的认识:

    • 1.UIVisuaEffectView :继承自UIView,可以看成是专门用于处理毛玻璃效果的视图,只要我们将这个特殊的View添加到其他视图(eg. ImageView )上面,被该UIVisuaEffectView遮盖的部分看起来就有了毛玻璃效果。使用UIVisuaEffectView有一点需要特别注意,不要在UIVisuaEffectView实例化View上面直接添加subViews,应该将需要添加的子视图添加到其contentView上。同时,尽量避免将UIVisualEffectView对象的alpha值设置为小于1.0的值,因为创建半透明的视图会导致系统在离屏渲染时去对UIVisualEffectView对象及所有的相关的子视图做混合操作,比较消耗性能。

    • 2.UIBlurEffect:毛玻璃效果。使用该效果,会使得UIVisualEffectView下面的内容出现毛玻璃化,但是添加到contentView的View不会受影响。

    • 3.UIVibrancyEffect:生动效果。该效果,能够放大和调整放在UIVisualEffectView对象下面的内容的颜色,也能让添加在contentView中的内容变得更加生动。它可以放在一个配置了UIBlurEffect效果的UIVisualEffectView的上面或者作为其subView。这种效果仅仅对与添加到contentView中的内容有效果。因为这种生动效果依赖于颜色,添加到contentView中的subViews 需要实现tintColorDidChange方法,并及时更新。如果是UIImageView,必须设置其渲染方式为UIImageRenderingModeAlwaysTemplate。

    • 4. UIVisualEffect:一个视觉效果抽象类,继承自NSObject,是UIBlurEffect和UIVibrancyEffect的父类。
      具体代码和效果:
      利用UIVisuaEffectView实现毛玻璃效果,首先需要创建一个UIVisuaEffectView对象,同时给该对象指定一种处理效果(UIBlurEffect/UIVibrancyEffect)。

    1). UIBlurEffect

    
    //设置背景图片
    UIImageView *backImageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"Snip20160714_17"]];
    
    backImageView.frame = self.view.bounds;
    
    [self.view addSubview:backImageView];
    
    //设置UIVisualEffectView
    
    UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
    
    UIVisualEffectView *visualView = [[UIVisualEffectView alloc]initWithEffect:blurEffect];
    
    visualView.frame = CGRectMake(0, 100,375, 300);
    
    [self.view addSubview:visualView];
    //UIBlurEffect的effectWithStyle有三种:UIBlurEffectStyleExtraLight/UIBlurEffectStyleLight/UIBlurEffectStyleDark
    
    Snip20160717_1.png Snip20160717_3.png

    可以看出使用UIBlurEffect 其实是在图片上面添加了三层遮盖。所以,如果图片放在了UIVisualEffectView的上面就没有效果。

    2). UIVibrancyEffect

    //设置背景图片
        UIImageView *backImageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"Snip20160714_17"]];
        backImageView.frame = self.view.bounds;
        [self.view addSubview:backImageView];
        //UIVisualEffectView
        UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
        UIVibrancyEffect *vibrancyEffect = [UIVibrancyEffect effectForBlurEffect:blurEffect];
        UIVisualEffectView *visualView = [[UIVisualEffectView alloc]initWithEffect:vibrancyEffect];
        UIView *redView = [[UIView alloc]init];
        redView.backgroundColor = [UIColor redColor];
        [visualView.contentView addSubview:redView];
        visualView.frame = CGRectMake(0, 100,375, 300);
        redView.frame = visualView.bounds;
        [self.view addSubview:visualView];
    

    通过改变contentView中subView,可以实现不同更加生动的效果。

    Snip20160717_5.png Snip20160717_6.png

    补充

    • 鉴于下面一位热心的朋友提示,自己就抽时间稍微看了一下Core Image相关的东西。Core Image是苹果提供的一个相当强大专门用于处理图片的库。稍微试了一下,不仅能实现毛玻璃效果,还能实现很多其他的效果。但是,在使用过程中发现使用Core Image来实现这些效果,非常占用内存。查看文档:createCGImage:outputImage : fromRect:方法会单独开辟一个临时的缓存区,出现离屏渲染,这可能是一个使得内存增大的重要原因。
    render the region 'fromRect' of image 'image' into a temporary buffer using the context, then create and return a new CoreGraphics image with  the results.
    
    • 下面简单看下效果吧
    #import "ViewController.h"
    
    @interface ViewController ()
    @property (strong, nonatomic) IBOutlet UIImageView *iconImageView;
    @property (strong, nonatomic) IBOutlet UIImageView *blurImageVIew;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        //1.获取CIIamge对象
        CIImage * ciIamge = [CIImage imageWithCGImage:_iconImageView.image.CGImage];
    //    //2.创建滤镜对象
        CIFilter *filter = [CIFilter filterWithName:@"CIMotionBlur"
                                      keysAndValues:kCIInputImageKey, ciIamge, nil];
        // 获取绘制上下文
        CIContext *context = [CIContext contextWithOptions:nil];
       // 渲染并输出CIImage
        CIImage *outputImage = [filter outputImage];
        // 创建CGImage句柄
        CGImageRef cgImage = [context createCGImage:outputImage
                                           fromRect:[outputImage extent]];
        self.blurImageVIew.image =[UIImage imageWithCGImage:cgImage];
        self.blurImageVIew.contentMode = UIViewContentModeScaleAspectFill;
        // 释放CGImage句柄
        CGImageRelease(cgImage);
    //    self.blurImageVIew.image = self.iconImageView.image;
    }
    
    
    Snip20160827_4.png
    • 未使用Core Image


      未使用.png
    • 使用Core Image

    使用Core Image.png

    相关文章

      网友评论

      • 潇湘候晨雪:介绍的详细~~学习了新技能!感谢
      • 042a0e1be73f:请问系统自带的AlertController弹窗透明效果是怎样实现的?
      • 掂吾掂:用UIVisuaEffectView是一种比较取巧的方法,另外可以用ImageIO也可以实现...我对比过,ImageIO的效果会更好,因为可以设置一下参数,建议作者也可以补上去..
        鲲鹏DP:使用core image渲染图片,感觉很耗内存啊
        掂吾掂:@鲲鹏DP 不好意思,记错了框架..是coreImage https://developer.apple.com/library/mac/documentation/GraphicsImaging/Reference/CoreImageFilterReference/
        鲲鹏DP: @掂吾掂 谢谢你的建议,回头我抽空试试。😊
      • e9ae9f114b3b:ios正确的写法是iOS :smiley:
      • 诸子百家谁的天下:6666
        鲲鹏DP: @诸子百家谁的天下 😄

      本文标题:iOS-毛玻璃效果详解

      本文链接:https://www.haomeiwen.com/subject/daxpjttx.html