2013-05-11 3 views
6

Я работаю над круговым индикатором прогресса для просмотра достижений в игровом центре, и у меня есть вид «попадания в стену». Я борюсь с этим более двух часов и до сих пор не могу заставить его работать.Использование круговой индикатор выполнения с замаскированным изображением?

Дело в том, что мне нужен круговой индикатор выполнения, где я мог бы установить (по крайней мере) образ дорожки (заполнить). Потому что мой прогресс заполняется радугой, как градиент, и я не могу достичь тех же результатов, используя только код.

Я возился с CALayers и методом drawRect, однако я не был успешным. Не могли бы вы дать мне небольшое руководство?

Вот примеры круговых баров прогресса: https://github.com/donnellyk/KDGoalBar https://github.com/danielamitay/DACircularProgress

мне просто нужна заливка быть обрезанное изображение в зависимости от прогресса. Если бы вы могли даже сделать его работу, что прогресс будет анимированный, это было бы действительно здорово, но я не нуждаюсь в помощи с этим :)

Спасибо, Ник

+0

Так это маскирование или рисование «радуги», как градиент, который останавливает вас?Или он объединяет две части? –

+0

Возможно, я описал это неясно, извините за это - я не хочу рисовать градиент, у меня очень крутая заливка градиента для индикатора выполнения, сделанного в Photoshop, и мне просто нужно ее замаскировать, так что это заполнить индикатор выполнения. Ты знаешь, что я имею в виду? :) –

ответ

23

Вы в основном просто нужно построить путь который определяет заполняемую область (например, используя CGPathAddArc), закрепите графический контекст на этом пути, используя CGContextClip, а затем просто нарисуйте свое изображение.

Вот пример метода drawRect: вы могли бы использовать в настраиваемое представление:

- (void)drawRect:(CGRect)rect 
{ 
    CGContextRef ctx = UIGraphicsGetCurrentContext(); 

    CGFloat progress = 0.7f; //This would be a property of your view 
    CGFloat innerRadiusRatio = 0.5f; //Adjust as needed 

    //Construct the path: 
    CGMutablePathRef path = CGPathCreateMutable(); 
    CGFloat startAngle = -M_PI_2; 
    CGFloat endAngle = -M_PI_2 + MIN(1.0f, progress) * M_PI * 2; 
    CGFloat outerRadius = CGRectGetWidth(self.bounds) * 0.5f - 1.0f; 
    CGFloat innerRadius = outerRadius * innerRadiusRatio; 
    CGPoint center = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds)); 
    CGPathAddArc(path, NULL, center.x, center.y, innerRadius, startAngle, endAngle, false); 
    CGPathAddArc(path, NULL, center.x, center.y, outerRadius, endAngle, startAngle, true); 
    CGPathCloseSubpath(path); 
    CGContextAddPath(ctx, path); 
    CGPathRelease(path); 

    //Draw the image, clipped to the path: 
    CGContextSaveGState(ctx); 
    CGContextClip(ctx); 
    CGContextDrawImage(ctx, self.bounds, [[UIImage imageNamed:@"RadialProgressFill"] CGImage]); 
    CGContextRestoreGState(ctx); 
} 

Чтобы сохранить его простым, у меня жестко закодированные несколько вещей - вы, очевидно, нужно добавить свойство для progress и вызовите setNeedsDisplay в сеттере. Это также предполагает, что у вас есть изображение с именем RadialProgressFill в вашем проекте.

Вот пример того, что это будет примерно выглядеть следующим образом:

Screenshot

Я надеюсь, что вы лучше выглядящий фоновое изображение. ;)

+0

Надеюсь, что таких людей будет больше, чем вы, - это намного больше, чем я ожидал! Большое спасибо за ваш подробный ответ - я вознаградил вас :) –

+0

@DominikHadl Как и где этот метод - (void) drawRect: (CGRect) rect –

+0

@omz это действительно полезно .. :) –

0

Решение, которое предложил omz, работало лагги, когда я пытался одушевить собственность, поэтому я продолжал искать. Нашел отличное решение - для использования каркаса и обертки кварцевого сердечника, называемого CADisplayLink. «Этот класс специально для анимации, где„ваши данные весьма вероятно, изменится в каждом кадре“. Он пытается отправить сообщение на цель каждый раз, когда что-то перерисовывается на экране» Source

И в library, что работа так.

Редактировать: Но есть более эффективное решение. Для анимации маски, которая применяется к слою с изображением. Я не знаю, почему я этого не делал с самого начала. CABasicAnimation работает быстрее, чем любой пользовательский чертеж. Вот моя реализация:

class ProgressBar: UIView { 
    var imageView:UIImageView! 

    var maskLayer: CAShapeLayer! 
    var currentValue: CGFloat = 1 

    override init(frame: CGRect) { 
     super.init(frame: frame) 
     updateUI() 
    } 

    required init?(coder aDecoder: NSCoder) { 
     super.init(coder: aDecoder) 
     updateUI() 
    } 

    func updateUI(){ 
     makeGradient() 
     setUpMask() 
    } 

    func animateCircle(strokeEnd: CGFloat) { 
     let oldStrokeEnd = maskLayer.strokeEnd 
     maskLayer.strokeEnd = strokeEnd 

     //override strokeEnd implicit animation 
     let animation = CABasicAnimation(keyPath: "strokeEnd") 
     animation.duration = 0.5 
     animation.fromValue = oldStrokeEnd 
     animation.toValue = strokeEnd 
     animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) 
     maskLayer.add(animation, forKey: "animateCircle") 

     currentValue = strokeEnd 
    } 

    func setUpMask(){ 

     let circlePath = UIBezierPath(arcCenter: CGPoint(x: frame.size.width/2.0, y: frame.size.height/2.0), 
             radius: (frame.size.width - 10)/2, 
             startAngle: -CGFloat.pi/2, 
             endAngle: CGFloat.pi*1.5, 
             clockwise: true) 

     maskLayer = CAShapeLayer() 
     maskLayer.path = circlePath.cgPath 
     maskLayer.fillColor = UIColor.clear.cgColor 
     maskLayer.strokeColor = UIColor.red.cgColor 
     maskLayer.lineWidth = 8.0; 
     maskLayer.strokeEnd = currentValue 
     maskLayer.lineCap = "round" 
     imageView.layer.mask = maskLayer 
    } 

    func makeGradient(){ 
     imageView = UIImageView(image: UIImage(named: "gradientImage")) 
     imageView.frame = bounds 
     imageView.contentMode = .scaleAspectFill 
     addSubview(imageView) 
    } 

} 

Кстати, если вы хотите, чтобы стать лучше в анимации, я предлагаю большую книгу «IOS Core Animation: Advanced Techniques книги Ник Локвуд»

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