Creating progress circle as WKInterfaceImage in Watch App

user3746428 picture user3746428 · Nov 22, 2014 · Viewed 10k times · Source

I am trying to create a progress circle for the Apple Watch version of my app. I know that we aren't able to use UIViews (which would make things so much easier!) so I am looking for alternatives.

Basically, I would like to create one of these prototypes:

enter image description here

The way I was hoping to do things was to add the background layers as a normal WKInterfaceImage and then the progress arrow/line on top as a WKInterfaceImage that rotates around the circle based on the percentage calculated.

I have the percentage calculated so basically, what I am looking for is some help with the math code for rotating the arrow.

Does anyone know if this is possible, and could anyone help me out if so? I'm not trying to update the circle while the app is running; it just needs to update when the Watch App launches to correspond with the iOS version.

Thanks!

Answer

AKM picture AKM · Aug 1, 2017

As of watchOS 3 it is possible to use SpriteKit.

SKShapeNode can draw shapes, so it is possible to create radial rings.

  1. Add a WKInterfaceSKScene to your interface controller in storyboard and hook it up through an outlet.
  2. Set it up in the awake method of the interface controller

    override func awake(withContext context: Any?) {
       super.awake(withContext: context)
       scene = SKScene(size: CGSize(width: 100, height: 100))
       scene.scaleMode = .aspectFit
       interfaceScene.presentScene(scene)
    }
    
  3. Create a shape node and add it to the scene

    let fraction: CGFloat = 0.75
    let path = UIBezierPath(arcCenter: .zero,
                             radius: 50,
                             startAngle: 0,
                             endAngle: 2 * .pi * fraction,
                             clockwise: true).cgPath
    
    let shapeNode = SKShapeNode(path: path)
    shapeNode.strokeColor = .blue
    shapeNode.fillColor = .clear
    shapeNode.lineWidth = 4
    shapeNode.lineCap = .round
    shapeNode.position = CGPoint(x: scene.size.width / 2, y: scene.size.height / 2)
    scene.addChild(shapeNode)
    

Example