Вопрос по ios4, cocoa-touch, objective-c, ios6, ios5 – Круговые индикаторы выполнения в IOS

54

Я хочу создать круговой индикатор выполнения, как показано ниже:

Как я могу сделать это, используя Objective-C и какао?

Как я начал это делать, создавал UIView и редактировал drawRect, но я немного растерялся. Любая помощь будет принята с благодарностью.

Спасибо!

Сделай сам, не беспокойся. WDUK
@WDuk это должен быть низкий уровень, так как я уверен, что видел кого-то с менее чем 100 повторными публикациями изображений. Я только что проверил переполнение мета-стека, и они предполагают, что повторение 10 - это минимум для публикации изображений. Peter M
Только пользователи с достаточно высокой репутацией могут включать изображения, но не уверены, что 31 достаточно высоко WDUK
Кроме того, вы можете включить изображения в свой вопрос. Это спасает нас от перехода на другой сайт, чтобы посмотреть на них. Peter M

Ваш Ответ

6   ответов
68

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;
    }
}
@Siriss Вы пытались изменитьlineCapStyle на ?UIBezierPath WDUK
Спасибо! Да, я наконец понял это, просто забыл вернуться и обновить это. Siriss
Отличный пост, спасибо! Несколько замечаний для начинающих: <br /> -[self.view addSubview:m_webView]; конечно должно быть[self.view addSubview: m_testView]; - TestView.h должен выглядеть так: <бр /> #import @interface UICircle : UIView @property (nonatomic) double percent; @end Fynh
Отличный пример кода. Я смог создать именно то, что мне нужно, на основе этого образца. Спасибо!! Rickster
12
Конечно, просто скопируйте файлы Layer и View в ваш проект Mati Bot
Как заполнить полный индикатор выполнения? Shahbaz Akram
Есть ли способ добавить вашу библиотеку в проект Xcode без модуля? Спасибо Ilario
Доступен ли какой-либо делегат изменений прогресса? Я имею в виду, что можно дать 40 секунд, чтобы достичь полного значения прогресса 100, и если кто-то захочет что-то сделать, когда оно достигнет 60% Durai Amuthan.H
22

  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];
Как бы вы получили лидерство CGPoint, как он оживляет вокруг? whyoz
@whyoz, я использовал методbezierPathWithArcCenter это рисует дугу в центре! Darkngs
ну, я знаю это! Хаха яЯ пытаюсь получить больше информации от вас, если у вас есть идея, как это сделать, если я хочу отслеживать эту точку, когда она перемещается вокруг центра. Так что получитеточка отсчета" в форме CGPoint от startAngle 'первый пункт .. думал, что может быть быстрое свойство захватить .. whyoz
@UserDev, да, вы можете обновлять объект CAShapeLayer каждый раз, когда ваш прогресс будет изменен. Darkngs
5

Swift 3 используйте это,

CAShapeLayer с анимацией: продолжить с 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)
21

основаны на классе UILabel, так что вы можете отображать все, что вы хотите, внутри вашего индикатора выполнения, но вы также можете оставить его пустым.

После инициализации у вас есть только одна строка кода для установки прогресса:

[_myProgressLabel setProgress:(50/100))];

Библиотека названаKAProgressLabel

Спасибо, чтобы быть справедливым, есть еще один очень хороший:github.com/danielamitay/DACircularProgress Kirualex
Было бы очень хорошо, если бы вы могли использовать 2 изображения для круглого индикатора выполнения Daniel
12

Застриж использовать этот,

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)

Ссылка: см.Вот.

Похожие вопросы