Quartz 2D 下载进度按钮绘制

1、绘制下载进度按钮

  • 具体实现代码见 GitHub 源码 QExtension

  • QProgressButton.h

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    @interface QProgressButton : UIButton

    /// 进度值,范围 0 ~ 1
    @property (nonatomic, assign) CGFloat progress;

    /// 进度终止状态标题,一旦设置了此标题进度条就会停止
    @property (nonatomic, strong) NSString *stopTitle;

    /**
    * 创建带进度条的按钮
    *
    * @param frame 按钮的 frame 值
    * @param title 进按钮的标题
    * @param lineWidth 进度条的线宽,default is 2
    * @param lineColor 进度条线的颜色,default is greenColor
    * @param textColor 进度值的颜色,default is blackColor
    * @param backColor 按钮的背景颜色,default is clearColor
    * @param isRound 按钮是否显示为圆形,default is YES
    *
    * @return 带进度条的按钮
    */
    + (instancetype)q_progressButtonWithFrame:(CGRect)frame
    title:(NSString *)title
    lineWidth:(CGFloat)lineWidth
    lineColor:(nullable UIColor *)lineColor
    textColor:(nullable UIColor *)textColor
    backColor:(nullable UIColor *)backColor
    isRound:(BOOL)isRound;

    @end
  • QProgressButton.m

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    @interface QProgressButton ()

    /// 进度条的线宽
    @property (nonatomic, assign) CGFloat lineWidth;

    /// 进度条线的颜色
    @property (nonatomic, strong) UIColor *lineColor;

    /// 按钮的背景颜色
    @property (nonatomic, strong) UIColor *backColor;

    /// 按钮是否显示为圆形
    @property (nonatomic, assign, getter=isRound) BOOL round;

    @end

    @implementation QProgressButton

    /// 创建带进度条的按钮
    + (instancetype)q_progressButtonWithFrame:(CGRect)frame
    title:(NSString *)title
    lineWidth:(CGFloat)lineWidth
    lineColor:(nullable UIColor *)lineColor
    textColor:(nullable UIColor *)textColor
    backColor:(nullable UIColor *)backColor
    isRound:(BOOL)isRound {

    QProgressButton *progressButton = [[self alloc] init];

    progressButton.lineWidth = lineWidth ? : 2;
    progressButton.lineColor = lineColor ? : [UIColor colorWithRed:76/255.0 green:217/255.0 blue:100/255.0 alpha:1.0];
    progressButton.backColor = backColor ? : [UIColor clearColor];
    progressButton.round = isRound;

    // 设置按钮的实际 frame
    if (isRound) {
    CGRect tmpFrame = frame;
    tmpFrame.origin.y = frame.origin.y - (frame.size.width - frame.size.height) * 0.5;
    tmpFrame.size.height = frame.size.width;
    progressButton.frame = tmpFrame;
    } else {
    progressButton.frame = frame;
    }

    // 设置显示的标题和颜色
    [progressButton setTitle:title forState:UIControlStateNormal];
    [progressButton setTitleColor:(textColor ? : [UIColor blackColor]) forState:UIControlStateNormal];

    return progressButton;
    }

    /// 绘制进度条
    - (void)drawRect:(CGRect)rect {

    // 设置按钮圆角
    self.layer.masksToBounds = YES;
    self.layer.cornerRadius = rect.size.height * 0.5;

    // 绘制按钮的背景颜色
    UIBezierPath *path = [UIBezierPath bezierPathWithRect:rect];
    [self.backColor set];
    [path fill];

    // 设置进度终止时显示的内容
    if (self.stopTitle) {

    // 设置下载完成后的标题
    [self setTitle:self.stopTitle forState:UIControlStateNormal];
    return;
    }

    if (self.progress <= 0) {
    return;
    }

    // 清除按钮背景图片
    [self setBackgroundImage:nil forState:UIControlStateNormal];

    // 设置进度值
    [self setTitle:[NSString stringWithFormat:@"%.2f%%", self.progress * 100] forState:UIControlStateNormal];

    if (self.isRound) {

    CGPoint center = CGPointMake(rect.size.height * 0.5, rect.size.height * 0.5);
    CGFloat radius = (rect.size.height - self.lineWidth) * 0.5;
    CGFloat startA = - M_PI_2;
    CGFloat endA = startA + self.progress * 2 * M_PI;

    // 绘制进度条背景
    path = [UIBezierPath bezierPathWithArcCenter:center
    radius:radius
    startAngle:0
    endAngle:2 * M_PI
    clockwise:YES];
    [[[UIColor lightGrayColor] colorWithAlphaComponent:0.5] set];
    path.lineWidth = self.lineWidth;
    [path stroke];

    // 绘制进度条
    path = [UIBezierPath bezierPathWithArcCenter:center
    radius:radius
    startAngle:startA
    endAngle:endA
    clockwise:YES];
    path.lineWidth = self.lineWidth;
    path.lineCapStyle = kCGLineCapRound;
    [self.lineColor set];
    [path stroke];

    } else {

    CGFloat w = self.progress * rect.size.width;
    CGFloat h = rect.size.height;

    // 绘制进度条背景
    path = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, rect.size.width, rect.size.height)];
    [[[UIColor lightGrayColor] colorWithAlphaComponent:0.5] set];
    [path fill];

    // 绘制进度条
    path = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, w, h)];
    [self.lineColor set];
    [path fill];
    }
    }

    /// 设置进度值
    - (void)setProgress:(CGFloat)progress {

    _progress = progress;

    [self setNeedsDisplay];
    }

    /// 设置进度终止状态标题
    - (void)setStopTitle:(NSString *)stopTitle {

    _stopTitle = stopTitle;

    [self setNeedsDisplay];
    }

    @end
  • ViewController.m

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    // 创建进度按钮
    QProgressButton *progressButton = [QProgressButton q_progressButtonWithFrame:CGRectMake(100, 100, 100, 50)
    title:@"开始下载"
    lineWidth:10
    lineColor:[UIColor blueColor]
    textColor:[UIColor redColor]
    backColor:[UIColor yellowColor]
    isRound:YES];

    // 设置按钮点击事件
    [progressButton addTarget:self action:@selector(progressUpdate:) forControlEvents:UIControlEventTouchUpInside];

    // 将按钮添加到当前控件显示
    [self.view addSubview:progressButton];

    // 设置按钮的进度值
    self.progressButton.progress = progress;

    // 设置按钮的进度终止标题,一旦设置了此标题进度条就会停止
    self.progressButton.stopTitle = @"下载完成";
  • 效果

文章目录
  1. 1. 1、绘制下载进度按钮
隐藏目录