iOS之UI--辉光动画
2016-01-31 04:33
369 查看
前言:学习来自YouXianMing老师的博客:《辉光UIView的category 》以及YouXianMing老师的github源码:《 GlowView 》
而我个人考虑到分类的二次拓展性(或者是再一次拓展)不是特别好,所以将YouXianMing老师的用分类拓展的辉光动画,改写成一个继承CALayer的可拓展的普通类。
一方面,也是作为自我训练编码,对辉光UIView的实现所使用到的上下文绘制、核心动画、GCD中的定时器以及Runtime动态添加属性等知识进一步的熟练运用和提高。
个人经验不足,也许观点片面,读者尽量指出,我不会介意的。嘻嘻。
先展示效果图:
源码下载地址:https://github.com/HeYang123456789/UIView
源码:
使用实例:
转载注明出处:http://www.cnblogs.com/goodboy-heyang/p/5172807.html,尊重劳动成果哦。
而我个人考虑到分类的二次拓展性(或者是再一次拓展)不是特别好,所以将YouXianMing老师的用分类拓展的辉光动画,改写成一个继承CALayer的可拓展的普通类。
一方面,也是作为自我训练编码,对辉光UIView的实现所使用到的上下文绘制、核心动画、GCD中的定时器以及Runtime动态添加属性等知识进一步的熟练运用和提高。
个人经验不足,也许观点片面,读者尽量指出,我不会介意的。嘻嘻。
先展示效果图:
源码下载地址:https://github.com/HeYang123456789/UIView
源码:
// // GlowLayer.h // GlowView // // Created by HEYANG on 16/1/30. // Copyright © 2016年 HeYang. All rights reserved. // #import <UIKit/UIKit.h> // == 动画时间解析 == // // 0.0 ----------- 0.0 ------------> glowOpacity [---------------] glowOpacity ------------> 0.0 // T T T T // | | | | // | | | | // . . . . // hideDuration animationDuration glowDuration animationDuration // /** * 需要考虑的参数 * * 需要考虑的逻辑 * 1.数值越界问题,通过懒加载 * 2.动画时间的安排(看前面的动画时间的解析) * * 需要对外公开的接口 */ @interface GlowLayer : CALayer #pragma mark - 对外公开的属性 #pragma mark 设置辉光效果 /** 辉光的阴影半径 */ @property (nonatomic,strong)NSNumber *glowRadius; /** 辉光的透明度 */ @property (nonatomic,strong)NSNumber *glowOpacity; #pragma mark 设置辉光的时间 /** 保持辉光的时间,默认设置为0.5f */ @property (nonatomic,strong)NSNumber *glowDuration; /** 不显示辉光的时间,默认设置为0.5f */ @property (nonatomic,strong)NSNumber *hideDuration; /** 辉光的变化时间,从明到暗或者是从暗到明,默认设置为1.f */ @property (nonatomic,strong)NSNumber *glowAnimationDuration; #pragma mark - 对外公开的接口 /** 在原始的View上创建出辉光layer */ -(void)createGlowLayerWithOriginView:(UIView*)originView glowColor:(UIColor*)glowColor; /** 显示辉光 */ -(void)showGLowLayer; /** 隐藏辉光 */ -(void)hideGlowLayer; /** 开始循环辉光动画 */ -(void)startGlowAnimation; /** 暂停辉光动画 */ -(void)pauseGlowAnimation; /** 重启辉光动画 */ -(void)reStareGlowAnimation; @end @interface UIView (GlowViews) /** GlowLayer */ @property (nonatomic,strong)GlowLayer *glowLayer; /** 创建GlowLayer,默认辉光颜色为红色 */ -(void)addGlowLayer; /** 创建GlowLayer,需要设置辉光颜色 */ -(void)addGlowLayerWithGlowColor:(UIColor*)glowColor; /** 插入辉光 */ -(void)insertGlowLayerToSuperlayer; /** 完全移除GLowLayer */ -(void)removeGlowLayerFromSuperlayer; @end
// // GlowLayer.m // GlowView // // Created by HEYANG on 16/1/30. // Copyright © 2016年 HeYang. All rights reserved. // #import "GlowLayer.h" @interface GlowLayer () /** 辉光的颜色 */ @property (nonatomic,strong)UIColor *glowColor; /** 需要添加辉光效果的View ,注意这里用的是weak,而不是strong */ @property (nonatomic,weak)UIView *addedGlowView; /** dispatch_source_t */ @property (nonatomic,strong)dispatch_source_t timer; @end @implementation GlowLayer #pragma mark - 创建辉光 // 遗留了一个先后顺序的问题, /** 在原始的View上创建出辉光layer */ -(void)createGlowLayerWithOriginView:(UIView*)originView glowColor:(UIColor*)glowColor{ self.glowColor = glowColor; // 创建一个图形上下文 参数:CGSize size:上下文的尺寸 BOOL opaque是否不透明 CGFloat scale缩放因子 UIGraphicsBeginImageContextWithOptions(originView.bounds.size, NO, [UIScreen mainScreen].scale); // 通过get函数得到当前图形上下文,然后将origingView上的图形渲染到这个图形上下文上 [originView.layer renderInContext:UIGraphicsGetCurrentContext()]; // 创建贝塞尔曲线 UIBezierPath *path = [UIBezierPath bezierPathWithRect:originView.bounds]; // 设置贝塞尔取消绘制的颜色 [self.glowColor setFill];//这里还是需要懒加载 // 设置贝塞尔曲线绘制模式 [path fillWithBlendMode:kCGBlendModeSourceAtop alpha:1]; // 设置self(GlowLayer)初始状态 self.frame = originView.bounds; // 至少要在设置好当前frame值之后,然后添加图形上下文的Image // 获得当前图形上下文的图形,然后赋值给CALayer的constraints self.contents = (__bridge id _Nullable)(UIGraphicsGetImageFromCurrentImageContext().CGImage); // 阴影设置不透明,其他的设置为透明 self.opacity = 0.f; self.shadowOpacity = 1.f; // 阴影偏移量为(0,0) self.shadowOffset = CGSizeMake(0, 0); // 关闭图形上下文 UIGraphicsEndImageContext(); // 强引用指向这个原来的View self.addedGlowView = originView; } #pragma mark - 显示和隐藏辉光 /** 显示辉光 */ -(void)showGLowLayer{ // 设置阴影初始效果 self.shadowColor = self.glowColor.CGColor; self.shadowRadius = self.glowRadius.floatValue; CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:@"opacity"]; animation.fromValue = @(0); animation.toValue = self.glowOpacity; animation.duration = self.glowAnimationDuration.floatValue; // 设置最终值 self.opacity = self.glowOpacity.floatValue; [self addAnimation:animation forKey:nil]; } /** 隐藏辉光 */ -(void)hideGlowLayer{ self.shadowColor = self.glowColor.CGColor; self.shadowRadius = self.glowRadius.floatValue; CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:@"opacity"]; animation.fromValue = self.glowOpacity; animation.toValue = @(0); animation.duration = self.glowAnimationDuration.floatValue; // 设置最终值 self.opacity = 0; [self addAnimation:animation forKey:nil]; } #pragma mark - 循环显示和隐藏辉光 /** 开始循环辉光动画 */ -(void)startGlowAnimation{ CGFloat cycleTime = self.glowAnimationDuration.floatValue * 2 + self.glowDuration.floatValue + self.hideDuration.floatValue; CGFloat delayTime = self.glowAnimationDuration.floatValue + self.glowDuration.floatValue; _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue()); dispatch_source_set_timer(_timer, DISPATCH_TIME_NOW, cycleTime * NSEC_PER_SEC, 0); dispatch_source_set_event_handler(_timer, ^{ [self showGLowLayer]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayTime * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self hideGlowLayer]; }); }); dispatch_resume(_timer); } /** 暂停辉光动画 */ -(void)pauseGlowAnimation{ [self removeFromSuperlayer]; } /** 重启辉光动画 */ -(void)reStareGlowAnimation{ [self.addedGlowView.layer addSublayer:self]; [self startGlowAnimation]; } #pragma mark - 懒加载辉光的效果,同时处理数据越界问题 #pragma mark duration 辉光时间 -(NSNumber *)glowDuration{ if (!_glowDuration || _glowDuration.floatValue < 0) { _glowDuration = @(0.5f); } return _glowDuration; } -(NSNumber *)hideDuration{ if (!_hideDuration || _hideDuration.floatValue < 0) { _hideDuration = @(0.5); } return _hideDuration; } -(NSNumber *)glowAnimationDuration{ if (!_glowDuration || _glowDuration.floatValue < 0) { _glowDuration = @(1.f); } return _glowDuration; } #pragma mark 辉光颜色 -(UIColor *)glowColor{ if (!_glowColor) { _glowColor = [UIColor redColor]; } return _glowColor; } #pragma mark 辉光半径 -(NSNumber *)glowRadius{ if (!_glowRadius || _glowRadius.floatValue <= 0) { _glowRadius = @(2.f); } return _glowRadius; } #pragma mark 辉光透明度 -(NSNumber *)glowOpacity{ if (!_glowOpacity || _glowOpacity.floatValue <= 0) { _glowOpacity = @(0.8); } return _glowOpacity; } @end #import <objc/runtime.h> @implementation UIView (GlowViews) /** 创建GlowLayer,默认辉光颜色为红色 */ -(void)addGlowLayer{ [self addGlowLayerWithGlowColor:nil]; } /** 创建GlowLayer,需要设置辉光颜色 */ -(void)addGlowLayerWithGlowColor:(UIColor*)glowColor{ if (self.glowLayer == nil) { self.glowLayer = [[GlowLayer alloc] init]; } [self.glowLayer createGlowLayerWithOriginView:self glowColor:glowColor]; [self insertGlowLayerToSuperlayer]; } #pragma mark - 插入和移除辉光 /** 插入辉光 */ -(void)insertGlowLayerToSuperlayer{ if (self.glowLayer == nil) { self.glowLayer = [[GlowLayer alloc] init]; } [self.layer addSublayer:self.glowLayer]; } /** 移除辉光 */ -(void)removeGlowLayerFromSuperlayer{ [self.glowLayer removeFromSuperlayer]; self.glowLayer = nil; } #pragma mark - Runtime动态添加属性 NSString * const _recognizerGlowLayer = @"_recognizerGlowLayer"; -(void)setGlowLayer:(GlowLayer *)glowLayer{ objc_setAssociatedObject(self, (__bridge const void *)(_recognizerGlowLayer), glowLayer, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } -(GlowLayer *)glowLayer{ return objc_getAssociatedObject(self, (__bridge const void *)(_recognizerGlowLayer)); } @end
使用实例:
转载注明出处:http://www.cnblogs.com/goodboy-heyang/p/5172807.html,尊重劳动成果哦。
相关文章推荐
- 动画交互设计与技术实现
- UIView上的按钮跳转到一个控制器UIViewController上去
- jfinal2.2+easyui1.4.4后台权限管理系统 [2016.01.31 更新]
- 利用values来反向查询key,有没有简单的方法呢?
- uicollectionview的基本使用
- 网卡解析arp协议导致ip address ** is already in ues for...
- LeetCode 303:Range Sum Query - Immutable
- 集训队专题(2)1004 Queuing
- lintcode: Unique Paths
- Divide and conquer:Showstopper(POJ 3484)
- Implement Queue by Two Stacks
- UISegmentedControl分段控件使用详解
- UISegmentedControl 分段控件-IOS开发
- TraitsUI-轻松制作用户界面
- 升级后重启造成fsck.ext3: Unable to resolve UUID
- Wunder Fund Round 2016 (Div. 1 + Div. 2 combined) B Guess the Permutation (两种做法,水题的一点点思考)
- [转]easyui tree 模仿ztree 使用扁平化加载json
- tkinter的GUI设计:界面与逻辑分离(四)-- 与 matplotlib 结合
- 【POJ】[2524]Ubiquitous Religions
- 继承Volley的Request<T>,创造自己的Request,实现cookie回调和指定返回数据类型回调