iOS之UI--辉光动画

前言:学习来自YouXianMing老师的博客:《辉光UIView的category 》以及YouXianMing老师的github源码:《 GlowView

     而我个人考虑到分类的二次拓展性(或者是再一次拓展)不是特别好,所以将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

使用实例:

时间: 2024-10-03 00:05:46

iOS之UI--辉光动画的相关文章

iOS开发UI篇—核心动画简介

一.简单介绍 Core Animation,中文翻译为核心动画,它是一组非常强大的动画处理API,使用它能做出非常炫丽的动画效果,而且往往是事半功倍.也就是说,使用少量的代码就可以实现非常强大的功能. Core Animation是跨平台的,可以用在Mac OS X和iOS平台. Core Animation的动画执行过程都是在后台操作的,不会阻塞主线程.不阻塞主线程,可以理解为在执行动画的时候还能点击(按钮). 要注意的是,Core Animation是直接作用在CALayer上的,并非UIV

iOS开发UI篇—核心动画(转场动画和组动画)

一.转场动画简单介绍 CAAnimation的子类,用于做转场动画,能够为层提供移出屏幕和移入屏幕的动画效果.iOS比Mac OS X的转场动画效果少一点 UINavigationController就是通过CATransition实现了将控制器的视图推入屏幕的动画效果 属性解析: type:动画过渡类型 subtype:动画过渡方向 startProgress:动画起点(在整体动画的百分比) endProgress:动画终点(在整体动画的百分比) 二.转场动画代码示例 1.界面搭建 2.实现代

iOS开发UI篇—核心动画(UIView封装动画)

一.UIView动画(首尾) 1.简单说明 UIKit直接将动画集成到UIView类中,当内部的一些属性发生改变时,UIView将为这些改变提供动画支持 执行动画所需要的工作由UIView类自动完成,但仍要在希望执行动画时通知视图,为此需要将改变属性的代码放在[UIViewbeginAnimations:nil context:nil]和[UIView commitAnimations]之间 常见方法解析: + (void)setAnimationDelegate:(id)delegate 设置

iOS开发UI篇—核心动画(关键帧动画)

一.简单介绍 是CApropertyAnimation的子类,跟CABasicAnimation的区别是:CABasicAnimation只能从一个数值(fromValue)变到另一个数值(toValue),而CAKeyframeAnimation会使用一个NSArray保存这些数值 属性解析: values:就是上述的NSArray对象.里面的元素称为"关键帧"(keyframe).动画对象会在指定的时间(duration)内,依次显示values数组中的每一个关键帧 path:可以

iOS开发UI篇—核心动画(基础动画)

一.简单介绍 CAPropertyAnimation的子类 属性解析: fromValue:keyPath相应属性的初始值 toValue:keyPath相应属性的结束值 随着动画的进行,在长度为duration的持续时间内,keyPath相应属性的值从fromValue渐渐地变为toValue 如果fillMode=kCAFillModeForwards和removedOnComletion=NO,那么在动画执行完毕后,图层会保持显示动画执行后的状态.但在实质上,图层的属性值还是动画执行前的初

使用CALayer制作View的辉光效果

使用CALayer制作View的辉光效果 实现以下的辉光效果: 思路是这样子的: 1. 创建好需要实现辉光效果的View 2. 对这个View进行截图 3. 将这个截图重新添加进View中 4. 对这个截图实现改变透明度的动画   ViewController.m // // ViewController.m // // Copyright (c) 2013 Nick Jensen. All rights reserved. // #import "ViewController.h"

辉光UIView的category

辉光UIView的category    本人视频教程系类   iOS中CALayer的使用   效果如下: 源码: UIView+GlowView.h 与 UIView+GlowView.m // // UIView+GlowView.h // YouXianClock // // Created by YouXianMing on 14-12-21. // Copyright (c) 2014年 YouXianMing. All rights reserved. // #import <UI

带辉光效果的跑马灯

带辉光效果的跑马灯   效果   说明 并没有对代码进行封装,以后会在项目 Animation(https://github.com/YouXianMing/Animations)里面进行集成,欢迎前去star.   源码 UIView+GlowView // // UIView+GlowView.h // GlowView // // Created by YouXianMing on 15/7/4. // Copyright (c) 2015年 YouXianMing. All rights

iOS开发UI篇—popoverController使用注意

iOS开发UI篇-popoverController使用注意 iOS开发UI篇-popoverController使用注意 一.设置尺寸 提示:不建议,像下面这样吧popover的宽度和高度写死. 1 //1.新建一个内容控制器 2 YYMenuViewController *menuVc=[[YYMenuViewController alloc]init]; 3 4 //2.新建一个popoverController,并设置其内容控制器 5 self.popover=[[UIPopoverCo