iOS_自己定义毛玻璃效果
终于效果图:
关键代码:
UIImage分类代码
//
// 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
//
// UIImage+BlurGlass.m
// 帅哥_团购
//
// Created by beyond on 14-8-30.
// Copyright (c) 2014年 com.beyond. All rights reserved.
// #import "UIImage+BlurGlass.h"
#import <Accelerate/Accelerate.h> @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, 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();
} // 开启上下文 用于输出图像
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
控制器代码
//
// MineController.m
// 帅哥_团购
//
// Created by beyond on 14-8-14.
// Copyright (c) 2014年 com.beyond. All rights reserved.
// dock上面的【我的】button相应的控制器 #import "MineController.h"
#import "ImgDownloadTool.h"
#import <Accelerate/Accelerate.h>
#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
iOS_自己定义毛玻璃效果的更多相关文章
- iOS_自定义毛玻璃效果
http://www.2cto.com/kf/201408/329969.html 最终效果图: 关键代码: UIImage分类代码 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 1 ...
- [开发笔记]-实现winform半透明毛玻璃效果
亲测win7下可用,win8下由于系统不支持Aero效果,所以效果不是半透明的. 代码: 博客园插入不了代码了..... public partial class Form1 : Form { int ...
- CSS 奇思妙想 | 全兼容的毛玻璃效果
通过本文,你能了解到 最基本的使用 CSS backdrop-filter 实现磨砂玻璃(毛玻璃)的效果 在至今不兼容 backdrop-filter 的 firefox 浏览器,如何利用一些技巧性的 ...
- 使用CSS3制作导航条和毛玻璃效果
导航条对于每一个Web前端攻城狮来说并不陌生,但是毛玻璃可能会相对陌生一些.简单的说,毛玻璃其实就是让图片或者背景使用相应的方法进行模糊处理.这种效果对用户来说是十分具有视觉冲击力的. 本次分享的主题 ...
- 解决css3毛玻璃效果(blur)有白边问题
做一个登录页,全屏背景图毛玻璃效果,实现方法如下: HTML: <body> <div class="login-wrap"> <div class= ...
- Swift 之模糊效果(毛玻璃效果,虚化效果)的实现
前言: 之前项目中有用到过Objective-C的的模糊效果,感觉很是不错,而且iOS8之后官方SDK也直接提供了可以实现毛玻璃效果的三个类:UIBlurEffect.UIVibrancyEffect ...
- iOS模糊效果(毛玻璃效果)的实现
前一段时间项目中用到毛玻璃效果,那时对UIBlurEffect类和 UIVisualEffectView这两个类做了一部分了解.但当时并没有去特别的深入研究,直到项目做完后,才静下心来好好研究了一番. ...
- qt qml fuzzyPanel 毛玻璃效果
毛玻璃效果,用qml来写代码真是简短,大爱qml:) [下载地址]http://download.csdn.net/detail/surfsky/8426641 [核心代码] Rectangle{ c ...
- CSS3中毛玻璃效果的使用方法
今天在使用icloud的时候看到苹果icloud官网的毛玻璃效果非常赞,仔细研究了一下它的实现方式,是使用js配合background-image: -webkit-canvas的形式绘制出的毛玻璃背 ...
随机推荐
- WCF WEB HTTP请求 WCF REST FUL
首先上点概念WCF 很好的支持了 REST 的开发, 而 RESTful 的服务通常是架构层面上的考虑. 因为它天生就具有很好的跨平台跨语言的集成能力,几乎所有的语言和网络平台都支持 HTTP 请求, ...
- Unity3d Time
using UnityEngine; using System.Collections; public class test1 : MonoBehaviour { public float angle ...
- ios - masonry第三方库使用自动布局(参考:http://www.cocoachina.com/ios/20141219/10702.html)
#import "ViewController.h" #import "Masonry.h" #define kWeakSelf(weakSelf) __wea ...
- nginx配置和测试
测试nginx处理能力和IO读写能力,使用工具webbench.iozone. 1.nginx测试 使用webbench工具,增加并发量,时间分别取30s,60s 1.webbench -c 200 ...
- Kafka学习笔记(5)----Kafka的Consumer
1. Pull vs Push Producer主动的通过push将消息发布到Broker上,Consumer通过Pull的的方式从Broker消息消息. 通过Push的方式由于是一有消息就推到Bro ...
- 创建dynamics CRM client-side (一) - Client-side Events
这个系列是帮助大家了解dynamics CRM (customer engagement CE) 的client-side 开发. Client-side Events 1. Form OnLoad ...
- nginx日志按日期自动切割脚本
#!/bin/bash #nginx日志切割脚本 #author:setevn #设置日志文件存放目录 logs_path="/usr/local/nginx/logs/" #设置 ...
- uva 11992 Fast Matrix Operations 线段树模板
注意 setsetset 和 addvaddvaddv 标记的下传. 我们可以控制懒惰标记的优先级. 由于 setsetset 操作的优先级高于 addaddadd 操作,当下传 setsetset ...
- Bzoj2124(p5364): 等差子序列
题目描述 给一个1到N的排列{Ai},询问是否存在1<=p1<p2<p3<p4<p5<…<pLen<=N (Len>=3), 使得Ap1,Ap2, ...
- css+div 绘制多边形
/*1.正方形*/ <div id="square"></div> #square { width: 100px; height: 100px; backg ...