上一篇根据自身经验,介绍了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; }