上一篇根据自身经验,介绍了iOS开发UI布局的几种方法。在实际的项目开发中,经常会为了某些效果自定义一些控件,这篇文章我向大家介绍我在github的开源项目,关于脉冲动画控件的自定义。
iOS开发之自定义View的核心是继承UIView,重写drawRect方法,与android中的onDraw函数是一样的功能,具体效果如下:脉冲间隔向外发散
首先我们创建PulseRipple的h和m文件
#import <UIKit/UIKit.h>
@interface PulseRipple : UIView
@end
接下来,在m文件中初始化控件的frame
-(instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(activeAction) name:UIApplicationDidBecomeActiveNotification object:nil];
}
return self;
}
这里注册了通知,目的是在App进入后台后再次回到前台,动画能够继续执行。通知注册之后,在控件销毁时,记得要移除通知。通常在controller中,我们经常会注册一些通知,一般会写到viewDidload或者viewWillAppear中,视具体需求决定。
-(void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
-(void)activeAction
{
if(animationLayer)
{ //将图层从他的父图层中删除
[animationLayer removeFromSuperlayer];
//手动重画这个View
[self setNeedsDisplay];
}
}
setNeedsDisplay方法非常重要,在我们需要手动让控件重绘时,需要执行该方法。以下drawRect方法是具体的动画绘制过程,使用了CABasicAnimation 基本动画类,其中的具体细节,大家可以随意修改颜色,或者脉冲的数目,了解其中的功能,最后[self.layer addSublayer:myAnimationLayer]添加整个动画。
-(void)drawRect:(CGRect)rect
{
[[UIColor colorWithRed:0 green:167.0/255.0 blue:248.0/255.0 alpha:1.0] setFill];
UIRectFill(rect);
NSInteger pulsingCount = 6;
double animationDuration = 10.0;
CALayer *myAnimationLayer = [[CALayer alloc] init];
for(int i = 0; i < pulsingCount; i++)
{
CALayer *pulsingLayer = [[CALayer alloc] init];
pulsingLayer.frame = CGRectMake(0, 0, rect.size.width, rect.size.height);
pulsingLayer.borderColor = [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:0.3].CGColor;
pulsingLayer.borderWidth = 2;
pulsingLayer.cornerRadius = rect.size.height / 2;
CAMediaTimingFunction *defaultCurve = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault];
CAAnimationGroup *animationGroup = [[CAAnimationGroup alloc] init];
animationGroup.fillMode = kCAFillModeBackwards;
animationGroup.beginTime = CACurrentMediaTime() + i * animationDuration / pulsingCount;
animationGroup.duration = animationDuration;
animationGroup.repeatCount = HUGE;
animationGroup.timingFunction = defaultCurve;
CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
scaleAnimation.fromValue = @0.0;
scaleAnimation.toValue = @1.5;
CAKeyframeAnimation *opacityAnimation = [CAKeyframeAnimation animationWithKeyPath:@"opacity"];
opacityAnimation.values = @[@1.0,@0.7,@0.0];
opacityAnimation.keyTimes = @[@0.0,@0.5,@1.0];
animationGroup.animations = @[scaleAnimation,opacityAnimation];
[pulsingLayer addAnimation:animationGroup forKey:@"pulsing"];
[myAnimationLayer addSublayer:pulsingLayer];
}
[self.layer addSublayer:myAnimationLayer];
animationLayer = myAnimationLayer;
}
iOS原生的动画有很多种,旋转、缩放等等,也可以改变坐标系,原始坐标系是以屏幕左上角为原点,对于需要以屏幕中心为原点的需求,可以将整个坐标系平移。动画的研究还是很复杂的,在我们做一些界面跳转效果的时候,也会采用一些动画的过渡。