2015-04-26 2 views
3

У меня есть UIView подкласса, который отображает круговую прогресс:UIView с пользовательским DrawRect и animateWithDuration

circular progress view

Скриншот выше показывает прогресс со значением 0.667.

Внутри моей реализации UIView подкласс в drawRect: метод Я рисую два круга - один для фона овальный (серый), второй для фактического прогресса овальный (синий). (Check out source code)

Работает так, как ожидалось, но не позволяет анимировать изменения прогресса. Я пытался найти решение, которое позволяет с помощью метода animateWithDuration:animations: класса UIView «S, как это:

MyCustomView *progressView = ... 
[UIView animateWithDuration:3 
       animations:^{ 
        progressView.progressValue = 1.f; 
       }]; 

Но я не был в состоянии сделать это воодушевляет тот путь.

Вы можете проверить исходный код в my GitHub repository.

Тем не менее, я нашел способ выполнить анимацию при изменении progressValue. Это не совсем то, что я хочу (все еще не работает с UIViewanimateWithDuration:animations:), и я не уверен, что это правильное направление. Он включает подклассификацию CALayer моего UIView. Вы можете проверить исходный код в том же репо, упомянутом выше, on custom_layer branch. Вот direct link до CALayer реализация подкласса подкласса.

Моего вопрос: Имея UIView подкласс, который рисует несколько фигур на основе пользовательских свойств (progressValue), можно сделать вид одушевляет с UIView «s animateWithDuration:animations: при изменении свойства представления (progressValue)?

UPDATE

Благодаря rounak's answer избавиться от рисования пользовательских форм в drawRect: метод и создал два отдельных CAShapeLayer с. Вместо того, чтобы рисовать новые фигуры каждый раз, когда меняются progressValue, я просто устанавливаю свойства strokeEnd для этих слоев, что дает тот же визуальный эффект, что и раньше, но должен работать лучше (check out source code).

Тогда я реализовал actionForLayer:forKey: метод (check out source code), который возвращает CABasicAnimation, которые должны анимировать strokeEnd когда progressValue изменения.

Однако я по-прежнему испытываю проблемы с анимацией:

__block NSDate *date = [NSDate date]; 
[UIView animateWithDuration:3 
       animations:^{ 
        self.progressView.progressValue = 1.f; 
       } 
       completion:^(BOOL finished1) { 
        NSLog(@"first animation completed in %f", [[NSDate date] timeIntervalSinceDate:date]); 
        date = [NSDate date]; 
        [UIView animateWithDuration:3 
             animations:^{ 
              self.progressView.progressValue = 0.f; 
             } 
             completion:^(BOOL finished2) { 
              NSLog(@"second animation completed in %f", [[NSDate date] timeIntervalSinceDate:date]); 
              [self animateProgress]; 
             }]; 
       }]; 

Моим круговой обзор прогресс одушевляет progressValue изменения и выполнение кода выше говорит, что каждая анимация занимает около 3 секунд. К сожалению, на экране вид анимации очень быстрый (анимация завершается в доли секунды).Вот как это выглядит:

enter image description here

Я не уверен, где проблема, но я заметил, что изменение в [CABasicAnimation animationWithKeyPath:@"strokeEnd"] Ключевой путь от strokeEnd к чему-то еще не дает никакого эффекта (анимация всегда выглядит одинаково).

Любые намеки на то, что мне не хватает здесь, будут оценены.

UPDATE 2

Я только заметил, что анимация на самом деле срабатывает этих двух линий в setProgressValue: сеттере:

self.progressOvalLayer.strokeEnd = MIN(1, MAX(0, progressValue)); 
self.backgroundOvalLayer.strokeEnd = MIN(1, MAX(0, 1 - progressValue)); 

(see on GitHub)

Это выглядит как моя реализация actionForLayer:forKey: не работает вообще, несмотря на выполнение (проверено с помощью brakepoint).

Интересно, что я делаю неправильно?

ОБНОВЛЕНИЕ - РЕШЕНИЕ НАЙДЕНО

Это произошло, что я пытался оживить основной слой моего UIView вместо пользовательских слоев, который содержит овальные формы. Мне нужно было исправить ошибку actionForLayer:(CALayer *)layer forKey:, чтобы она работала (check out fixed source code). Это решает мою проблему.

ответ

2

Я предлагаю вам сделать круговой ход с CAShapeLayer и использовать strokeStart, strokeEnd и fillColor свойства для достижения вашего эффекта. Вероятно, вам понадобятся две фигуры, одна над другой, но преимущество в этом подходе заключается в том, что свойства shapeLayer могут быть доступны с помощью CoreAnimation.

Кроме того, вы можете использовать повозку, запряженные вол, как это сделать анимацию в анимации блоков, а https://gist.github.com/nicklockwood/d374033b27c62662ac8d

+0

Спасибо за подсказки, я обновил свою реализацию и вопрос. К сожалению, я все еще не умею правильно выполнять анимацию. Пожалуйста, ознакомьтесь с моим обновленным вопросом. – Darrarski

Смежные вопросы