• iOS_自定义毛玻璃效果


    http://www.2cto.com/kf/201408/329969.html

    最终效果图:

    关键代码:

    UIImage分类代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    //
    //  UIImage+BlurGlass.h
    //  帅哥_团购
    //
    //  Created by beyond on 14-8-30.
    //  Copyright (c) 2014年 com.beyond. All rights reserved.
    //  毛玻璃效果 UIImage分类
     
    #import <uikit uikit.h="">
     
    @interface UIImage (BlurGlass)
     
     
    /*
     1.白色,参数:
     透明度 0~1,  0为白,   1为深灰色
     半径:默认30,推荐值 3   半径值越大越模糊 ,值越小越清楚
     色彩饱和度(浓度)因子:  0是黑白灰, 9是浓彩色, 1是原色  默认1.8
     “彩度”,英文是称Saturation,即饱和度。将无彩色的黑白灰定为0,最鲜艳定为9s,这样大致分成十阶段,让数值和人的感官直觉一致。
     */
    - (UIImage *)imgWithLightAlpha:(CGFloat)alpha radius:(CGFloat)radius colorSaturationFactor:(CGFloat)colorSaturationFactor;
    // 2.封装好,供外界调用的
    - (UIImage *)imgWithBlur;
     
     
    @end
    </uikit>



    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    //
    //  UIImage+BlurGlass.m
    //  帅哥_团购
    //
    //  Created by beyond on 14-8-30.
    //  Copyright (c) 2014年 com.beyond. All rights reserved.
    //
     
    #import UIImage+BlurGlass.h
    #import
     
    @implementation UIImage (BlurGlass)
     
     
     
    /*
       1.白色,参数:
        透明度 0~1,  0为白,   1为深灰色
        半径:默认30,推荐值 3   半径值越大越模糊 ,值越小越清楚
        色彩饱和度(浓度)因子:  0是黑白灰, 9是浓彩色, 1是原色  默认1.8
        “彩度”,英文是称Saturation,即饱和度。将无彩色的黑白灰定为0,最鲜艳定为9s,这样大致分成十阶段,让数值和人的感官直觉一致。
     */
    - (UIImage *)imgWithLightAlpha:(CGFloat)alpha radius:(CGFloat)radius colorSaturationFactor:(CGFloat)colorSaturationFactor
    {
        UIColor *tintColor = [UIColor colorWithWhite:1.0 alpha:alpha];
        return [self imgBluredWithRadius:radius tintColor:tintColor saturationDeltaFactor:colorSaturationFactor maskImage:nil];
    }
    // 2.封装好,供外界调用的
    - (UIImage *)imgWithBlur
    {
        // 调用方法1
       return [self imgWithLightAlpha:0.1 radius:3 colorSaturationFactor:1];
    }
     
     
     
     
    // 内部方法,核心代码,封装了毛玻璃效果 参数:半径,颜色,色彩饱和度
    - (UIImage *)imgBluredWithRadius:(CGFloat)blurRadius tintColor:(UIColor *)tintColor saturationDeltaFactor:(CGFloat)saturationDeltaFactor maskImage:(UIImage *)maskImage
    {
         
         
        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) {
                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,                    01,
                };
                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();
        }
         
        // 开启上下文 用于输出图像
        UIGraphicsBeginImageContextWithOptions(self.size, NO, [[UIScreen mainScreen] scale]);
        CGContextRef outputContext = UIGraphicsGetCurrentContext();
        CGContextScaleCTM(outputContext, 1.0, -1.0);
        CGContextTranslateCTM(outputContext, 0, -self.size.height);
         
        // 开始画底图
        CGContextDrawImage(outputContext, imageRect, self.CGImage);
         
        // 开始画模糊效果
        if (hasBlur) {
            CGContextSaveGState(outputContext);
            if (maskImage) {
                CGContextClipToMask(outputContext, imageRect, maskImage.CGImage);
            }
            CGContextDrawImage(outputContext, imageRect, effectImage.CGImage);
            CGContextRestoreGState(outputContext);
        }
         
        // 添加颜色渲染
        if (tintColor) {
            CGContextSaveGState(outputContext);
            CGContextSetFillColorWithColor(outputContext, tintColor.CGColor);
            CGContextFillRect(outputContext, imageRect);
            CGContextRestoreGState(outputContext);
        }
         
        // 输出成品,并关闭上下文
        UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
         
        return outputImage;
    }
     
    @end
    </accelerate>


    控制器代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    //
    //  MineController.m
    //  帅哥_团购
    //
    //  Created by beyond on 14-8-14.
    //  Copyright (c) 2014年 com.beyond. All rights reserved.
    //  dock上面的【我的】按钮对应的控制器
     
    #import MineController.h
    #import ImgDownloadTool.h
    #import
    #import UIImage+BoxBlur.h
    #import GirlCell.h
    // 每一个格子的宽和高
    #define kItemW 240
    #define kItemH 320
    @interface MineController ()<uicollectionviewdatasource,uicollectionviewdelegate>
    {
        NSMutableArray *_imgArr;
        UIWebView *_webView;
         
        // 添加一个coverImgView,用于点击了cell时,进行屏幕截图并加上毛玻璃效果,置于最上方作为蒙板
         
        UIImageView *_coverBlurImgView;
        // 点击cell,弹出一个大图(必须在控制器显示之前 再确定frame,真实的frame)
        UIImageView *_showingImgView;
     
    }
     
    @end
     
    @implementation MineController
     
     
    #pragma mark - 生命周期方法
     
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        self.title = @我的青春谁做主;
        // 0.加载plist文件保存的url数组
        // sg_bundle模板代码,1,获得.app主要的包;2,返回主要的包中某个文件的fullPath全路径
        NSBundle *mainBundle = [NSBundle mainBundle];
        NSString *fullPath = [mainBundle pathForResource:@sinaImgArr.plist ofType:nil];
        _imgArr = [NSArray arrayWithContentsOfFile:fullPath];
         
         
         
         
        // 1.创建自己的collectionView
        [self addCollectionView];
         
        // 2.注册cell格子要用到的xib文件
        [self.collectionView registerNib:[UINib nibWithNibName:@GirlCell bundle:nil] forCellWithReuseIdentifier:@GirlCell];
         
        // 3.设置collectionView永远支持垂直滚动,为下拉刷新准备(弹簧)
        self.collectionView.alwaysBounceVertical = YES;
         
        // 4.设置collectionView的背景色
        self.collectionView.backgroundColor = kGlobalBg;
         
        // 5.添加一个coverImgView,用于点击了cell时,进行屏幕截图并加上毛玻璃效果,置于最上方作为蒙板
        _coverBlurImgView = [[UIImageView alloc]init];
        [self.view addSubview:_coverBlurImgView];
         
         
        // 6.点击cell,弹出一个大图(必须在控制器显示之前 再确定frame,真实的frame)
        _showingImgView = [[UIImageView alloc]init];
        _showingImgView.backgroundColor = [UIColor clearColor];
        [self.view addSubview:_showingImgView];
        _showingImgView.contentMode = UIViewContentModeScaleAspectFit;
        _showingImgView.userInteractionEnabled = YES;
        [_showingImgView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(showingImgTap)]];
     
    }
     
    // 1.创建自己的collectionView
    - (void)addCollectionView
    {
        // 创建一个流布局,必须指定
        UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
        // 设置流布局里面的每一个格子宽和高,即每一个网格的尺寸
        layout.itemSize = CGSizeMake(kItemW, kItemH);
        // 每一行之间的间距
        layout.minimumLineSpacing = 20;
        // 指定的流布局创建一个collectionView,并且用成员变量记住
        self.collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:layout];
        // 高度和宽度自动伸缩
        self.collectionView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
        self.collectionView.delegate = self;
        self.collectionView.dataSource = self;
        [self.view addSubview:self.collectionView];
    }
    #pragma mark 在viewWillAppear和viewDidAppear中可以取得view最准确的宽高(width和height)
    // 重要~~~因为在控制器创建时,宽默认是768,高默认是1024,不管横竖屏
    // 只有在viewWillAppear和viewDidAppear方法中,可以取得view最准确的(即实际的)宽和高(width和height)
    - (void)viewWillAppear:(BOOL)animated
    {
        // 默认计算layout
        [self didRotateFromInterfaceOrientation:0];
    }
    #pragma mark - 父类方法
     
    // 拦截,屏幕即将旋转的时候调用(控制器监控屏幕旋转)
    - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
    {
        //log(@屏幕即将旋转);
    }
     
     
    #pragma mark 屏幕旋转完毕的时候调用
    // 拦截,屏幕旋转完毕的时候调用
    - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
    {
        // 1.取出创建CollectionViewController时传入的的UICollectionViewFlowLayout
        UICollectionViewFlowLayout *layout = (UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout;
         
         
        // 2.计算间距
        CGFloat v = 0;
        CGFloat h = 0;
        CGFloat height = self.view.frame.size.height -44;
        CGFloat width = self.view.frame.size.width;
        if (UIInterfaceOrientationIsLandscape(self.interfaceOrientation)
            ) {
            // 横屏的间距
            v = (height - 2 * kItemH) / 3;
            h = (width - 3 * kItemW) / 4;
             
        } else {
            // 竖屏的间距
            v = (height - 3 * kItemH) / 4;
            h = (width - 2 * kItemW) / 3;
        }
        // 3.动画调整格子之间的距离
        [UIView animateWithDuration:4.0 animations:^{
            // 上 左 下 右 四个方向的margin
            layout.sectionInset = UIEdgeInsetsMake(h, h, v, h);
            // 每一行之间的间距
            layout.minimumLineSpacing = h;
        }];
         
        // 4.旋转完成之后,才可以得到真实的frame,暂时隐藏起来,当点击cell的时侯才展示  -5
        _coverBlurImgView.frame = CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height);
        _coverBlurImgView.hidden = YES;
         
         
        _showingImgView.hidden = YES;
        CGRect temp =     _showingImgView.frame;
        CGFloat x =self.view.frame.size.width * 0.5;
        CGFloat y =self.view.frame.size.height * 0.5;
        temp = CGRectMake(x,y, 0, 0);
        _showingImgView.frame = temp;
    }
     
    #pragma mark - collectionView代理方法
    // 共有多少个Item(就是格子Cube),询问子类
    - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
    {
        return _imgArr.count;
    }
    #pragma mark 刷新数据的时候会调用(reloadData)
    #pragma mark 每当有一个cell重新进入屏幕视野范围内就会调用
    // 生成每一个独一无二的格子,询问子类
    - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
    {
        static NSString *ID = @GirlCell;
        GirlCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:ID forIndexPath:indexPath];
         
        cell.imgSrc = _imgArr[indexPath.row];
         
        return cell;
    }
    // 点击了一个格子时,1,截屏,2,动画毛玻璃图片,3,showing从小放到大
    - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
    {
         
        // 1,截屏
        [self screenShot];
        // 2,显示
        _coverBlurImgView.alpha = 1;
        _coverBlurImgView.hidden = NO;
         
        // 3.调用UIImage的分类方法,进行毛玻璃处理
        _coverBlurImgView.image = [_coverBlurImgView.image imgWithBlur];
     
        // 4.展示_showingImgView
        _showingImgView.hidden = NO;
         
         
        // 点击cell,弹出一个大图
        CGRect temp =     _showingImgView.frame;
        CGFloat x =self.view.frame.size.width * 0.5;
        CGFloat y =self.view.frame.size.height * 0.5;
        temp = CGRectMake(x,y, 0, 0);
        _showingImgView.frame = temp;
        _showingImgView.alpha = 0;
        [UIView animateWithDuration:0.5 animations:^{
              [ImgDownloadTool imgDownloadWithUrl:_imgArr[indexPath.row] tmpImgName:kImgPlaceHolder imageView:_showingImgView];
            _showingImgView.alpha = 1;
            _showingImgView.frame = self.view.bounds;
        }];
         
    }
     
     
    // 使用上下文截图,并使用指定的区域裁剪,模板代码
    - (void)screenShot
    {
        // 将要被截图的view
        // 背景图片 总的大小
        CGSize size = self.view.frame.size;
        UIGraphicsBeginImageContext(size);
        // 开启上下文,使用参数之后,截出来的是原图(YES  0.0 质量高)
        UIGraphicsBeginImageContextWithOptions(size, YES, 0.0);
     
        // 裁剪的关键代码,要裁剪的矩形范围
        CGRect rect = CGRectMake(0, 0, size.width, size.height  );
        //注:iOS7以后renderInContext:由drawViewHierarchyInRect:afterScreenUpdates:替代
        [self.view drawViewHierarchyInRect:rect  afterScreenUpdates:NO];
        // 从上下文中,取出UIImage
        UIImage *snapshot = UIGraphicsGetImageFromCurrentImageContext();
        // 添加截取好的图片到图片View里面
        _coverBlurImgView.image = snapshot;
         
        // 千万记得,结束上下文(移除栈顶上下文)
        UIGraphicsEndImageContext();
         
    }
     
    // 正在显示的大图被点了
    - (void)showingImgTap
    {
         
         
         
        [UIView animateWithDuration:0.5 animations:^{
            CGRect temp =     _showingImgView.frame;
            CGFloat x =self.view.frame.size.width * 0.5;
            CGFloat y =self.view.frame.size.height * 0.5;
            temp = CGRectMake(x,y, 0, 0);
            _showingImgView.frame = temp;
            _showingImgView.alpha = 0;
        } completion:^(BOOL finished) {
            // 隐藏起来
            _showingImgView.hidden = YES;
             
            _coverBlurImgView.hidden = YES;
        }];
    }
     
    #pragma mark - 生命周期方法
    - (void)dealloc
    {
        [[NSNotificationCenter defaultCenter] removeObserver:self];
    }
     
    @end
    </uicollectionviewdatasource,uicollectionviewdelegate></accelerate>
  • 相关阅读:
    插入排序
    选择排序
    二分法查找
    pickle模块的使用
    循环和递归求阶乘、递归实现汉诺塔程序、递归实现拆出每个位的数字放在列表中、递归求第五个人的年龄
    app测试和测试基础
    TCP协议中的三次握手和四次挥手及其他
    AcWing 122 糖果传递
    AcWing 121 赶牛入圈 (二分+离散化)
    AcWing 120 防线 (二分)
  • 原文地址:https://www.cnblogs.com/xuejinhui/p/4387535.html
Copyright © 2020-2023  润新知