我想创建一个圆形进度条,如下所示:

我如何使用 Objective-C 和 Cocoa 来做到这一点?
我是如何开始创建 UIView 并编辑 drawRect 的,但我有点迷失了。任何帮助将不胜感激。
谢谢!
我想创建一个圆形进度条,如下所示:

我如何使用 Objective-C 和 Cocoa 来做到这一点?
我是如何开始创建 UIView 并编辑 drawRect 的,但我有点迷失了。任何帮助将不胜感激。
谢谢!
基本概念是利用UIBezierPath课程来发挥自己的优势。您可以绘制弧线,从而达到您所追求的效果。我只有半个小时左右的时间来解决这个问题,但我的尝试在下面。
非常简陋,它只是在路径上使用笔画,但我们开始了。您可以根据您的确切需要更改/修改它,但是执行弧倒计时的逻辑将非常相似。
在视图类中:
@interface TestView () {
    CGFloat startAngle;
    CGFloat endAngle;
}
@end
@implementation TestView
- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
        self.backgroundColor = [UIColor whiteColor];
        // Determine our start and stop angles for the arc (in radians)
        startAngle = M_PI * 1.5;
        endAngle = startAngle + (M_PI * 2);
    }
    return self;
}
- (void)drawRect:(CGRect)rect
{
    // Display our percentage as a string
    NSString* textContent = [NSString stringWithFormat:@"%d", self.percent];
    UIBezierPath* bezierPath = [UIBezierPath bezierPath];
    // Create our arc, with the correct angles
    [bezierPath addArcWithCenter:CGPointMake(rect.size.width / 2, rect.size.height / 2) 
                          radius:130 
                      startAngle:startAngle
                        endAngle:(endAngle - startAngle) * (_percent / 100.0) + startAngle
                       clockwise:YES];
    // Set the display for the path, and stroke it
    bezierPath.lineWidth = 20;
    [[UIColor redColor] setStroke];
    [bezierPath stroke];
    // Text Drawing
    CGRect textRect = CGRectMake((rect.size.width / 2.0) - 71/2.0, (rect.size.height / 2.0) - 45/2.0, 71, 45);
    [[UIColor blackColor] setFill];
    [textContent drawInRect: textRect withFont: [UIFont fontWithName: @"Helvetica-Bold" size: 42.5] lineBreakMode: NSLineBreakByWordWrapping alignment: NSTextAlignmentCenter];
}
对于视图控制器:
@interface ViewController () {    
    TestView* m_testView;
    NSTimer* m_timer;
}
@end
- (void)viewDidLoad
{
    // Init our view
    [super viewDidLoad];
    m_testView = [[TestView alloc] initWithFrame:self.view.bounds];
    m_testView.percent = 100;
    [self.view addSubview:m_testView];
}
- (void)viewDidAppear:(BOOL)animated
{
    // Kick off a timer to count it down
    m_timer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(decrementSpin) userInfo:nil repeats:YES];
}
- (void)decrementSpin
{
    // If we can decrement our percentage, do so, and redraw the view
    if (m_testView.percent > 0) {
        m_testView.percent = m_testView.percent - 1;
        [m_testView setNeedsDisplay];
    }
    else {
       [m_timer invalidate];
       m_timer = nil;
    }
}
    我的魔术数字示例(为了更好地理解):
  CAShapeLayer *circle = [CAShapeLayer layer];
  circle.path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(29, 29) radius:27 startAngle:-M_PI_2 endAngle:2 * M_PI - M_PI_2 clockwise:YES].CGPath;
  circle.fillColor = [UIColor clearColor].CGColor;
  circle.strokeColor = [UIColor greenColor].CGColor;
  circle.lineWidth = 4;
  CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
  animation.duration = 10;
  animation.removedOnCompletion = NO;
  animation.fromValue = @(0);
  animation.toValue = @(1);
  animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
  [circle addAnimation:animation forKey:@"drawCircleAnimation"];
  [imageCircle.layer.sublayers makeObjectsPerformSelector:@selector(removeFromSuperlayer)];
  [imageCircle.layer addSublayer:circle];
    我已经为 iOS 实现了一个简单的库。它基于 UILabel 类,因此您可以在进度条中显示您想要的任何内容,但您也可以将其留空。
初始化后,您只有一行代码来设置进度:
[_myProgressLabel setProgress:(50/100))];
该库被命名为KAProgressLabel
你可以查看我的 lib MBCircularProgressBar
对于Swift使用这个,
let circle = UIView(frame: CGRectMake(0,0, 100, 100))
circle.layoutIfNeeded()
let centerPoint = CGPoint (x: circle.bounds.width / 2, y: circle.bounds.width / 2)
let circleRadius : CGFloat = circle.bounds.width / 2 * 0.83
var circlePath = UIBezierPath(arcCenter: centerPoint, radius: circleRadius, startAngle: CGFloat(-0.5 * M_PI), endAngle: CGFloat(1.5 * M_PI), clockwise: true    )
let progressCircle = CAShapeLayer()
progressCircle.path = circlePath.CGPath
progressCircle.strokeColor = UIColor.greenColor().CGColor
progressCircle.fillColor = UIColor.clearColor().CGColor
progressCircle.lineWidth = 1.5
progressCircle.strokeStart = 0
progressCircle.strokeEnd = 0.22
circle.layer.addSublayer(progressCircle)
self.view.addSubview(circle)
参考:见这里。
Swift 3 使用这个,
CAShapeLayer with Animation : 继续 Zaid Pathan ans。
    let circle = UIView(frame: CGRect(x: 100, y: 100, width: 100, height: 100))
    circle.layoutIfNeeded()
    var progressCircle = CAShapeLayer()
    let centerPoint = CGPoint (x: circle.bounds.width / 2, y: circle.bounds.width / 2)
    let circleRadius : CGFloat = circle.bounds.width / 2 * 0.83
    let circlePath = UIBezierPath(arcCenter: centerPoint, radius: circleRadius, startAngle: CGFloat(-0.5 * M_PI), endAngle: CGFloat(1.5 * M_PI), clockwise: true    )
    progressCircle = CAShapeLayer ()
    progressCircle.path = circlePath.cgPath
    progressCircle.strokeColor = UIColor.green.cgColor
    progressCircle.fillColor = UIColor.clear.cgColor
    progressCircle.lineWidth = 2.5
    progressCircle.strokeStart = 0
    progressCircle.strokeEnd = 1.0
     circle.layer.addSublayer(progressCircle)
    let animation = CABasicAnimation(keyPath: "strokeEnd")
    animation.fromValue = 0
    animation.toValue = 1.0
    animation.duration = 5.0
    animation.fillMode = kCAFillModeForwards
    animation.isRemovedOnCompletion = false
     progressCircle.add(animation, forKey: "ani")
    self.view.addSubview(circle)
    这是一个Swift示例,说明如何制作一个简单的、不封闭的(为长数字留出空间)带有圆角和动画的圆形进度条。
open_circular_progress_bar.jpg
func drawBackRingFittingInsideView(lineWidth: CGFloat, lineColor: UIColor) {
    let halfSize:CGFloat = min( bounds.size.width/2, bounds.size.height/2)
    let desiredLineWidth:CGFloat = lineWidth
    let circle = CGFloat(Double.pi * 2)
    let startAngle = CGFloat(circle * 0.1)
    let endAngle = circle – startAngle
    let circlePath = UIBezierPath(
        arcCenter: CGPoint(x:halfSize, y:halfSize),
        radius: CGFloat( halfSize – (desiredLineWidth/2) ),
        startAngle: startAngle,
        endAngle: endAngle,
        clockwise: true)
    let shapeBackLayer = CAShapeLayer()
        shapeBackLayer.path = circlePath.cgPath
        shapeBackLayer.fillColor = UIColor.clear.cgColor
        shapeBackLayer.strokeColor = lineColor.cgColor
        shapeBackLayer.lineWidth = desiredLineWidth
        shapeBackLayer.lineCap = .round
    layer.addSublayer(shapeBackLayer)
}
以及动画功能。
 func animateCircle(duration: TimeInterval) {
    let animation = CABasicAnimation(keyPath: “strokeEnd”)
    animation.duration = duration
    animation.fromValue = 0
    animation.toValue = 1
    animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear)        
    shapeLayer.strokeEnd = 1.0
    shapeLayer.add(animation, forKey: “animateCircle”)
}
有一个很好的博客例子。