美文网首页
渐变直线/圆形进度条实现

渐变直线/圆形进度条实现

作者: Junetaurus | 来源:发表于2017-12-05 11:58 被阅读0次
    ProgressBar.gif

    直线进度条

    • 结构



      第一部分:背景 view
      第二部分:填充 view,用 CAGradientLayer 填充

    • 核心代码
    /*
     CAGradientLayer 渐变色,目前只有 kCAGradientLayerAxial 一个选项,即呈线性变化
     startPoint、endPoint:分别表示渐变层的起始位置和终止位置,这两个点被定义在一个单元坐标空间,[0,0] 表示左上角位置,[1,1] 表示右下角位置,默认值分别是 [0.5,0] and [0.5,1]
     colors:颜色数组,定义渐变层的各个颜色
     locations: 可选的 NSNumber 数组,决定每个渐变颜色的终止位置,这些值必须是递增的,数组的长度和 colors 的长度最好一致
     */
    - (void)gradientColorForView:(UIView *)view {
        CAGradientLayer *layer = [CAGradientLayer layer];
        layer.startPoint = CGPointMake(0, 0);
        layer.endPoint = CGPointMake(1, 0);
        layer.colors = [NSArray arrayWithObjects:(__bridge id)[UIColor colorWithRed:24/255.0 green:201/255.0 blue:255/255.0 alpha:1].CGColor,(__bridge id)[UIColor colorWithRed:0/255.0 green:147/255.0 blue:255/255.0 alpha:1].CGColor, nil];
        layer.locations = @[@0,@1];
        [view.layer insertSublayer:layer atIndex:0];
    }
    

    圆形进度条

    • 首先画个圆,
      这里就需要用到 UIBezierPathCAShapeLayer 了。
    @property (nonatomic, strong) UIBezierPath *bezierPath;
    @property (nonatomic, strong) CAShapeLayer *inCAShapeLayer;
    
    self.bezierPath = [UIBezierPath bezierPath];
    
    self.inCAShapeLayer = [CAShapeLayer layer];
    self.inCAShapeLayer.lineWidth = self.lineWidth/2;
    self.inCAShapeLayer.strokeColor = [UIColor colorWithRed:219/255.0 green:219/255.0 blue:219/255.0 alpha:1].CGColor;
    self.inCAShapeLayer.fillColor = [UIColor whiteColor].CGColor;
    self.inCAShapeLayer.lineCap = kCALineCapRound
    [self.layer addSublayer:self.inCAShapeLayer];
    
    [self.bezierPath appendPath:[UIBezierPath bezierPathWithArcCenter:CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2) radius:self.bounds.size.width/2 - self.lineWidth startAngle:0 endAngle:M_PI*2 clockwise:YES]];
    self.inCAShapeLayer.path = self.bezierPath.CGPath;
    
    效果图
    CAShapeLayer 是 CALayer 的子类,比 CALayer 更灵活,可以画出各种图形。fillColor 代表这个 Layer 的填充色,strokeColor 代表这个 Layer 的边框色。
    UIBezierPath 贝塞尔曲线,可以用来构建一段弧线,你可以用任意条弧线来组成你想要的形状。
    • 渐变填充色
      渐变色就需要上面用到过的 CAShapeLayer 了。
      先添加左边的:
    @property (nonatomic, strong) CALayer *caLayer;
    @property (nonatomic, strong) CAGradientLayer *leftGradientLayer;
    
    self.caLayer = [CALayer layer];
    [self.layer addSublayer:self.caLayer];
    
    self.leftGradientLayer = [CAGradientLayer layer];
    self.leftGradientLayer.startPoint = CGPointMake(0, 1);
    self.leftGradientLayer.endPoint = CGPointMake(0, 0);
    self.leftGradientLayer.colors = [NSArray arrayWithObjects:(__bridge id)[UIColor colorWithRed:237/255.0 green:199/255.0 blue:109/255.0 alpha:1].CGColor,(__bridge id)[UIColor colorWithRed:219.5/255.0 green:181/255.0 blue:100.5/255.0 alpha:1].CGColor, nil];
    [self.caLayer addSublayer:self.leftGradientLayer];
    
    效果图

    在添加右边的:

    @property (nonatomic, strong) CAGradientLayer *rightGradientLayer;
    
    self.rightGradientLayer = [CAGradientLayer layer];
    self.rightGradientLayer.startPoint = CGPointMake(0, 0);
    self.rightGradientLayer.endPoint = CGPointMake(0, 1);
    self.rightGradientLayer.colors = [NSArray arrayWithObjects:(__bridge id)[UIColor colorWithRed:219.5/255.0 green:181/255.0 blue:100.5/255.0 alpha:1].CGColor,(__bridge id)[UIColor colorWithRed:202/255.0 green:163/255.0 blue:92/255.0 alpha:1].CGColor, nil];
    [self.caLayer addSublayer:self.rightGradientLayer];
    
    效果图
    然后为self.caLayer``setMask设置一个遮罩,遮罩范围外面的就不会在显示了。
    @property (nonatomic, strong) CAShapeLayer *outCAShapeLayer;
    
    self.outCAShapeLayer = [CAShapeLayer layer];
    self.outCAShapeLayer.lineWidth = self.lineWidth;
    self.outCAShapeLayer.fillColor = [UIColor clearColor].CGColor;
    self.outCAShapeLayer.strokeColor = [UIColor whiteColor].CGColor;
    self.outCAShapeLayer.lineCap = kCALineCapRound;
    
    [self.caLayer setMask:self.outCAShapeLayer];
    
    [self.bezierPath appendPath:[UIBezierPath bezierPathWithArcCenter:CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2) radius:self.bounds.size.width/2 - self.lineWidth startAngle:self.startAngle endAngle:self.endAngle clockwise:YES]];
    self.outCAShapeLayer.path = self.bezierPath.CGPath;
    
    效果图
    • 添加动画
    @property (nonatomic, strong) CABasicAnimation *caAnimation;
    
    - (CABasicAnimation *)caAnimation {
        if (!_caAnimation) {
            _caAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
            _caAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
            _caAnimation.fromValue = [NSNumber numberWithFloat:0.0f];
            _caAnimation.toValue = [NSNumber numberWithFloat:1.0f];
        }
        return _caAnimation;
    }
    
    - (void)setProgress:(CGFloat)progressValue withValueMax:(CGFloat)progressMaxValue {
        if (progressValue > progressMaxValue) progressValue = progressMaxValue;
        
        CGFloat allAngle = (progressValue/progressMaxValue) * M_PI * 2;
        //弧长L=αr 其中 α 为圆心角的弧度数,r 为圆的半径  α = L/r
        self.startAngle = M_PI_2 + (self.lineWidth/2)/(self.bounds.size.width/2 - self.lineWidth);
        self.endAngle = allAngle + self.startAngle;
        
        [self.outCAShapeLayer removeAllAnimations];
        if (progressMaxValue) {
            self.caAnimation.duration = (progressValue/progressMaxValue)*3.0;
            //添加动画
            [self.outCAShapeLayer addAnimation:self.caAnimation forKey:@"strokeEndAnimation"];
        }
        /*
         -setNeedsLayout 方法:标记为需要重新布局,异步调用 layoutIfNeeded 刷新布局,不立即刷新,但 layoutSubviews 一定会被调用
         -layoutIfNeeded 方法:如果,有需要刷新的标记,立即调用 layoutSubviews 进行布局(如果没有标记,不会调用 layoutSubviews)
         如果要立即刷新,要先调用 [view setNeedsLayout],把标记设为需要布局,然后马上调用 [view layoutIfNeeded],实现布局。
         */
        [self setNeedsLayout];
    }
    

    完整的Demo下载

    相关文章

      网友评论

          本文标题:渐变直线/圆形进度条实现

          本文链接:https://www.haomeiwen.com/subject/xvhwbxtx.html