Как создать круговой индикатор прогресса для таймера обратного отсчета

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

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

Я рассматривал раскраску здесь https://developer.apple.com/library/prerelease/ios/documentation/GraphicsAnimation/Conceptual/SpriteKit_PG/Sprites/Sprites.html#//apple_ref/doc/uid/TP40013043-CH9, но не может видеть способ раскраски раздела спрайта, кажется, что весь спрайт будет изменен.

Кто-нибудь знает, может ли раскрасить вариант здесь, или есть способ уменьшить память, используемую атласом изображения?

благодаря

Вы можете сделать это, используя CAShapeLayer и анимировать конец штриха следующим образом:

обновление Xcode 9 • Swift 4

определить оставшееся время

let timeLeftShapeLayer = CAShapeLayer() let bgShapeLayer = CAShapeLayer() var timeLeft: TimeInterval = 60 var endTime: Date? var timeLabel = UILabel() var timer = Timer() // here you create your basic animation object to animate the strokeEnd let strokeIt = CABasicAnimation(keyPath: "strokeEnd") 

определить способ создания UIBezierPath

startAngle at -90˚ и endAngle 270

 func drawBgShape() { bgShapeLayer.path = UIBezierPath(arcCenter: CGPoint(x: view.frame.midX , y: view.frame.midY), radius: 100, startAngle: -90.degreesToRadians, endAngle: 270.degreesToRadians, clockwise: true).cgPath bgShapeLayer.strokeColor = UIColor.white.cgColor bgShapeLayer.fillColor = UIColor.clear.cgColor bgShapeLayer.lineWidth = 15 view.layer.addSublayer(bgShapeLayer) } func drawTimeLeftShape() { timeLeftShapeLayer.path = UIBezierPath(arcCenter: CGPoint(x: view.frame.midX , y: view.frame.midY), radius: 100, startAngle: -90.degreesToRadians, endAngle: 270.degreesToRadians, clockwise: true).cgPath timeLeftShapeLayer.strokeColor = UIColor.red.cgColor timeLeftShapeLayer.fillColor = UIColor.clear.cgColor timeLeftShapeLayer.lineWidth = 15 view.layer.addSublayer(timeLeftShapeLayer) } 

добавить свою метку

 func addTimeLabel() { timeLabel = UILabel(frame: CGRect(x: view.frame.midX-50 ,y: view.frame.midY-25, width: 100, height: 50)) timeLabel.textAlignment = .center timeLabel.text = timeLeft.time view.addSubview(timeLabel) } 

в viewDidload установите endTime и добавьте CAShapeLayer к вашему представлению:

 override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = UIColor(white: 0.94, alpha: 1.0) drawBgShape() drawTimeLeftShape() addTimeLabel() // here you define the fromValue, toValue and duration of your animation strokeIt.fromValue = 0 strokeIt.toValue = 1 strokeIt.duration = 60 // add the animation to your timeLeftShapeLayer timeLeftShapeLayer.add(strokeIt, forKey: nil) // define the future end time by adding the timeLeft to now Date() endTime = Date().addingTimeInterval(timeLeft) timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(updateTime), userInfo: nil, repeats: true) } 

при обновлении времени

 @objc func updateTime() { if timeLeft > 0 { timeLeft = endTime?.timeIntervalSinceNow ?? 0 timeLabel.text = timeLeft.time } else { timeLabel.text = "00:00" timer.invalidate() } } 

вы можете использовать это расширение для преобразования градусов в радианы и отображения времени

 extension TimeInterval { var time: String { return String(format:"%02d:%02d", Int(self/60), Int(ceil(truncatingRemainder(dividingBy: 60))) ) } } extension Int { var degreesToRadians : CGFloat { return CGFloat(self) * .pi / 180 } } 

Пример проекта

Большая часть кода и ответ! Просто подумал, что я предлагаю следующее. Я получал время, показанное как 1:00, а затем 0:60, которое, я думаю, может быть связано с частью кода «ceil».

Я изменил его на следующее (также желая, чтобы времена менее 60 отображались по-разному), и, похоже, они удалили перекрытие времен.

Для чего это стоит …

 extension NSTimeInterval { var time:String { if self < 60 { return String(format: "%02d", Int(floor(self%60))) } else { return String(format: "%01d:%02d", Int(self/60), Int(floor(self%60))) } } }