估计是史上最简单的自定义进度条实现

进度条(ProgressBar)估计在每个App中都会使用到,再加上最近学习完了CoreAnimation框架,故而想自己实现一款进度条玩玩。

进度条其实就是绘制一条线的过程,重点就是怎么让绘制线的过程“动”起来,要想“动”就需要用到CoreAnimation框架了,用CoreAnimation实现动画的过程主要分3步:

  1. 创建动画Path、CALayer;
  2. 创建合适的CAAnimation;
  3. 把CAAnimation添加到想要动画的CALayer上。

下面就依照这3个步骤逐步实现我们的进度条。

创建动画Path、CALayer

iOS中画路径最简单的就是用UIBezierPath实现(本文只需要画一条线),因为要实现进度条所以layer最好选用CAShapeLayer(因为CAShapeLayer有个strokeStart和strokeEnd属性非常方便用作进度条动画),再者进度条需要有前景色和背景色所以需要创建2个CAShapeLayer,相关伪代码如下:

@implementation NFPProgressView
{
    //Layer
    CAShapeLayer *progressLayer;
    //backgroundLayer
    CAShapeLayer *backgroundLayer;
    UIBezierPath *progressPath;
}
- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if(self)
    {
        //Path
        progressPath = [UIBezierPath bezierPath];
        [progressPath moveToPoint:CGPointMake(PROGRESSHEIGHT/2,frame.size.height/2)];
        [progressPath addLineToPoint:CGPointMake(frame.size.width-PROGRESSHEIGHT/2,frame.size.height/2)];
        //Layer
        progressLayer = [CAShapeLayer layer];
        progressLayer.path = progressPath.CGPath;
        progressLayer.lineWidth = PROGRESSHEIGHT;
        progressLayer.lineCap = kCALineCapRound;
        progressLayer.strokeColor = [UIColor redColor].CGColor;
        backgroundLayer = [CAShapeLayer layer];
        backgroundLayer.path = progressPath.CGPath;
        backgroundLayer.strokeColor = [UIColor greenColor].CGColor;
        backgroundLayer.lineWidth = PROGRESSHEIGHT;
        backgroundLayer.lineCap = kCALineCapRound;
        [self.layer addSublayer:backgroundLayer];
        [self.layer addSublayer:progressLayer];
        self.progress = 0.0;
    }
    return self;
}

创建合适的CAAnimation

因进度条动画只有2帧(start、end)所以选用CABasicAnimation,创建时KeyPath设置为“strokeEnd”,创建动画的animationWithKeyPath:方法其本质上是KVO,也就是它会监听KeyPath的变化。至于KeyPath可以设置为哪些属性,CALayer中那些描述为Animatable的属性均可以(当然我们还可以自定义,但需要实现一系列的方法,needsDisplayForKey:、display之类的),比如path、lineWidth。以下是创建CAAnimation的伪代码:

CABasicAnimation *progressAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
progressAnimation.duration = 0.5f;

把CAAnimation添加到想要动画的CALayer上

这一步非常简单,只需把之前创建好的CAAnimation添加到之前创建好的CALayer上即可,伪代码如下:

[progressLayer addAnimation:progressAnimation forKey:@"progress"];

扫尾工作

到这一步时进度条主要的功能就已实现了,就剩下进度条前景色、背景色的设置这类属性的设置了,关于这些属性的设置只需要重写setter方法即可,伪代码如下:
@interface NFPProgressView : UIView
@property(nonatomic,strong) UIColor tintColor;
@property(nonatomic,strong) UIColor
trackColor;
@end

@implementation NFPProgressView
- (void)setTintColor:(UIColor *)tintColor
{
    progressLayer.strokeColor = tintColor.CGColor;
}

- (void)setTrackColor:(UIColor *)trackColor
{
    backgroundLayer.strokeColor = trackColor.CGColor;
}
@end

Demo效果

本文完整代码github地址NFPProgressView

最终的Demo效果如下:

Progress